1#! /usr/bin/env perl 2# This file is dual-licensed, meaning that you can use it under your 3# choice of either of the following two licenses: 4# 5# Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved. 6# 7# Licensed under the Apache License 2.0 (the "License"). You can obtain 8# a copy in the file LICENSE in the source distribution or at 9# https://www.openssl.org/source/license.html 10# 11# or 12# 13# Copyright (c) 2023, Christoph Müllner <christoph.muellner@vrull.eu> 14# Copyright (c) 2023, Jerry Shih <jerry.shih@sifive.com> 15# Copyright (c) 2023, Phoebe Chen <phoebe.chen@sifive.com> 16# All rights reserved. 17# 18# Redistribution and use in source and binary forms, with or without 19# modification, are permitted provided that the following conditions 20# are met: 21# 1. Redistributions of source code must retain the above copyright 22# notice, this list of conditions and the following disclaimer. 23# 2. Redistributions in binary form must reproduce the above copyright 24# notice, this list of conditions and the following disclaimer in the 25# documentation and/or other materials provided with the distribution. 26# 27# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 39use strict; 40use warnings; 41 42# Set $have_stacktrace to 1 if we have Devel::StackTrace 43my $have_stacktrace = 0; 44if (eval {require Devel::StackTrace;1;}) { 45 $have_stacktrace = 1; 46} 47 48my @regs = map("x$_",(0..31)); 49# Mapping from the RISC-V psABI ABI mnemonic names to the register number. 50my @regaliases = ('zero','ra','sp','gp','tp','t0','t1','t2','s0','s1', 51 map("a$_",(0..7)), 52 map("s$_",(2..11)), 53 map("t$_",(3..6)) 54); 55 56my %reglookup; 57@reglookup{@regs} = @regs; 58@reglookup{@regaliases} = @regs; 59 60# Takes a register name, possibly an alias, and converts it to a register index 61# from 0 to 31 62sub read_reg { 63 my $reg = lc shift; 64 if (!exists($reglookup{$reg})) { 65 my $trace = ""; 66 if ($have_stacktrace) { 67 $trace = Devel::StackTrace->new->as_string; 68 } 69 die("Unknown register ".$reg."\n".$trace); 70 } 71 my $regstr = $reglookup{$reg}; 72 if (!($regstr =~ /^x([0-9]+)$/)) { 73 my $trace = ""; 74 if ($have_stacktrace) { 75 $trace = Devel::StackTrace->new->as_string; 76 } 77 die("Could not process register ".$reg."\n".$trace); 78 } 79 return $1; 80} 81 82# Read the sew setting(8, 16, 32 and 64) and convert to vsew encoding. 83sub read_sew { 84 my $sew_setting = shift; 85 86 if ($sew_setting eq "e8") { 87 return 0; 88 } elsif ($sew_setting eq "e16") { 89 return 1; 90 } elsif ($sew_setting eq "e32") { 91 return 2; 92 } elsif ($sew_setting eq "e64") { 93 return 3; 94 } else { 95 my $trace = ""; 96 if ($have_stacktrace) { 97 $trace = Devel::StackTrace->new->as_string; 98 } 99 die("Unsupported SEW setting:".$sew_setting."\n".$trace); 100 } 101} 102 103# Read the LMUL settings and convert to vlmul encoding. 104sub read_lmul { 105 my $lmul_setting = shift; 106 107 if ($lmul_setting eq "mf8") { 108 return 5; 109 } elsif ($lmul_setting eq "mf4") { 110 return 6; 111 } elsif ($lmul_setting eq "mf2") { 112 return 7; 113 } elsif ($lmul_setting eq "m1") { 114 return 0; 115 } elsif ($lmul_setting eq "m2") { 116 return 1; 117 } elsif ($lmul_setting eq "m4") { 118 return 2; 119 } elsif ($lmul_setting eq "m8") { 120 return 3; 121 } else { 122 my $trace = ""; 123 if ($have_stacktrace) { 124 $trace = Devel::StackTrace->new->as_string; 125 } 126 die("Unsupported LMUL setting:".$lmul_setting."\n".$trace); 127 } 128} 129 130# Read the tail policy settings and convert to vta encoding. 131sub read_tail_policy { 132 my $tail_setting = shift; 133 134 if ($tail_setting eq "ta") { 135 return 1; 136 } elsif ($tail_setting eq "tu") { 137 return 0; 138 } else { 139 my $trace = ""; 140 if ($have_stacktrace) { 141 $trace = Devel::StackTrace->new->as_string; 142 } 143 die("Unsupported tail policy setting:".$tail_setting."\n".$trace); 144 } 145} 146 147# Read the mask policy settings and convert to vma encoding. 148sub read_mask_policy { 149 my $mask_setting = shift; 150 151 if ($mask_setting eq "ma") { 152 return 1; 153 } elsif ($mask_setting eq "mu") { 154 return 0; 155 } else { 156 my $trace = ""; 157 if ($have_stacktrace) { 158 $trace = Devel::StackTrace->new->as_string; 159 } 160 die("Unsupported mask policy setting:".$mask_setting."\n".$trace); 161 } 162} 163 164my @vregs = map("v$_",(0..31)); 165my %vreglookup; 166@vreglookup{@vregs} = @vregs; 167 168sub read_vreg { 169 my $vreg = lc shift; 170 if (!exists($vreglookup{$vreg})) { 171 my $trace = ""; 172 if ($have_stacktrace) { 173 $trace = Devel::StackTrace->new->as_string; 174 } 175 die("Unknown vector register ".$vreg."\n".$trace); 176 } 177 if (!($vreg =~ /^v([0-9]+)$/)) { 178 my $trace = ""; 179 if ($have_stacktrace) { 180 $trace = Devel::StackTrace->new->as_string; 181 } 182 die("Could not process vector register ".$vreg."\n".$trace); 183 } 184 return $1; 185} 186 187# Read the vm settings and convert to mask encoding. 188sub read_mask_vreg { 189 my $vreg = shift; 190 # The default value is unmasked. 191 my $mask_bit = 1; 192 193 if (defined($vreg)) { 194 my $reg_id = read_vreg $vreg; 195 if ($reg_id == 0) { 196 $mask_bit = 0; 197 } else { 198 my $trace = ""; 199 if ($have_stacktrace) { 200 $trace = Devel::StackTrace->new->as_string; 201 } 202 die("The ".$vreg." is not the mask register v0.\n".$trace); 203 } 204 } 205 return $mask_bit; 206} 207 208# Helper functions 209 210sub brev8_rv64i { 211 # brev8 without `brev8` instruction (only in Zbkb) 212 # Bit-reverses the first argument and needs two scratch registers 213 my $val = shift; 214 my $t0 = shift; 215 my $t1 = shift; 216 my $brev8_const = shift; 217 my $seq = <<___; 218 la $brev8_const, Lbrev8_const 219 220 ld $t0, 0($brev8_const) # 0xAAAAAAAAAAAAAAAA 221 slli $t1, $val, 1 222 and $t1, $t1, $t0 223 and $val, $val, $t0 224 srli $val, $val, 1 225 or $val, $t1, $val 226 227 ld $t0, 8($brev8_const) # 0xCCCCCCCCCCCCCCCC 228 slli $t1, $val, 2 229 and $t1, $t1, $t0 230 and $val, $val, $t0 231 srli $val, $val, 2 232 or $val, $t1, $val 233 234 ld $t0, 16($brev8_const) # 0xF0F0F0F0F0F0F0F0 235 slli $t1, $val, 4 236 and $t1, $t1, $t0 237 and $val, $val, $t0 238 srli $val, $val, 4 239 or $val, $t1, $val 240___ 241 return $seq; 242} 243 244sub sd_rev8_rv64i { 245 # rev8 without `rev8` instruction (only in Zbb or Zbkb) 246 # Stores the given value byte-reversed and needs one scratch register 247 my $val = shift; 248 my $addr = shift; 249 my $off = shift; 250 my $tmp = shift; 251 my $off0 = ($off + 0); 252 my $off1 = ($off + 1); 253 my $off2 = ($off + 2); 254 my $off3 = ($off + 3); 255 my $off4 = ($off + 4); 256 my $off5 = ($off + 5); 257 my $off6 = ($off + 6); 258 my $off7 = ($off + 7); 259 my $seq = <<___; 260 sb $val, $off7($addr) 261 srli $tmp, $val, 8 262 sb $tmp, $off6($addr) 263 srli $tmp, $val, 16 264 sb $tmp, $off5($addr) 265 srli $tmp, $val, 24 266 sb $tmp, $off4($addr) 267 srli $tmp, $val, 32 268 sb $tmp, $off3($addr) 269 srli $tmp, $val, 40 270 sb $tmp, $off2($addr) 271 srli $tmp, $val, 48 272 sb $tmp, $off1($addr) 273 srli $tmp, $val, 56 274 sb $tmp, $off0($addr) 275___ 276 return $seq; 277} 278 279# Scalar crypto instructions 280 281sub aes64ds { 282 # Encoding for aes64ds rd, rs1, rs2 instruction on RV64 283 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 284 my $template = 0b0011101_00000_00000_000_00000_0110011; 285 my $rd = read_reg shift; 286 my $rs1 = read_reg shift; 287 my $rs2 = read_reg shift; 288 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 289} 290 291sub aes64dsm { 292 # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64 293 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 294 my $template = 0b0011111_00000_00000_000_00000_0110011; 295 my $rd = read_reg shift; 296 my $rs1 = read_reg shift; 297 my $rs2 = read_reg shift; 298 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 299} 300 301sub aes64es { 302 # Encoding for aes64es rd, rs1, rs2 instruction on RV64 303 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 304 my $template = 0b0011001_00000_00000_000_00000_0110011; 305 my $rd = read_reg shift; 306 my $rs1 = read_reg shift; 307 my $rs2 = read_reg shift; 308 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 309} 310 311sub aes64esm { 312 # Encoding for aes64esm rd, rs1, rs2 instruction on RV64 313 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 314 my $template = 0b0011011_00000_00000_000_00000_0110011; 315 my $rd = read_reg shift; 316 my $rs1 = read_reg shift; 317 my $rs2 = read_reg shift; 318 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 319} 320 321sub aes64im { 322 # Encoding for aes64im rd, rs1 instruction on RV64 323 # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX 324 my $template = 0b001100000000_00000_001_00000_0010011; 325 my $rd = read_reg shift; 326 my $rs1 = read_reg shift; 327 return ".word ".($template | ($rs1 << 15) | ($rd << 7)); 328} 329 330sub aes64ks1i { 331 # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64 332 # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX 333 my $template = 0b00110001_0000_00000_001_00000_0010011; 334 my $rd = read_reg shift; 335 my $rs1 = read_reg shift; 336 my $rnum = shift; 337 return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7)); 338} 339 340sub aes64ks2 { 341 # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64 342 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 343 my $template = 0b0111111_00000_00000_000_00000_0110011; 344 my $rd = read_reg shift; 345 my $rs1 = read_reg shift; 346 my $rs2 = read_reg shift; 347 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 348} 349 350sub brev8 { 351 # brev8 rd, rs 352 my $template = 0b011010000111_00000_101_00000_0010011; 353 my $rd = read_reg shift; 354 my $rs = read_reg shift; 355 return ".word ".($template | ($rs << 15) | ($rd << 7)); 356} 357 358sub clmul { 359 # Encoding for clmul rd, rs1, rs2 instruction on RV64 360 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 361 my $template = 0b0000101_00000_00000_001_00000_0110011; 362 my $rd = read_reg shift; 363 my $rs1 = read_reg shift; 364 my $rs2 = read_reg shift; 365 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 366} 367 368sub clmulh { 369 # Encoding for clmulh rd, rs1, rs2 instruction on RV64 370 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 371 my $template = 0b0000101_00000_00000_011_00000_0110011; 372 my $rd = read_reg shift; 373 my $rs1 = read_reg shift; 374 my $rs2 = read_reg shift; 375 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 376} 377 378sub rev8 { 379 # Encoding for rev8 rd, rs instruction on RV64 380 # XXXXXXXXXXXXX_ rs _XXX_ rd _XXXXXXX 381 my $template = 0b011010111000_00000_101_00000_0010011; 382 my $rd = read_reg shift; 383 my $rs = read_reg shift; 384 return ".word ".($template | ($rs << 15) | ($rd << 7)); 385} 386 387sub roriw { 388 # Encoding for roriw rd, rs1, shamt instruction on RV64 389 # XXXXXXX_ shamt _ rs1 _XXX_ rd _XXXXXXX 390 my $template = 0b0110000_00000_00000_101_00000_0011011; 391 my $rd = read_reg shift; 392 my $rs1 = read_reg shift; 393 my $shamt = shift; 394 return ".word ".($template | ($shamt << 20) | ($rs1 << 15) | ($rd << 7)); 395} 396 397sub maxu { 398 # Encoding for maxu rd, rs1, rs2 instruction on RV64 399 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 400 my $template = 0b0000101_00000_00000_111_00000_0110011; 401 my $rd = read_reg shift; 402 my $rs1 = read_reg shift; 403 my $rs2 = read_reg shift; 404 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 405} 406 407sub minu { 408 # Encoding for minu rd, rs1, rs2 instruction on RV64 409 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX 410 my $template = 0b0000101_00000_00000_101_00000_0110011; 411 my $rd = read_reg shift; 412 my $rs1 = read_reg shift; 413 my $rs2 = read_reg shift; 414 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); 415} 416 417# Vector instructions 418 419sub vadd_vv { 420 # vadd.vv vd, vs2, vs1, vm 421 my $template = 0b000000_0_00000_00000_000_00000_1010111; 422 my $vd = read_vreg shift; 423 my $vs2 = read_vreg shift; 424 my $vs1 = read_vreg shift; 425 my $vm = read_mask_vreg shift; 426 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 427} 428 429sub vadd_vx { 430 # vadd.vx vd, vs2, rs1, vm 431 my $template = 0b000000_0_00000_00000_100_00000_1010111; 432 my $vd = read_vreg shift; 433 my $vs2 = read_vreg shift; 434 my $rs1 = read_reg shift; 435 my $vm = read_mask_vreg shift; 436 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 437} 438 439sub vsub_vv { 440 # vsub.vv vd, vs2, vs1, vm 441 my $template = 0b000010_0_00000_00000_000_00000_1010111; 442 my $vd = read_vreg shift; 443 my $vs2 = read_vreg shift; 444 my $vs1 = read_vreg shift; 445 my $vm = read_mask_vreg shift; 446 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 447} 448 449sub vsub_vx { 450 # vsub.vx vd, vs2, rs1, vm 451 my $template = 0b000010_0_00000_00000_100_00000_1010111; 452 my $vd = read_vreg shift; 453 my $vs2 = read_vreg shift; 454 my $rs1 = read_reg shift; 455 my $vm = read_mask_vreg shift; 456 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 457} 458 459sub vid_v { 460 # vid.v vd 461 my $template = 0b0101001_00000_10001_010_00000_1010111; 462 my $vd = read_vreg shift; 463 return ".word ".($template | ($vd << 7)); 464} 465 466sub viota_m { 467 # viota.m vd, vs2, vm 468 my $template = 0b010100_0_00000_10000_010_00000_1010111; 469 my $vd = read_vreg shift; 470 my $vs2 = read_vreg shift; 471 my $vm = read_mask_vreg shift; 472 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7)); 473} 474 475sub vle8_v { 476 # vle8.v vd, (rs1), vm 477 my $template = 0b000000_0_00000_00000_000_00000_0000111; 478 my $vd = read_vreg shift; 479 my $rs1 = read_reg shift; 480 my $vm = read_mask_vreg shift; 481 return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7)); 482} 483 484sub vle32_v { 485 # vle32.v vd, (rs1), vm 486 my $template = 0b000000_0_00000_00000_110_00000_0000111; 487 my $vd = read_vreg shift; 488 my $rs1 = read_reg shift; 489 my $vm = read_mask_vreg shift; 490 return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7)); 491} 492 493sub vle64_v { 494 # vle64.v vd, (rs1) 495 my $template = 0b0000001_00000_00000_111_00000_0000111; 496 my $vd = read_vreg shift; 497 my $rs1 = read_reg shift; 498 return ".word ".($template | ($rs1 << 15) | ($vd << 7)); 499} 500 501sub vlse32_v { 502 # vlse32.v vd, (rs1), rs2 503 my $template = 0b0000101_00000_00000_110_00000_0000111; 504 my $vd = read_vreg shift; 505 my $rs1 = read_reg shift; 506 my $rs2 = read_reg shift; 507 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7)); 508} 509 510sub vlsseg_nf_e32_v { 511 # vlsseg<nf>e32.v vd, (rs1), rs2 512 my $template = 0b0000101_00000_00000_110_00000_0000111; 513 my $nf = shift; 514 $nf -= 1; 515 my $vd = read_vreg shift; 516 my $rs1 = read_reg shift; 517 my $rs2 = read_reg shift; 518 return ".word ".($template | ($nf << 29) | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7)); 519} 520 521sub vlse64_v { 522 # vlse64.v vd, (rs1), rs2 523 my $template = 0b0000101_00000_00000_111_00000_0000111; 524 my $vd = read_vreg shift; 525 my $rs1 = read_reg shift; 526 my $rs2 = read_reg shift; 527 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7)); 528} 529 530sub vluxei8_v { 531 # vluxei8.v vd, (rs1), vs2, vm 532 my $template = 0b000001_0_00000_00000_000_00000_0000111; 533 my $vd = read_vreg shift; 534 my $rs1 = read_reg shift; 535 my $vs2 = read_vreg shift; 536 my $vm = read_mask_vreg shift; 537 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 538} 539 540sub vmerge_vim { 541 # vmerge.vim vd, vs2, imm, v0 542 my $template = 0b0101110_00000_00000_011_00000_1010111; 543 my $vd = read_vreg shift; 544 my $vs2 = read_vreg shift; 545 my $imm = shift; 546 return ".word ".($template | ($vs2 << 20) | ($imm << 15) | ($vd << 7)); 547} 548 549sub vmerge_vvm { 550 # vmerge.vvm vd vs2 vs1 551 my $template = 0b0101110_00000_00000_000_00000_1010111; 552 my $vd = read_vreg shift; 553 my $vs2 = read_vreg shift; 554 my $vs1 = read_vreg shift; 555 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)) 556} 557 558sub vmseq_vi { 559 # vmseq.vi vd vs1, imm 560 my $template = 0b0110001_00000_00000_011_00000_1010111; 561 my $vd = read_vreg shift; 562 my $vs1 = read_vreg shift; 563 my $imm = shift; 564 return ".word ".($template | ($vs1 << 20) | ($imm << 15) | ($vd << 7)) 565} 566 567sub vmsgtu_vx { 568 # vmsgtu.vx vd vs2, rs1, vm 569 my $template = 0b011110_0_00000_00000_100_00000_1010111; 570 my $vd = read_vreg shift; 571 my $vs2 = read_vreg shift; 572 my $rs1 = read_reg shift; 573 my $vm = read_mask_vreg shift; 574 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)) 575} 576 577sub vmv_v_i { 578 # vmv.v.i vd, imm 579 my $template = 0b0101111_00000_00000_011_00000_1010111; 580 my $vd = read_vreg shift; 581 my $imm = shift; 582 return ".word ".($template | ($imm << 15) | ($vd << 7)); 583} 584 585sub vmv_v_x { 586 # vmv.v.x vd, rs1 587 my $template = 0b0101111_00000_00000_100_00000_1010111; 588 my $vd = read_vreg shift; 589 my $rs1 = read_reg shift; 590 return ".word ".($template | ($rs1 << 15) | ($vd << 7)); 591} 592 593sub vmv_v_v { 594 # vmv.v.v vd, vs1 595 my $template = 0b0101111_00000_00000_000_00000_1010111; 596 my $vd = read_vreg shift; 597 my $vs1 = read_vreg shift; 598 return ".word ".($template | ($vs1 << 15) | ($vd << 7)); 599} 600 601sub vor_vv { 602 # vor.vv vd, vs2, vs1 603 my $template = 0b0010101_00000_00000_000_00000_1010111; 604 my $vd = read_vreg shift; 605 my $vs2 = read_vreg shift; 606 my $vs1 = read_vreg shift; 607 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 608} 609 610sub vor_vv_v0t { 611 # vor.vv vd, vs2, vs1, v0.t 612 my $template = 0b0010100_00000_00000_000_00000_1010111; 613 my $vd = read_vreg shift; 614 my $vs2 = read_vreg shift; 615 my $vs1 = read_vreg shift; 616 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 617} 618 619sub vse8_v { 620 # vse8.v vd, (rs1), vm 621 my $template = 0b000000_0_00000_00000_000_00000_0100111; 622 my $vd = read_vreg shift; 623 my $rs1 = read_reg shift; 624 my $vm = read_mask_vreg shift; 625 return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7)); 626} 627 628sub vse32_v { 629 # vse32.v vd, (rs1), vm 630 my $template = 0b000000_0_00000_00000_110_00000_0100111; 631 my $vd = read_vreg shift; 632 my $rs1 = read_reg shift; 633 my $vm = read_mask_vreg shift; 634 return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7)); 635} 636 637sub vssseg_nf_e32_v { 638 # vssseg<nf>e32.v vs3, (rs1), rs2 639 my $template = 0b0000101_00000_00000_110_00000_0100111; 640 my $nf = shift; 641 $nf -= 1; 642 my $vs3 = read_vreg shift; 643 my $rs1 = read_reg shift; 644 my $rs2 = read_reg shift; 645 return ".word ".($template | ($nf << 29) | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7)); 646} 647 648sub vsuxei8_v { 649 # vsuxei8.v vs3, (rs1), vs2, vm 650 my $template = 0b000001_0_00000_00000_000_00000_0100111; 651 my $vs3 = read_vreg shift; 652 my $rs1 = read_reg shift; 653 my $vs2 = read_vreg shift; 654 my $vm = read_mask_vreg shift; 655 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vs3 << 7)); 656} 657 658sub vse64_v { 659 # vse64.v vd, (rs1) 660 my $template = 0b0000001_00000_00000_111_00000_0100111; 661 my $vd = read_vreg shift; 662 my $rs1 = read_reg shift; 663 return ".word ".($template | ($rs1 << 15) | ($vd << 7)); 664} 665 666sub vsetivli__x0_2_e64_m1_tu_mu { 667 # vsetivli x0, 2, e64, m1, tu, mu 668 return ".word 0xc1817057"; 669} 670 671sub vsetivli__x0_4_e32_m1_tu_mu { 672 # vsetivli x0, 4, e32, m1, tu, mu 673 return ".word 0xc1027057"; 674} 675 676sub vsetivli__x0_4_e64_m1_tu_mu { 677 # vsetivli x0, 4, e64, m1, tu, mu 678 return ".word 0xc1827057"; 679} 680 681sub vsetivli__x0_8_e32_m1_tu_mu { 682 # vsetivli x0, 8, e32, m1, tu, mu 683 return ".word 0xc1047057"; 684} 685 686sub vsetvli { 687 # vsetvli rd, rs1, vtypei 688 my $template = 0b0_00000000000_00000_111_00000_1010111; 689 my $rd = read_reg shift; 690 my $rs1 = read_reg shift; 691 my $sew = read_sew shift; 692 my $lmul = read_lmul shift; 693 my $tail_policy = read_tail_policy shift; 694 my $mask_policy = read_mask_policy shift; 695 my $vtypei = ($mask_policy << 7) | ($tail_policy << 6) | ($sew << 3) | $lmul; 696 697 return ".word ".($template | ($vtypei << 20) | ($rs1 << 15) | ($rd << 7)); 698} 699 700sub vsetivli { 701 # vsetvli rd, uimm, vtypei 702 my $template = 0b11_0000000000_00000_111_00000_1010111; 703 my $rd = read_reg shift; 704 my $uimm = shift; 705 my $sew = read_sew shift; 706 my $lmul = read_lmul shift; 707 my $tail_policy = read_tail_policy shift; 708 my $mask_policy = read_mask_policy shift; 709 my $vtypei = ($mask_policy << 7) | ($tail_policy << 6) | ($sew << 3) | $lmul; 710 711 return ".word ".($template | ($vtypei << 20) | ($uimm << 15) | ($rd << 7)); 712} 713 714sub vslidedown_vi { 715 # vslidedown.vi vd, vs2, uimm 716 my $template = 0b0011111_00000_00000_011_00000_1010111; 717 my $vd = read_vreg shift; 718 my $vs2 = read_vreg shift; 719 my $uimm = shift; 720 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 721} 722 723sub vslidedown_vx { 724 # vslidedown.vx vd, vs2, rs1 725 my $template = 0b0011111_00000_00000_100_00000_1010111; 726 my $vd = read_vreg shift; 727 my $vs2 = read_vreg shift; 728 my $rs1 = read_reg shift; 729 return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 730} 731 732sub vslideup_vi_v0t { 733 # vslideup.vi vd, vs2, uimm, v0.t 734 my $template = 0b0011100_00000_00000_011_00000_1010111; 735 my $vd = read_vreg shift; 736 my $vs2 = read_vreg shift; 737 my $uimm = shift; 738 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 739} 740 741sub vslideup_vi { 742 # vslideup.vi vd, vs2, uimm 743 my $template = 0b0011101_00000_00000_011_00000_1010111; 744 my $vd = read_vreg shift; 745 my $vs2 = read_vreg shift; 746 my $uimm = shift; 747 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 748} 749 750sub vsll_vi { 751 # vsll.vi vd, vs2, uimm, vm 752 my $template = 0b1001011_00000_00000_011_00000_1010111; 753 my $vd = read_vreg shift; 754 my $vs2 = read_vreg shift; 755 my $uimm = shift; 756 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 757} 758 759sub vsrl_vi { 760 # vsrl.vi vd, vs2, uimm, vm 761 my $template = 0b1010001_00000_00000_011_00000_1010111; 762 my $vd = read_vreg shift; 763 my $vs2 = read_vreg shift; 764 my $uimm = shift; 765 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 766} 767 768sub vsrl_vx { 769 # vsrl.vx vd, vs2, rs1 770 my $template = 0b1010001_00000_00000_100_00000_1010111; 771 my $vd = read_vreg shift; 772 my $vs2 = read_vreg shift; 773 my $rs1 = read_reg shift; 774 return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 775} 776 777sub vsse32_v { 778 # vse32.v vs3, (rs1), rs2 779 my $template = 0b0000101_00000_00000_110_00000_0100111; 780 my $vs3 = read_vreg shift; 781 my $rs1 = read_reg shift; 782 my $rs2 = read_reg shift; 783 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7)); 784} 785 786sub vsse64_v { 787 # vsse64.v vs3, (rs1), rs2 788 my $template = 0b0000101_00000_00000_111_00000_0100111; 789 my $vs3 = read_vreg shift; 790 my $rs1 = read_reg shift; 791 my $rs2 = read_reg shift; 792 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7)); 793} 794 795sub vxor_vv_v0t { 796 # vxor.vv vd, vs2, vs1, v0.t 797 my $template = 0b0010110_00000_00000_000_00000_1010111; 798 my $vd = read_vreg shift; 799 my $vs2 = read_vreg shift; 800 my $vs1 = read_vreg shift; 801 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 802} 803 804sub vxor_vv { 805 # vxor.vv vd, vs2, vs1 806 my $template = 0b0010111_00000_00000_000_00000_1010111; 807 my $vd = read_vreg shift; 808 my $vs2 = read_vreg shift; 809 my $vs1 = read_vreg shift; 810 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 811} 812 813sub vzext_vf2 { 814 # vzext.vf2 vd, vs2, vm 815 my $template = 0b010010_0_00000_00110_010_00000_1010111; 816 my $vd = read_vreg shift; 817 my $vs2 = read_vreg shift; 818 my $vm = read_mask_vreg shift; 819 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7)); 820} 821 822# Vector crypto instructions 823 824## Zvbb and Zvkb instructions 825## 826## vandn (also in zvkb) 827## vbrev 828## vbrev8 (also in zvkb) 829## vrev8 (also in zvkb) 830## vclz 831## vctz 832## vcpop 833## vrol (also in zvkb) 834## vror (also in zvkb) 835## vwsll 836 837sub vbrev8_v { 838 # vbrev8.v vd, vs2, vm 839 my $template = 0b010010_0_00000_01000_010_00000_1010111; 840 my $vd = read_vreg shift; 841 my $vs2 = read_vreg shift; 842 my $vm = read_mask_vreg shift; 843 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7)); 844} 845 846sub vrev8_v { 847 # vrev8.v vd, vs2, vm 848 my $template = 0b010010_0_00000_01001_010_00000_1010111; 849 my $vd = read_vreg shift; 850 my $vs2 = read_vreg shift; 851 my $vm = read_mask_vreg shift; 852 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7)); 853} 854 855sub vror_vi { 856 # vror.vi vd, vs2, uimm 857 my $template = 0b01010_0_1_00000_00000_011_00000_1010111; 858 my $vd = read_vreg shift; 859 my $vs2 = read_vreg shift; 860 my $uimm = shift; 861 my $uimm_i5 = $uimm >> 5; 862 my $uimm_i4_0 = $uimm & 0b11111; 863 864 return ".word ".($template | ($uimm_i5 << 26) | ($vs2 << 20) | ($uimm_i4_0 << 15) | ($vd << 7)); 865} 866 867sub vwsll_vv { 868 # vwsll.vv vd, vs2, vs1, vm 869 my $template = 0b110101_0_00000_00000_000_00000_1010111; 870 my $vd = read_vreg shift; 871 my $vs2 = read_vreg shift; 872 my $vs1 = read_vreg shift; 873 my $vm = read_mask_vreg shift; 874 return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 875} 876 877## Zvbc instructions 878 879sub vclmulh_vx { 880 # vclmulh.vx vd, vs2, rs1 881 my $template = 0b0011011_00000_00000_110_00000_1010111; 882 my $vd = read_vreg shift; 883 my $vs2 = read_vreg shift; 884 my $rs1 = read_reg shift; 885 return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 886} 887 888sub vclmul_vx_v0t { 889 # vclmul.vx vd, vs2, rs1, v0.t 890 my $template = 0b0011000_00000_00000_110_00000_1010111; 891 my $vd = read_vreg shift; 892 my $vs2 = read_vreg shift; 893 my $rs1 = read_reg shift; 894 return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 895} 896 897sub vclmul_vx { 898 # vclmul.vx vd, vs2, rs1 899 my $template = 0b0011001_00000_00000_110_00000_1010111; 900 my $vd = read_vreg shift; 901 my $vs2 = read_vreg shift; 902 my $rs1 = read_reg shift; 903 return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7)); 904} 905 906## Zvkg instructions 907 908sub vghsh_vv { 909 # vghsh.vv vd, vs2, vs1 910 my $template = 0b1011001_00000_00000_010_00000_1110111; 911 my $vd = read_vreg shift; 912 my $vs2 = read_vreg shift; 913 my $vs1 = read_vreg shift; 914 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); 915} 916 917sub vgmul_vv { 918 # vgmul.vv vd, vs2 919 my $template = 0b1010001_00000_10001_010_00000_1110111; 920 my $vd = read_vreg shift; 921 my $vs2 = read_vreg shift; 922 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 923} 924 925## Zvkned instructions 926 927sub vaesdf_vs { 928 # vaesdf.vs vd, vs2 929 my $template = 0b101001_1_00000_00001_010_00000_1110111; 930 my $vd = read_vreg shift; 931 my $vs2 = read_vreg shift; 932 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 933} 934 935sub vaesdm_vs { 936 # vaesdm.vs vd, vs2 937 my $template = 0b101001_1_00000_00000_010_00000_1110111; 938 my $vd = read_vreg shift; 939 my $vs2 = read_vreg shift; 940 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 941} 942 943sub vaesef_vs { 944 # vaesef.vs vd, vs2 945 my $template = 0b101001_1_00000_00011_010_00000_1110111; 946 my $vd = read_vreg shift; 947 my $vs2 = read_vreg shift; 948 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 949} 950 951sub vaesem_vs { 952 # vaesem.vs vd, vs2 953 my $template = 0b101001_1_00000_00010_010_00000_1110111; 954 my $vd = read_vreg shift; 955 my $vs2 = read_vreg shift; 956 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 957} 958 959sub vaeskf1_vi { 960 # vaeskf1.vi vd, vs2, uimmm 961 my $template = 0b100010_1_00000_00000_010_00000_1110111; 962 my $vd = read_vreg shift; 963 my $vs2 = read_vreg shift; 964 my $uimm = shift; 965 return ".word ".($template | ($uimm << 15) | ($vs2 << 20) | ($vd << 7)); 966} 967 968sub vaeskf2_vi { 969 # vaeskf2.vi vd, vs2, uimm 970 my $template = 0b101010_1_00000_00000_010_00000_1110111; 971 my $vd = read_vreg shift; 972 my $vs2 = read_vreg shift; 973 my $uimm = shift; 974 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 975} 976 977sub vaesz_vs { 978 # vaesz.vs vd, vs2 979 my $template = 0b101001_1_00000_00111_010_00000_1110111; 980 my $vd = read_vreg shift; 981 my $vs2 = read_vreg shift; 982 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 983} 984 985## Zvknha and Zvknhb instructions 986 987sub vsha2ms_vv { 988 # vsha2ms.vv vd, vs2, vs1 989 my $template = 0b1011011_00000_00000_010_00000_1110111; 990 my $vd = read_vreg shift; 991 my $vs2 = read_vreg shift; 992 my $vs1 = read_vreg shift; 993 return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7)); 994} 995 996sub vsha2ch_vv { 997 # vsha2ch.vv vd, vs2, vs1 998 my $template = 0b101110_10000_00000_001_00000_01110111; 999 my $vd = read_vreg shift; 1000 my $vs2 = read_vreg shift; 1001 my $vs1 = read_vreg shift; 1002 return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7)); 1003} 1004 1005sub vsha2cl_vv { 1006 # vsha2cl.vv vd, vs2, vs1 1007 my $template = 0b101111_10000_00000_001_00000_01110111; 1008 my $vd = read_vreg shift; 1009 my $vs2 = read_vreg shift; 1010 my $vs1 = read_vreg shift; 1011 return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7)); 1012} 1013 1014## Zvksed instructions 1015 1016sub vsm4k_vi { 1017 # vsm4k.vi vd, vs2, uimm 1018 my $template = 0b1000011_00000_00000_010_00000_1110111; 1019 my $vd = read_vreg shift; 1020 my $vs2 = read_vreg shift; 1021 my $uimm = shift; 1022 return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); 1023} 1024 1025sub vsm4r_vs { 1026 # vsm4r.vs vd, vs2 1027 my $template = 0b1010011_00000_10000_010_00000_1110111; 1028 my $vd = read_vreg shift; 1029 my $vs2 = read_vreg shift; 1030 return ".word ".($template | ($vs2 << 20) | ($vd << 7)); 1031} 1032 1033## zvksh instructions 1034 1035sub vsm3c_vi { 1036 # vsm3c.vi vd, vs2, uimm 1037 my $template = 0b1010111_00000_00000_010_00000_1110111; 1038 my $vd = read_vreg shift; 1039 my $vs2 = read_vreg shift; 1040 my $uimm = shift; 1041 return ".word ".($template | ($vs2 << 20) | ($uimm << 15 ) | ($vd << 7)); 1042} 1043 1044sub vsm3me_vv { 1045 # vsm3me.vv vd, vs2, vs1 1046 my $template = 0b1000001_00000_00000_010_00000_1110111; 1047 my $vd = read_vreg shift; 1048 my $vs2 = read_vreg shift; 1049 my $vs1 = read_vreg shift; 1050 return ".word ".($template | ($vs2 << 20) | ($vs1 << 15 ) | ($vd << 7)); 1051} 1052 10531; 1054