2
0

riscv.pm 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  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 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. use strict;
  39. use warnings;
  40. # Set $have_stacktrace to 1 if we have Devel::StackTrace
  41. my $have_stacktrace = 0;
  42. if (eval {require Devel::StackTrace;1;}) {
  43. $have_stacktrace = 1;
  44. }
  45. my @regs = map("x$_",(0..31));
  46. # Mapping from the RISC-V psABI ABI mnemonic names to the register number.
  47. my @regaliases = ('zero','ra','sp','gp','tp','t0','t1','t2','s0','s1',
  48. map("a$_",(0..7)),
  49. map("s$_",(2..11)),
  50. map("t$_",(3..6))
  51. );
  52. my %reglookup;
  53. @reglookup{@regs} = @regs;
  54. @reglookup{@regaliases} = @regs;
  55. # Takes a register name, possibly an alias, and converts it to a register index
  56. # from 0 to 31
  57. sub read_reg {
  58. my $reg = lc shift;
  59. if (!exists($reglookup{$reg})) {
  60. my $trace = "";
  61. if ($have_stacktrace) {
  62. $trace = Devel::StackTrace->new->as_string;
  63. }
  64. die("Unknown register ".$reg."\n".$trace);
  65. }
  66. my $regstr = $reglookup{$reg};
  67. if (!($regstr =~ /^x([0-9]+)$/)) {
  68. my $trace = "";
  69. if ($have_stacktrace) {
  70. $trace = Devel::StackTrace->new->as_string;
  71. }
  72. die("Could not process register ".$reg."\n".$trace);
  73. }
  74. return $1;
  75. }
  76. # Read the sew setting(8, 16, 32 and 64) and convert to vsew encoding.
  77. sub read_sew {
  78. my $sew_setting = shift;
  79. if ($sew_setting eq "e8") {
  80. return 0;
  81. } elsif ($sew_setting eq "e16") {
  82. return 1;
  83. } elsif ($sew_setting eq "e32") {
  84. return 2;
  85. } elsif ($sew_setting eq "e64") {
  86. return 3;
  87. } else {
  88. my $trace = "";
  89. if ($have_stacktrace) {
  90. $trace = Devel::StackTrace->new->as_string;
  91. }
  92. die("Unsupported SEW setting:".$sew_setting."\n".$trace);
  93. }
  94. }
  95. # Read the LMUL settings and convert to vlmul encoding.
  96. sub read_lmul {
  97. my $lmul_setting = shift;
  98. if ($lmul_setting eq "mf8") {
  99. return 5;
  100. } elsif ($lmul_setting eq "mf4") {
  101. return 6;
  102. } elsif ($lmul_setting eq "mf2") {
  103. return 7;
  104. } elsif ($lmul_setting eq "m1") {
  105. return 0;
  106. } elsif ($lmul_setting eq "m2") {
  107. return 1;
  108. } elsif ($lmul_setting eq "m4") {
  109. return 2;
  110. } elsif ($lmul_setting eq "m8") {
  111. return 3;
  112. } else {
  113. my $trace = "";
  114. if ($have_stacktrace) {
  115. $trace = Devel::StackTrace->new->as_string;
  116. }
  117. die("Unsupported LMUL setting:".$lmul_setting."\n".$trace);
  118. }
  119. }
  120. # Read the tail policy settings and convert to vta encoding.
  121. sub read_tail_policy {
  122. my $tail_setting = shift;
  123. if ($tail_setting eq "ta") {
  124. return 1;
  125. } elsif ($tail_setting eq "tu") {
  126. return 0;
  127. } else {
  128. my $trace = "";
  129. if ($have_stacktrace) {
  130. $trace = Devel::StackTrace->new->as_string;
  131. }
  132. die("Unsupported tail policy setting:".$tail_setting."\n".$trace);
  133. }
  134. }
  135. # Read the mask policy settings and convert to vma encoding.
  136. sub read_mask_policy {
  137. my $mask_setting = shift;
  138. if ($mask_setting eq "ma") {
  139. return 1;
  140. } elsif ($mask_setting eq "mu") {
  141. return 0;
  142. } else {
  143. my $trace = "";
  144. if ($have_stacktrace) {
  145. $trace = Devel::StackTrace->new->as_string;
  146. }
  147. die("Unsupported mask policy setting:".$mask_setting."\n".$trace);
  148. }
  149. }
  150. my @vregs = map("v$_",(0..31));
  151. my %vreglookup;
  152. @vreglookup{@vregs} = @vregs;
  153. sub read_vreg {
  154. my $vreg = lc shift;
  155. if (!exists($vreglookup{$vreg})) {
  156. my $trace = "";
  157. if ($have_stacktrace) {
  158. $trace = Devel::StackTrace->new->as_string;
  159. }
  160. die("Unknown vector register ".$vreg."\n".$trace);
  161. }
  162. if (!($vreg =~ /^v([0-9]+)$/)) {
  163. my $trace = "";
  164. if ($have_stacktrace) {
  165. $trace = Devel::StackTrace->new->as_string;
  166. }
  167. die("Could not process vector register ".$vreg."\n".$trace);
  168. }
  169. return $1;
  170. }
  171. # Read the vm settings and convert to mask encoding.
  172. sub read_mask_vreg {
  173. my $vreg = shift;
  174. # The default value is unmasked.
  175. my $mask_bit = 1;
  176. if (defined($vreg)) {
  177. my $reg_id = read_vreg $vreg;
  178. if ($reg_id == 0) {
  179. $mask_bit = 0;
  180. } else {
  181. my $trace = "";
  182. if ($have_stacktrace) {
  183. $trace = Devel::StackTrace->new->as_string;
  184. }
  185. die("The ".$vreg." is not the mask register v0.\n".$trace);
  186. }
  187. }
  188. return $mask_bit;
  189. }
  190. # Helper functions
  191. sub brev8_rv64i {
  192. # brev8 without `brev8` instruction (only in Zbkb)
  193. # Bit-reverses the first argument and needs two scratch registers
  194. my $val = shift;
  195. my $t0 = shift;
  196. my $t1 = shift;
  197. my $brev8_const = shift;
  198. my $seq = <<___;
  199. la $brev8_const, Lbrev8_const
  200. ld $t0, 0($brev8_const) # 0xAAAAAAAAAAAAAAAA
  201. slli $t1, $val, 1
  202. and $t1, $t1, $t0
  203. and $val, $val, $t0
  204. srli $val, $val, 1
  205. or $val, $t1, $val
  206. ld $t0, 8($brev8_const) # 0xCCCCCCCCCCCCCCCC
  207. slli $t1, $val, 2
  208. and $t1, $t1, $t0
  209. and $val, $val, $t0
  210. srli $val, $val, 2
  211. or $val, $t1, $val
  212. ld $t0, 16($brev8_const) # 0xF0F0F0F0F0F0F0F0
  213. slli $t1, $val, 4
  214. and $t1, $t1, $t0
  215. and $val, $val, $t0
  216. srli $val, $val, 4
  217. or $val, $t1, $val
  218. ___
  219. return $seq;
  220. }
  221. sub sd_rev8_rv64i {
  222. # rev8 without `rev8` instruction (only in Zbb or Zbkb)
  223. # Stores the given value byte-reversed and needs one scratch register
  224. my $val = shift;
  225. my $addr = shift;
  226. my $off = shift;
  227. my $tmp = shift;
  228. my $off0 = ($off + 0);
  229. my $off1 = ($off + 1);
  230. my $off2 = ($off + 2);
  231. my $off3 = ($off + 3);
  232. my $off4 = ($off + 4);
  233. my $off5 = ($off + 5);
  234. my $off6 = ($off + 6);
  235. my $off7 = ($off + 7);
  236. my $seq = <<___;
  237. sb $val, $off7($addr)
  238. srli $tmp, $val, 8
  239. sb $tmp, $off6($addr)
  240. srli $tmp, $val, 16
  241. sb $tmp, $off5($addr)
  242. srli $tmp, $val, 24
  243. sb $tmp, $off4($addr)
  244. srli $tmp, $val, 32
  245. sb $tmp, $off3($addr)
  246. srli $tmp, $val, 40
  247. sb $tmp, $off2($addr)
  248. srli $tmp, $val, 48
  249. sb $tmp, $off1($addr)
  250. srli $tmp, $val, 56
  251. sb $tmp, $off0($addr)
  252. ___
  253. return $seq;
  254. }
  255. # Scalar crypto instructions
  256. sub aes64ds {
  257. # Encoding for aes64ds rd, rs1, rs2 instruction on RV64
  258. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  259. my $template = 0b0011101_00000_00000_000_00000_0110011;
  260. my $rd = read_reg shift;
  261. my $rs1 = read_reg shift;
  262. my $rs2 = read_reg shift;
  263. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  264. }
  265. sub aes64dsm {
  266. # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64
  267. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  268. my $template = 0b0011111_00000_00000_000_00000_0110011;
  269. my $rd = read_reg shift;
  270. my $rs1 = read_reg shift;
  271. my $rs2 = read_reg shift;
  272. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  273. }
  274. sub aes64es {
  275. # Encoding for aes64es rd, rs1, rs2 instruction on RV64
  276. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  277. my $template = 0b0011001_00000_00000_000_00000_0110011;
  278. my $rd = read_reg shift;
  279. my $rs1 = read_reg shift;
  280. my $rs2 = read_reg shift;
  281. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  282. }
  283. sub aes64esm {
  284. # Encoding for aes64esm rd, rs1, rs2 instruction on RV64
  285. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  286. my $template = 0b0011011_00000_00000_000_00000_0110011;
  287. my $rd = read_reg shift;
  288. my $rs1 = read_reg shift;
  289. my $rs2 = read_reg shift;
  290. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  291. }
  292. sub aes64im {
  293. # Encoding for aes64im rd, rs1 instruction on RV64
  294. # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX
  295. my $template = 0b001100000000_00000_001_00000_0010011;
  296. my $rd = read_reg shift;
  297. my $rs1 = read_reg shift;
  298. return ".word ".($template | ($rs1 << 15) | ($rd << 7));
  299. }
  300. sub aes64ks1i {
  301. # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64
  302. # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX
  303. my $template = 0b00110001_0000_00000_001_00000_0010011;
  304. my $rd = read_reg shift;
  305. my $rs1 = read_reg shift;
  306. my $rnum = shift;
  307. return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7));
  308. }
  309. sub aes64ks2 {
  310. # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64
  311. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  312. my $template = 0b0111111_00000_00000_000_00000_0110011;
  313. my $rd = read_reg shift;
  314. my $rs1 = read_reg shift;
  315. my $rs2 = read_reg shift;
  316. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  317. }
  318. sub brev8 {
  319. # brev8 rd, rs
  320. my $template = 0b011010000111_00000_101_00000_0010011;
  321. my $rd = read_reg shift;
  322. my $rs = read_reg shift;
  323. return ".word ".($template | ($rs << 15) | ($rd << 7));
  324. }
  325. sub clmul {
  326. # Encoding for clmul rd, rs1, rs2 instruction on RV64
  327. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  328. my $template = 0b0000101_00000_00000_001_00000_0110011;
  329. my $rd = read_reg shift;
  330. my $rs1 = read_reg shift;
  331. my $rs2 = read_reg shift;
  332. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  333. }
  334. sub clmulh {
  335. # Encoding for clmulh rd, rs1, rs2 instruction on RV64
  336. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  337. my $template = 0b0000101_00000_00000_011_00000_0110011;
  338. my $rd = read_reg shift;
  339. my $rs1 = read_reg shift;
  340. my $rs2 = read_reg shift;
  341. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  342. }
  343. sub rev8 {
  344. # Encoding for rev8 rd, rs instruction on RV64
  345. # XXXXXXXXXXXXX_ rs _XXX_ rd _XXXXXXX
  346. my $template = 0b011010111000_00000_101_00000_0010011;
  347. my $rd = read_reg shift;
  348. my $rs = read_reg shift;
  349. return ".word ".($template | ($rs << 15) | ($rd << 7));
  350. }
  351. # Vector instructions
  352. sub vadd_vv {
  353. # vadd.vv vd, vs2, vs1, vm
  354. my $template = 0b000000_0_00000_00000_000_00000_1010111;
  355. my $vd = read_vreg shift;
  356. my $vs2 = read_vreg shift;
  357. my $vs1 = read_vreg shift;
  358. my $vm = read_mask_vreg shift;
  359. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  360. }
  361. sub vadd_vx {
  362. # vadd.vx vd, vs2, rs1, vm
  363. my $template = 0b000000_0_00000_00000_100_00000_1010111;
  364. my $vd = read_vreg shift;
  365. my $vs2 = read_vreg shift;
  366. my $rs1 = read_reg shift;
  367. my $vm = read_mask_vreg shift;
  368. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  369. }
  370. sub vsub_vv {
  371. # vsub.vv vd, vs2, vs1, vm
  372. my $template = 0b000010_0_00000_00000_000_00000_1010111;
  373. my $vd = read_vreg shift;
  374. my $vs2 = read_vreg shift;
  375. my $vs1 = read_vreg shift;
  376. my $vm = read_mask_vreg shift;
  377. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  378. }
  379. sub vsub_vx {
  380. # vsub.vx vd, vs2, rs1, vm
  381. my $template = 0b000010_0_00000_00000_100_00000_1010111;
  382. my $vd = read_vreg shift;
  383. my $vs2 = read_vreg shift;
  384. my $rs1 = read_reg shift;
  385. my $vm = read_mask_vreg shift;
  386. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  387. }
  388. sub vid_v {
  389. # vid.v vd
  390. my $template = 0b0101001_00000_10001_010_00000_1010111;
  391. my $vd = read_vreg shift;
  392. return ".word ".($template | ($vd << 7));
  393. }
  394. sub viota_m {
  395. # viota.m vd, vs2, vm
  396. my $template = 0b010100_0_00000_10000_010_00000_1010111;
  397. my $vd = read_vreg shift;
  398. my $vs2 = read_vreg shift;
  399. my $vm = read_mask_vreg shift;
  400. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  401. }
  402. sub vle8_v {
  403. # vle8.v vd, (rs1), vm
  404. my $template = 0b000000_0_00000_00000_000_00000_0000111;
  405. my $vd = read_vreg shift;
  406. my $rs1 = read_reg shift;
  407. my $vm = read_mask_vreg shift;
  408. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  409. }
  410. sub vle32_v {
  411. # vle32.v vd, (rs1), vm
  412. my $template = 0b000000_0_00000_00000_110_00000_0000111;
  413. my $vd = read_vreg shift;
  414. my $rs1 = read_reg shift;
  415. my $vm = read_mask_vreg shift;
  416. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  417. }
  418. sub vle64_v {
  419. # vle64.v vd, (rs1)
  420. my $template = 0b0000001_00000_00000_111_00000_0000111;
  421. my $vd = read_vreg shift;
  422. my $rs1 = read_reg shift;
  423. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  424. }
  425. sub vlse32_v {
  426. # vlse32.v vd, (rs1), rs2
  427. my $template = 0b0000101_00000_00000_110_00000_0000111;
  428. my $vd = read_vreg shift;
  429. my $rs1 = read_reg shift;
  430. my $rs2 = read_reg shift;
  431. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  432. }
  433. sub vlsseg_nf_e32_v {
  434. # vlsseg<nf>e32.v vd, (rs1), rs2
  435. my $template = 0b0000101_00000_00000_110_00000_0000111;
  436. my $nf = shift;
  437. $nf -= 1;
  438. my $vd = read_vreg shift;
  439. my $rs1 = read_reg shift;
  440. my $rs2 = read_reg shift;
  441. return ".word ".($template | ($nf << 29) | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  442. }
  443. sub vlse64_v {
  444. # vlse64.v vd, (rs1), rs2
  445. my $template = 0b0000101_00000_00000_111_00000_0000111;
  446. my $vd = read_vreg shift;
  447. my $rs1 = read_reg shift;
  448. my $rs2 = read_reg shift;
  449. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  450. }
  451. sub vluxei8_v {
  452. # vluxei8.v vd, (rs1), vs2, vm
  453. my $template = 0b000001_0_00000_00000_000_00000_0000111;
  454. my $vd = read_vreg shift;
  455. my $rs1 = read_reg shift;
  456. my $vs2 = read_vreg shift;
  457. my $vm = read_mask_vreg shift;
  458. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  459. }
  460. sub vmerge_vim {
  461. # vmerge.vim vd, vs2, imm, v0
  462. my $template = 0b0101110_00000_00000_011_00000_1010111;
  463. my $vd = read_vreg shift;
  464. my $vs2 = read_vreg shift;
  465. my $imm = shift;
  466. return ".word ".($template | ($vs2 << 20) | ($imm << 15) | ($vd << 7));
  467. }
  468. sub vmerge_vvm {
  469. # vmerge.vvm vd vs2 vs1
  470. my $template = 0b0101110_00000_00000_000_00000_1010111;
  471. my $vd = read_vreg shift;
  472. my $vs2 = read_vreg shift;
  473. my $vs1 = read_vreg shift;
  474. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7))
  475. }
  476. sub vmseq_vi {
  477. # vmseq.vi vd vs1, imm
  478. my $template = 0b0110001_00000_00000_011_00000_1010111;
  479. my $vd = read_vreg shift;
  480. my $vs1 = read_vreg shift;
  481. my $imm = shift;
  482. return ".word ".($template | ($vs1 << 20) | ($imm << 15) | ($vd << 7))
  483. }
  484. sub vmsgtu_vx {
  485. # vmsgtu.vx vd vs2, rs1, vm
  486. my $template = 0b011110_0_00000_00000_100_00000_1010111;
  487. my $vd = read_vreg shift;
  488. my $vs2 = read_vreg shift;
  489. my $rs1 = read_reg shift;
  490. my $vm = read_mask_vreg shift;
  491. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7))
  492. }
  493. sub vmv_v_i {
  494. # vmv.v.i vd, imm
  495. my $template = 0b0101111_00000_00000_011_00000_1010111;
  496. my $vd = read_vreg shift;
  497. my $imm = shift;
  498. return ".word ".($template | ($imm << 15) | ($vd << 7));
  499. }
  500. sub vmv_v_x {
  501. # vmv.v.x vd, rs1
  502. my $template = 0b0101111_00000_00000_100_00000_1010111;
  503. my $vd = read_vreg shift;
  504. my $rs1 = read_reg shift;
  505. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  506. }
  507. sub vmv_v_v {
  508. # vmv.v.v vd, vs1
  509. my $template = 0b0101111_00000_00000_000_00000_1010111;
  510. my $vd = read_vreg shift;
  511. my $vs1 = read_vreg shift;
  512. return ".word ".($template | ($vs1 << 15) | ($vd << 7));
  513. }
  514. sub vor_vv_v0t {
  515. # vor.vv vd, vs2, vs1, v0.t
  516. my $template = 0b0010100_00000_00000_000_00000_1010111;
  517. my $vd = read_vreg shift;
  518. my $vs2 = read_vreg shift;
  519. my $vs1 = read_vreg shift;
  520. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  521. }
  522. sub vse8_v {
  523. # vse8.v vd, (rs1), vm
  524. my $template = 0b000000_0_00000_00000_000_00000_0100111;
  525. my $vd = read_vreg shift;
  526. my $rs1 = read_reg shift;
  527. my $vm = read_mask_vreg shift;
  528. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  529. }
  530. sub vse32_v {
  531. # vse32.v vd, (rs1), vm
  532. my $template = 0b000000_0_00000_00000_110_00000_0100111;
  533. my $vd = read_vreg shift;
  534. my $rs1 = read_reg shift;
  535. my $vm = read_mask_vreg shift;
  536. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  537. }
  538. sub vssseg_nf_e32_v {
  539. # vssseg<nf>e32.v vs3, (rs1), rs2
  540. my $template = 0b0000101_00000_00000_110_00000_0100111;
  541. my $nf = shift;
  542. $nf -= 1;
  543. my $vs3 = read_vreg shift;
  544. my $rs1 = read_reg shift;
  545. my $rs2 = read_reg shift;
  546. return ".word ".($template | ($nf << 29) | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  547. }
  548. sub vsuxei8_v {
  549. # vsuxei8.v vs3, (rs1), vs2, vm
  550. my $template = 0b000001_0_00000_00000_000_00000_0100111;
  551. my $vs3 = read_vreg shift;
  552. my $rs1 = read_reg shift;
  553. my $vs2 = read_vreg shift;
  554. my $vm = read_mask_vreg shift;
  555. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  556. }
  557. sub vse64_v {
  558. # vse64.v vd, (rs1)
  559. my $template = 0b0000001_00000_00000_111_00000_0100111;
  560. my $vd = read_vreg shift;
  561. my $rs1 = read_reg shift;
  562. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  563. }
  564. sub vsetivli__x0_2_e64_m1_tu_mu {
  565. # vsetivli x0, 2, e64, m1, tu, mu
  566. return ".word 0xc1817057";
  567. }
  568. sub vsetivli__x0_4_e32_m1_tu_mu {
  569. # vsetivli x0, 4, e32, m1, tu, mu
  570. return ".word 0xc1027057";
  571. }
  572. sub vsetivli__x0_4_e64_m1_tu_mu {
  573. # vsetivli x0, 4, e64, m1, tu, mu
  574. return ".word 0xc1827057";
  575. }
  576. sub vsetivli__x0_8_e32_m1_tu_mu {
  577. # vsetivli x0, 8, e32, m1, tu, mu
  578. return ".word 0xc1047057";
  579. }
  580. sub vsetvli {
  581. # vsetvli rd, rs1, vtypei
  582. my $template = 0b0_00000000000_00000_111_00000_1010111;
  583. my $rd = read_reg shift;
  584. my $rs1 = read_reg shift;
  585. my $sew = read_sew shift;
  586. my $lmul = read_lmul shift;
  587. my $tail_policy = read_tail_policy shift;
  588. my $mask_policy = read_mask_policy shift;
  589. my $vtypei = ($mask_policy << 7) | ($tail_policy << 6) | ($sew << 3) | $lmul;
  590. return ".word ".($template | ($vtypei << 20) | ($rs1 << 15) | ($rd << 7));
  591. }
  592. sub vsetivli {
  593. # vsetvli rd, uimm, vtypei
  594. my $template = 0b11_0000000000_00000_111_00000_1010111;
  595. my $rd = read_reg shift;
  596. my $uimm = shift;
  597. my $sew = read_sew shift;
  598. my $lmul = read_lmul shift;
  599. my $tail_policy = read_tail_policy shift;
  600. my $mask_policy = read_mask_policy shift;
  601. my $vtypei = ($mask_policy << 7) | ($tail_policy << 6) | ($sew << 3) | $lmul;
  602. return ".word ".($template | ($vtypei << 20) | ($uimm << 15) | ($rd << 7));
  603. }
  604. sub vslidedown_vi {
  605. # vslidedown.vi vd, vs2, uimm
  606. my $template = 0b0011111_00000_00000_011_00000_1010111;
  607. my $vd = read_vreg shift;
  608. my $vs2 = read_vreg shift;
  609. my $uimm = shift;
  610. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  611. }
  612. sub vslidedown_vx {
  613. # vslidedown.vx vd, vs2, rs1
  614. my $template = 0b0011111_00000_00000_100_00000_1010111;
  615. my $vd = read_vreg shift;
  616. my $vs2 = read_vreg shift;
  617. my $rs1 = read_reg shift;
  618. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  619. }
  620. sub vslideup_vi_v0t {
  621. # vslideup.vi vd, vs2, uimm, v0.t
  622. my $template = 0b0011100_00000_00000_011_00000_1010111;
  623. my $vd = read_vreg shift;
  624. my $vs2 = read_vreg shift;
  625. my $uimm = shift;
  626. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  627. }
  628. sub vslideup_vi {
  629. # vslideup.vi vd, vs2, uimm
  630. my $template = 0b0011101_00000_00000_011_00000_1010111;
  631. my $vd = read_vreg shift;
  632. my $vs2 = read_vreg shift;
  633. my $uimm = shift;
  634. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  635. }
  636. sub vsll_vi {
  637. # vsll.vi vd, vs2, uimm, vm
  638. my $template = 0b1001011_00000_00000_011_00000_1010111;
  639. my $vd = read_vreg shift;
  640. my $vs2 = read_vreg shift;
  641. my $uimm = shift;
  642. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  643. }
  644. sub vsrl_vx {
  645. # vsrl.vx vd, vs2, rs1
  646. my $template = 0b1010001_00000_00000_100_00000_1010111;
  647. my $vd = read_vreg shift;
  648. my $vs2 = read_vreg shift;
  649. my $rs1 = read_reg shift;
  650. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  651. }
  652. sub vsse32_v {
  653. # vse32.v vs3, (rs1), rs2
  654. my $template = 0b0000101_00000_00000_110_00000_0100111;
  655. my $vs3 = read_vreg shift;
  656. my $rs1 = read_reg shift;
  657. my $rs2 = read_reg shift;
  658. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  659. }
  660. sub vsse64_v {
  661. # vsse64.v vs3, (rs1), rs2
  662. my $template = 0b0000101_00000_00000_111_00000_0100111;
  663. my $vs3 = read_vreg shift;
  664. my $rs1 = read_reg shift;
  665. my $rs2 = read_reg shift;
  666. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  667. }
  668. sub vxor_vv_v0t {
  669. # vxor.vv vd, vs2, vs1, v0.t
  670. my $template = 0b0010110_00000_00000_000_00000_1010111;
  671. my $vd = read_vreg shift;
  672. my $vs2 = read_vreg shift;
  673. my $vs1 = read_vreg shift;
  674. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  675. }
  676. sub vxor_vv {
  677. # vxor.vv vd, vs2, vs1
  678. my $template = 0b0010111_00000_00000_000_00000_1010111;
  679. my $vd = read_vreg shift;
  680. my $vs2 = read_vreg shift;
  681. my $vs1 = read_vreg shift;
  682. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  683. }
  684. sub vzext_vf2 {
  685. # vzext.vf2 vd, vs2, vm
  686. my $template = 0b010010_0_00000_00110_010_00000_1010111;
  687. my $vd = read_vreg shift;
  688. my $vs2 = read_vreg shift;
  689. my $vm = read_mask_vreg shift;
  690. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  691. }
  692. # Vector crypto instructions
  693. ## Zvbb and Zvkb instructions
  694. ##
  695. ## vandn (also in zvkb)
  696. ## vbrev
  697. ## vbrev8 (also in zvkb)
  698. ## vrev8 (also in zvkb)
  699. ## vclz
  700. ## vctz
  701. ## vcpop
  702. ## vrol (also in zvkb)
  703. ## vror (also in zvkb)
  704. ## vwsll
  705. sub vbrev8_v {
  706. # vbrev8.v vd, vs2, vm
  707. my $template = 0b010010_0_00000_01000_010_00000_1010111;
  708. my $vd = read_vreg shift;
  709. my $vs2 = read_vreg shift;
  710. my $vm = read_mask_vreg shift;
  711. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  712. }
  713. sub vrev8_v {
  714. # vrev8.v vd, vs2, vm
  715. my $template = 0b010010_0_00000_01001_010_00000_1010111;
  716. my $vd = read_vreg shift;
  717. my $vs2 = read_vreg shift;
  718. my $vm = read_mask_vreg shift;
  719. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  720. }
  721. sub vror_vi {
  722. # vror.vi vd, vs2, uimm
  723. my $template = 0b01010_0_1_00000_00000_011_00000_1010111;
  724. my $vd = read_vreg shift;
  725. my $vs2 = read_vreg shift;
  726. my $uimm = shift;
  727. my $uimm_i5 = $uimm >> 5;
  728. my $uimm_i4_0 = $uimm & 0b11111;
  729. return ".word ".($template | ($uimm_i5 << 26) | ($vs2 << 20) | ($uimm_i4_0 << 15) | ($vd << 7));
  730. }
  731. sub vwsll_vv {
  732. # vwsll.vv vd, vs2, vs1, vm
  733. my $template = 0b110101_0_00000_00000_000_00000_1010111;
  734. my $vd = read_vreg shift;
  735. my $vs2 = read_vreg shift;
  736. my $vs1 = read_vreg shift;
  737. my $vm = read_mask_vreg shift;
  738. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  739. }
  740. ## Zvbc instructions
  741. sub vclmulh_vx {
  742. # vclmulh.vx vd, vs2, rs1
  743. my $template = 0b0011011_00000_00000_110_00000_1010111;
  744. my $vd = read_vreg shift;
  745. my $vs2 = read_vreg shift;
  746. my $rs1 = read_reg shift;
  747. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  748. }
  749. sub vclmul_vx_v0t {
  750. # vclmul.vx vd, vs2, rs1, v0.t
  751. my $template = 0b0011000_00000_00000_110_00000_1010111;
  752. my $vd = read_vreg shift;
  753. my $vs2 = read_vreg shift;
  754. my $rs1 = read_reg shift;
  755. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  756. }
  757. sub vclmul_vx {
  758. # vclmul.vx vd, vs2, rs1
  759. my $template = 0b0011001_00000_00000_110_00000_1010111;
  760. my $vd = read_vreg shift;
  761. my $vs2 = read_vreg shift;
  762. my $rs1 = read_reg shift;
  763. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  764. }
  765. ## Zvkg instructions
  766. sub vghsh_vv {
  767. # vghsh.vv vd, vs2, vs1
  768. my $template = 0b1011001_00000_00000_010_00000_1110111;
  769. my $vd = read_vreg shift;
  770. my $vs2 = read_vreg shift;
  771. my $vs1 = read_vreg shift;
  772. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  773. }
  774. sub vgmul_vv {
  775. # vgmul.vv vd, vs2
  776. my $template = 0b1010001_00000_10001_010_00000_1110111;
  777. my $vd = read_vreg shift;
  778. my $vs2 = read_vreg shift;
  779. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  780. }
  781. ## Zvkned instructions
  782. sub vaesdf_vs {
  783. # vaesdf.vs vd, vs2
  784. my $template = 0b101001_1_00000_00001_010_00000_1110111;
  785. my $vd = read_vreg shift;
  786. my $vs2 = read_vreg shift;
  787. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  788. }
  789. sub vaesdm_vs {
  790. # vaesdm.vs vd, vs2
  791. my $template = 0b101001_1_00000_00000_010_00000_1110111;
  792. my $vd = read_vreg shift;
  793. my $vs2 = read_vreg shift;
  794. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  795. }
  796. sub vaesef_vs {
  797. # vaesef.vs vd, vs2
  798. my $template = 0b101001_1_00000_00011_010_00000_1110111;
  799. my $vd = read_vreg shift;
  800. my $vs2 = read_vreg shift;
  801. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  802. }
  803. sub vaesem_vs {
  804. # vaesem.vs vd, vs2
  805. my $template = 0b101001_1_00000_00010_010_00000_1110111;
  806. my $vd = read_vreg shift;
  807. my $vs2 = read_vreg shift;
  808. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  809. }
  810. sub vaeskf1_vi {
  811. # vaeskf1.vi vd, vs2, uimmm
  812. my $template = 0b100010_1_00000_00000_010_00000_1110111;
  813. my $vd = read_vreg shift;
  814. my $vs2 = read_vreg shift;
  815. my $uimm = shift;
  816. return ".word ".($template | ($uimm << 15) | ($vs2 << 20) | ($vd << 7));
  817. }
  818. sub vaeskf2_vi {
  819. # vaeskf2.vi vd, vs2, uimm
  820. my $template = 0b101010_1_00000_00000_010_00000_1110111;
  821. my $vd = read_vreg shift;
  822. my $vs2 = read_vreg shift;
  823. my $uimm = shift;
  824. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  825. }
  826. sub vaesz_vs {
  827. # vaesz.vs vd, vs2
  828. my $template = 0b101001_1_00000_00111_010_00000_1110111;
  829. my $vd = read_vreg shift;
  830. my $vs2 = read_vreg shift;
  831. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  832. }
  833. ## Zvknha and Zvknhb instructions
  834. sub vsha2ms_vv {
  835. # vsha2ms.vv vd, vs2, vs1
  836. my $template = 0b1011011_00000_00000_010_00000_1110111;
  837. my $vd = read_vreg shift;
  838. my $vs2 = read_vreg shift;
  839. my $vs1 = read_vreg shift;
  840. return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7));
  841. }
  842. sub vsha2ch_vv {
  843. # vsha2ch.vv vd, vs2, vs1
  844. my $template = 0b101110_10000_00000_001_00000_01110111;
  845. my $vd = read_vreg shift;
  846. my $vs2 = read_vreg shift;
  847. my $vs1 = read_vreg shift;
  848. return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7));
  849. }
  850. sub vsha2cl_vv {
  851. # vsha2cl.vv vd, vs2, vs1
  852. my $template = 0b101111_10000_00000_001_00000_01110111;
  853. my $vd = read_vreg shift;
  854. my $vs2 = read_vreg shift;
  855. my $vs1 = read_vreg shift;
  856. return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7));
  857. }
  858. ## Zvksed instructions
  859. sub vsm4k_vi {
  860. # vsm4k.vi vd, vs2, uimm
  861. my $template = 0b1000011_00000_00000_010_00000_1110111;
  862. my $vd = read_vreg shift;
  863. my $vs2 = read_vreg shift;
  864. my $uimm = shift;
  865. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  866. }
  867. sub vsm4r_vs {
  868. # vsm4r.vs vd, vs2
  869. my $template = 0b1010011_00000_10000_010_00000_1110111;
  870. my $vd = read_vreg shift;
  871. my $vs2 = read_vreg shift;
  872. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  873. }
  874. ## zvksh instructions
  875. sub vsm3c_vi {
  876. # vsm3c.vi vd, vs2, uimm
  877. my $template = 0b1010111_00000_00000_010_00000_1110111;
  878. my $vd = read_vreg shift;
  879. my $vs2 = read_vreg shift;
  880. my $uimm = shift;
  881. return ".word ".($template | ($vs2 << 20) | ($uimm << 15 ) | ($vd << 7));
  882. }
  883. sub vsm3me_vv {
  884. # vsm3me.vv vd, vs2, vs1
  885. my $template = 0b1000001_00000_00000_010_00000_1110111;
  886. my $vd = read_vreg shift;
  887. my $vs2 = read_vreg shift;
  888. my $vs1 = read_vreg shift;
  889. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15 ) | ($vd << 7));
  890. }
  891. 1;