riscv.pm 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  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. sub roriw {
  352. # Encoding for roriw rd, rs1, shamt instruction on RV64
  353. # XXXXXXX_ shamt _ rs1 _XXX_ rd _XXXXXXX
  354. my $template = 0b0110000_00000_00000_101_00000_0011011;
  355. my $rd = read_reg shift;
  356. my $rs1 = read_reg shift;
  357. my $shamt = shift;
  358. return ".word ".($template | ($shamt << 20) | ($rs1 << 15) | ($rd << 7));
  359. }
  360. sub maxu {
  361. # Encoding for maxu rd, rs1, rs2 instruction on RV64
  362. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  363. my $template = 0b0000101_00000_00000_111_00000_0110011;
  364. my $rd = read_reg shift;
  365. my $rs1 = read_reg shift;
  366. my $rs2 = read_reg shift;
  367. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  368. }
  369. sub minu {
  370. # Encoding for minu rd, rs1, rs2 instruction on RV64
  371. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  372. my $template = 0b0000101_00000_00000_101_00000_0110011;
  373. my $rd = read_reg shift;
  374. my $rs1 = read_reg shift;
  375. my $rs2 = read_reg shift;
  376. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  377. }
  378. # Vector instructions
  379. sub vadd_vv {
  380. # vadd.vv vd, vs2, vs1, vm
  381. my $template = 0b000000_0_00000_00000_000_00000_1010111;
  382. my $vd = read_vreg shift;
  383. my $vs2 = read_vreg shift;
  384. my $vs1 = read_vreg shift;
  385. my $vm = read_mask_vreg shift;
  386. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  387. }
  388. sub vadd_vx {
  389. # vadd.vx vd, vs2, rs1, vm
  390. my $template = 0b000000_0_00000_00000_100_00000_1010111;
  391. my $vd = read_vreg shift;
  392. my $vs2 = read_vreg shift;
  393. my $rs1 = read_reg shift;
  394. my $vm = read_mask_vreg shift;
  395. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  396. }
  397. sub vsub_vv {
  398. # vsub.vv vd, vs2, vs1, vm
  399. my $template = 0b000010_0_00000_00000_000_00000_1010111;
  400. my $vd = read_vreg shift;
  401. my $vs2 = read_vreg shift;
  402. my $vs1 = read_vreg shift;
  403. my $vm = read_mask_vreg shift;
  404. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  405. }
  406. sub vsub_vx {
  407. # vsub.vx vd, vs2, rs1, vm
  408. my $template = 0b000010_0_00000_00000_100_00000_1010111;
  409. my $vd = read_vreg shift;
  410. my $vs2 = read_vreg shift;
  411. my $rs1 = read_reg shift;
  412. my $vm = read_mask_vreg shift;
  413. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  414. }
  415. sub vid_v {
  416. # vid.v vd
  417. my $template = 0b0101001_00000_10001_010_00000_1010111;
  418. my $vd = read_vreg shift;
  419. return ".word ".($template | ($vd << 7));
  420. }
  421. sub viota_m {
  422. # viota.m vd, vs2, vm
  423. my $template = 0b010100_0_00000_10000_010_00000_1010111;
  424. my $vd = read_vreg shift;
  425. my $vs2 = read_vreg shift;
  426. my $vm = read_mask_vreg shift;
  427. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  428. }
  429. sub vle8_v {
  430. # vle8.v vd, (rs1), vm
  431. my $template = 0b000000_0_00000_00000_000_00000_0000111;
  432. my $vd = read_vreg shift;
  433. my $rs1 = read_reg shift;
  434. my $vm = read_mask_vreg shift;
  435. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  436. }
  437. sub vle32_v {
  438. # vle32.v vd, (rs1), vm
  439. my $template = 0b000000_0_00000_00000_110_00000_0000111;
  440. my $vd = read_vreg shift;
  441. my $rs1 = read_reg shift;
  442. my $vm = read_mask_vreg shift;
  443. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  444. }
  445. sub vle64_v {
  446. # vle64.v vd, (rs1)
  447. my $template = 0b0000001_00000_00000_111_00000_0000111;
  448. my $vd = read_vreg shift;
  449. my $rs1 = read_reg shift;
  450. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  451. }
  452. sub vlse32_v {
  453. # vlse32.v vd, (rs1), rs2
  454. my $template = 0b0000101_00000_00000_110_00000_0000111;
  455. my $vd = read_vreg shift;
  456. my $rs1 = read_reg shift;
  457. my $rs2 = read_reg shift;
  458. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  459. }
  460. sub vlsseg_nf_e32_v {
  461. # vlsseg<nf>e32.v vd, (rs1), rs2
  462. my $template = 0b0000101_00000_00000_110_00000_0000111;
  463. my $nf = shift;
  464. $nf -= 1;
  465. my $vd = read_vreg shift;
  466. my $rs1 = read_reg shift;
  467. my $rs2 = read_reg shift;
  468. return ".word ".($template | ($nf << 29) | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  469. }
  470. sub vlse64_v {
  471. # vlse64.v vd, (rs1), rs2
  472. my $template = 0b0000101_00000_00000_111_00000_0000111;
  473. my $vd = read_vreg shift;
  474. my $rs1 = read_reg shift;
  475. my $rs2 = read_reg shift;
  476. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  477. }
  478. sub vluxei8_v {
  479. # vluxei8.v vd, (rs1), vs2, vm
  480. my $template = 0b000001_0_00000_00000_000_00000_0000111;
  481. my $vd = read_vreg shift;
  482. my $rs1 = read_reg shift;
  483. my $vs2 = read_vreg shift;
  484. my $vm = read_mask_vreg shift;
  485. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  486. }
  487. sub vmerge_vim {
  488. # vmerge.vim vd, vs2, imm, v0
  489. my $template = 0b0101110_00000_00000_011_00000_1010111;
  490. my $vd = read_vreg shift;
  491. my $vs2 = read_vreg shift;
  492. my $imm = shift;
  493. return ".word ".($template | ($vs2 << 20) | ($imm << 15) | ($vd << 7));
  494. }
  495. sub vmerge_vvm {
  496. # vmerge.vvm vd vs2 vs1
  497. my $template = 0b0101110_00000_00000_000_00000_1010111;
  498. my $vd = read_vreg shift;
  499. my $vs2 = read_vreg shift;
  500. my $vs1 = read_vreg shift;
  501. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7))
  502. }
  503. sub vmseq_vi {
  504. # vmseq.vi vd vs1, imm
  505. my $template = 0b0110001_00000_00000_011_00000_1010111;
  506. my $vd = read_vreg shift;
  507. my $vs1 = read_vreg shift;
  508. my $imm = shift;
  509. return ".word ".($template | ($vs1 << 20) | ($imm << 15) | ($vd << 7))
  510. }
  511. sub vmsgtu_vx {
  512. # vmsgtu.vx vd vs2, rs1, vm
  513. my $template = 0b011110_0_00000_00000_100_00000_1010111;
  514. my $vd = read_vreg shift;
  515. my $vs2 = read_vreg shift;
  516. my $rs1 = read_reg shift;
  517. my $vm = read_mask_vreg shift;
  518. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7))
  519. }
  520. sub vmv_v_i {
  521. # vmv.v.i vd, imm
  522. my $template = 0b0101111_00000_00000_011_00000_1010111;
  523. my $vd = read_vreg shift;
  524. my $imm = shift;
  525. return ".word ".($template | ($imm << 15) | ($vd << 7));
  526. }
  527. sub vmv_v_x {
  528. # vmv.v.x vd, rs1
  529. my $template = 0b0101111_00000_00000_100_00000_1010111;
  530. my $vd = read_vreg shift;
  531. my $rs1 = read_reg shift;
  532. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  533. }
  534. sub vmv_v_v {
  535. # vmv.v.v vd, vs1
  536. my $template = 0b0101111_00000_00000_000_00000_1010111;
  537. my $vd = read_vreg shift;
  538. my $vs1 = read_vreg shift;
  539. return ".word ".($template | ($vs1 << 15) | ($vd << 7));
  540. }
  541. sub vor_vv_v0t {
  542. # vor.vv vd, vs2, vs1, v0.t
  543. my $template = 0b0010100_00000_00000_000_00000_1010111;
  544. my $vd = read_vreg shift;
  545. my $vs2 = read_vreg shift;
  546. my $vs1 = read_vreg shift;
  547. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  548. }
  549. sub vse8_v {
  550. # vse8.v vd, (rs1), vm
  551. my $template = 0b000000_0_00000_00000_000_00000_0100111;
  552. my $vd = read_vreg shift;
  553. my $rs1 = read_reg shift;
  554. my $vm = read_mask_vreg shift;
  555. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  556. }
  557. sub vse32_v {
  558. # vse32.v vd, (rs1), vm
  559. my $template = 0b000000_0_00000_00000_110_00000_0100111;
  560. my $vd = read_vreg shift;
  561. my $rs1 = read_reg shift;
  562. my $vm = read_mask_vreg shift;
  563. return ".word ".($template | ($vm << 25) | ($rs1 << 15) | ($vd << 7));
  564. }
  565. sub vssseg_nf_e32_v {
  566. # vssseg<nf>e32.v vs3, (rs1), rs2
  567. my $template = 0b0000101_00000_00000_110_00000_0100111;
  568. my $nf = shift;
  569. $nf -= 1;
  570. my $vs3 = read_vreg shift;
  571. my $rs1 = read_reg shift;
  572. my $rs2 = read_reg shift;
  573. return ".word ".($template | ($nf << 29) | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  574. }
  575. sub vsuxei8_v {
  576. # vsuxei8.v vs3, (rs1), vs2, vm
  577. my $template = 0b000001_0_00000_00000_000_00000_0100111;
  578. my $vs3 = read_vreg shift;
  579. my $rs1 = read_reg shift;
  580. my $vs2 = read_vreg shift;
  581. my $vm = read_mask_vreg shift;
  582. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  583. }
  584. sub vse64_v {
  585. # vse64.v vd, (rs1)
  586. my $template = 0b0000001_00000_00000_111_00000_0100111;
  587. my $vd = read_vreg shift;
  588. my $rs1 = read_reg shift;
  589. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  590. }
  591. sub vsetivli__x0_2_e64_m1_tu_mu {
  592. # vsetivli x0, 2, e64, m1, tu, mu
  593. return ".word 0xc1817057";
  594. }
  595. sub vsetivli__x0_4_e32_m1_tu_mu {
  596. # vsetivli x0, 4, e32, m1, tu, mu
  597. return ".word 0xc1027057";
  598. }
  599. sub vsetivli__x0_4_e64_m1_tu_mu {
  600. # vsetivli x0, 4, e64, m1, tu, mu
  601. return ".word 0xc1827057";
  602. }
  603. sub vsetivli__x0_8_e32_m1_tu_mu {
  604. # vsetivli x0, 8, e32, m1, tu, mu
  605. return ".word 0xc1047057";
  606. }
  607. sub vsetvli {
  608. # vsetvli rd, rs1, vtypei
  609. my $template = 0b0_00000000000_00000_111_00000_1010111;
  610. my $rd = read_reg shift;
  611. my $rs1 = read_reg shift;
  612. my $sew = read_sew shift;
  613. my $lmul = read_lmul shift;
  614. my $tail_policy = read_tail_policy shift;
  615. my $mask_policy = read_mask_policy shift;
  616. my $vtypei = ($mask_policy << 7) | ($tail_policy << 6) | ($sew << 3) | $lmul;
  617. return ".word ".($template | ($vtypei << 20) | ($rs1 << 15) | ($rd << 7));
  618. }
  619. sub vsetivli {
  620. # vsetvli rd, uimm, vtypei
  621. my $template = 0b11_0000000000_00000_111_00000_1010111;
  622. my $rd = read_reg shift;
  623. my $uimm = shift;
  624. my $sew = read_sew shift;
  625. my $lmul = read_lmul shift;
  626. my $tail_policy = read_tail_policy shift;
  627. my $mask_policy = read_mask_policy shift;
  628. my $vtypei = ($mask_policy << 7) | ($tail_policy << 6) | ($sew << 3) | $lmul;
  629. return ".word ".($template | ($vtypei << 20) | ($uimm << 15) | ($rd << 7));
  630. }
  631. sub vslidedown_vi {
  632. # vslidedown.vi vd, vs2, uimm
  633. my $template = 0b0011111_00000_00000_011_00000_1010111;
  634. my $vd = read_vreg shift;
  635. my $vs2 = read_vreg shift;
  636. my $uimm = shift;
  637. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  638. }
  639. sub vslidedown_vx {
  640. # vslidedown.vx vd, vs2, rs1
  641. my $template = 0b0011111_00000_00000_100_00000_1010111;
  642. my $vd = read_vreg shift;
  643. my $vs2 = read_vreg shift;
  644. my $rs1 = read_reg shift;
  645. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  646. }
  647. sub vslideup_vi_v0t {
  648. # vslideup.vi vd, vs2, uimm, v0.t
  649. my $template = 0b0011100_00000_00000_011_00000_1010111;
  650. my $vd = read_vreg shift;
  651. my $vs2 = read_vreg shift;
  652. my $uimm = shift;
  653. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  654. }
  655. sub vslideup_vi {
  656. # vslideup.vi vd, vs2, uimm
  657. my $template = 0b0011101_00000_00000_011_00000_1010111;
  658. my $vd = read_vreg shift;
  659. my $vs2 = read_vreg shift;
  660. my $uimm = shift;
  661. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  662. }
  663. sub vsll_vi {
  664. # vsll.vi vd, vs2, uimm, vm
  665. my $template = 0b1001011_00000_00000_011_00000_1010111;
  666. my $vd = read_vreg shift;
  667. my $vs2 = read_vreg shift;
  668. my $uimm = shift;
  669. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  670. }
  671. sub vsrl_vx {
  672. # vsrl.vx vd, vs2, rs1
  673. my $template = 0b1010001_00000_00000_100_00000_1010111;
  674. my $vd = read_vreg shift;
  675. my $vs2 = read_vreg shift;
  676. my $rs1 = read_reg shift;
  677. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  678. }
  679. sub vsse32_v {
  680. # vse32.v vs3, (rs1), rs2
  681. my $template = 0b0000101_00000_00000_110_00000_0100111;
  682. my $vs3 = read_vreg shift;
  683. my $rs1 = read_reg shift;
  684. my $rs2 = read_reg shift;
  685. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  686. }
  687. sub vsse64_v {
  688. # vsse64.v vs3, (rs1), rs2
  689. my $template = 0b0000101_00000_00000_111_00000_0100111;
  690. my $vs3 = read_vreg shift;
  691. my $rs1 = read_reg shift;
  692. my $rs2 = read_reg shift;
  693. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  694. }
  695. sub vxor_vv_v0t {
  696. # vxor.vv vd, vs2, vs1, v0.t
  697. my $template = 0b0010110_00000_00000_000_00000_1010111;
  698. my $vd = read_vreg shift;
  699. my $vs2 = read_vreg shift;
  700. my $vs1 = read_vreg shift;
  701. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  702. }
  703. sub vxor_vv {
  704. # vxor.vv vd, vs2, vs1
  705. my $template = 0b0010111_00000_00000_000_00000_1010111;
  706. my $vd = read_vreg shift;
  707. my $vs2 = read_vreg shift;
  708. my $vs1 = read_vreg shift;
  709. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  710. }
  711. sub vzext_vf2 {
  712. # vzext.vf2 vd, vs2, vm
  713. my $template = 0b010010_0_00000_00110_010_00000_1010111;
  714. my $vd = read_vreg shift;
  715. my $vs2 = read_vreg shift;
  716. my $vm = read_mask_vreg shift;
  717. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  718. }
  719. # Vector crypto instructions
  720. ## Zvbb and Zvkb instructions
  721. ##
  722. ## vandn (also in zvkb)
  723. ## vbrev
  724. ## vbrev8 (also in zvkb)
  725. ## vrev8 (also in zvkb)
  726. ## vclz
  727. ## vctz
  728. ## vcpop
  729. ## vrol (also in zvkb)
  730. ## vror (also in zvkb)
  731. ## vwsll
  732. sub vbrev8_v {
  733. # vbrev8.v vd, vs2, vm
  734. my $template = 0b010010_0_00000_01000_010_00000_1010111;
  735. my $vd = read_vreg shift;
  736. my $vs2 = read_vreg shift;
  737. my $vm = read_mask_vreg shift;
  738. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  739. }
  740. sub vrev8_v {
  741. # vrev8.v vd, vs2, vm
  742. my $template = 0b010010_0_00000_01001_010_00000_1010111;
  743. my $vd = read_vreg shift;
  744. my $vs2 = read_vreg shift;
  745. my $vm = read_mask_vreg shift;
  746. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vd << 7));
  747. }
  748. sub vror_vi {
  749. # vror.vi vd, vs2, uimm
  750. my $template = 0b01010_0_1_00000_00000_011_00000_1010111;
  751. my $vd = read_vreg shift;
  752. my $vs2 = read_vreg shift;
  753. my $uimm = shift;
  754. my $uimm_i5 = $uimm >> 5;
  755. my $uimm_i4_0 = $uimm & 0b11111;
  756. return ".word ".($template | ($uimm_i5 << 26) | ($vs2 << 20) | ($uimm_i4_0 << 15) | ($vd << 7));
  757. }
  758. sub vwsll_vv {
  759. # vwsll.vv vd, vs2, vs1, vm
  760. my $template = 0b110101_0_00000_00000_000_00000_1010111;
  761. my $vd = read_vreg shift;
  762. my $vs2 = read_vreg shift;
  763. my $vs1 = read_vreg shift;
  764. my $vm = read_mask_vreg shift;
  765. return ".word ".($template | ($vm << 25) | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  766. }
  767. ## Zvbc instructions
  768. sub vclmulh_vx {
  769. # vclmulh.vx vd, vs2, rs1
  770. my $template = 0b0011011_00000_00000_110_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. sub vclmul_vx_v0t {
  777. # vclmul.vx vd, vs2, rs1, v0.t
  778. my $template = 0b0011000_00000_00000_110_00000_1010111;
  779. my $vd = read_vreg shift;
  780. my $vs2 = read_vreg shift;
  781. my $rs1 = read_reg shift;
  782. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  783. }
  784. sub vclmul_vx {
  785. # vclmul.vx vd, vs2, rs1
  786. my $template = 0b0011001_00000_00000_110_00000_1010111;
  787. my $vd = read_vreg shift;
  788. my $vs2 = read_vreg shift;
  789. my $rs1 = read_reg shift;
  790. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  791. }
  792. ## Zvkg instructions
  793. sub vghsh_vv {
  794. # vghsh.vv vd, vs2, vs1
  795. my $template = 0b1011001_00000_00000_010_00000_1110111;
  796. my $vd = read_vreg shift;
  797. my $vs2 = read_vreg shift;
  798. my $vs1 = read_vreg shift;
  799. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  800. }
  801. sub vgmul_vv {
  802. # vgmul.vv vd, vs2
  803. my $template = 0b1010001_00000_10001_010_00000_1110111;
  804. my $vd = read_vreg shift;
  805. my $vs2 = read_vreg shift;
  806. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  807. }
  808. ## Zvkned instructions
  809. sub vaesdf_vs {
  810. # vaesdf.vs vd, vs2
  811. my $template = 0b101001_1_00000_00001_010_00000_1110111;
  812. my $vd = read_vreg shift;
  813. my $vs2 = read_vreg shift;
  814. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  815. }
  816. sub vaesdm_vs {
  817. # vaesdm.vs vd, vs2
  818. my $template = 0b101001_1_00000_00000_010_00000_1110111;
  819. my $vd = read_vreg shift;
  820. my $vs2 = read_vreg shift;
  821. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  822. }
  823. sub vaesef_vs {
  824. # vaesef.vs vd, vs2
  825. my $template = 0b101001_1_00000_00011_010_00000_1110111;
  826. my $vd = read_vreg shift;
  827. my $vs2 = read_vreg shift;
  828. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  829. }
  830. sub vaesem_vs {
  831. # vaesem.vs vd, vs2
  832. my $template = 0b101001_1_00000_00010_010_00000_1110111;
  833. my $vd = read_vreg shift;
  834. my $vs2 = read_vreg shift;
  835. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  836. }
  837. sub vaeskf1_vi {
  838. # vaeskf1.vi vd, vs2, uimmm
  839. my $template = 0b100010_1_00000_00000_010_00000_1110111;
  840. my $vd = read_vreg shift;
  841. my $vs2 = read_vreg shift;
  842. my $uimm = shift;
  843. return ".word ".($template | ($uimm << 15) | ($vs2 << 20) | ($vd << 7));
  844. }
  845. sub vaeskf2_vi {
  846. # vaeskf2.vi vd, vs2, uimm
  847. my $template = 0b101010_1_00000_00000_010_00000_1110111;
  848. my $vd = read_vreg shift;
  849. my $vs2 = read_vreg shift;
  850. my $uimm = shift;
  851. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  852. }
  853. sub vaesz_vs {
  854. # vaesz.vs vd, vs2
  855. my $template = 0b101001_1_00000_00111_010_00000_1110111;
  856. my $vd = read_vreg shift;
  857. my $vs2 = read_vreg shift;
  858. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  859. }
  860. ## Zvknha and Zvknhb instructions
  861. sub vsha2ms_vv {
  862. # vsha2ms.vv vd, vs2, vs1
  863. my $template = 0b1011011_00000_00000_010_00000_1110111;
  864. my $vd = read_vreg shift;
  865. my $vs2 = read_vreg shift;
  866. my $vs1 = read_vreg shift;
  867. return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7));
  868. }
  869. sub vsha2ch_vv {
  870. # vsha2ch.vv vd, vs2, vs1
  871. my $template = 0b101110_10000_00000_001_00000_01110111;
  872. my $vd = read_vreg shift;
  873. my $vs2 = read_vreg shift;
  874. my $vs1 = read_vreg shift;
  875. return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7));
  876. }
  877. sub vsha2cl_vv {
  878. # vsha2cl.vv vd, vs2, vs1
  879. my $template = 0b101111_10000_00000_001_00000_01110111;
  880. my $vd = read_vreg shift;
  881. my $vs2 = read_vreg shift;
  882. my $vs1 = read_vreg shift;
  883. return ".word ".($template | ($vs2 << 20)| ($vs1 << 15 )| ($vd << 7));
  884. }
  885. ## Zvksed instructions
  886. sub vsm4k_vi {
  887. # vsm4k.vi vd, vs2, uimm
  888. my $template = 0b1000011_00000_00000_010_00000_1110111;
  889. my $vd = read_vreg shift;
  890. my $vs2 = read_vreg shift;
  891. my $uimm = shift;
  892. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  893. }
  894. sub vsm4r_vs {
  895. # vsm4r.vs vd, vs2
  896. my $template = 0b1010011_00000_10000_010_00000_1110111;
  897. my $vd = read_vreg shift;
  898. my $vs2 = read_vreg shift;
  899. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  900. }
  901. ## zvksh instructions
  902. sub vsm3c_vi {
  903. # vsm3c.vi vd, vs2, uimm
  904. my $template = 0b1010111_00000_00000_010_00000_1110111;
  905. my $vd = read_vreg shift;
  906. my $vs2 = read_vreg shift;
  907. my $uimm = shift;
  908. return ".word ".($template | ($vs2 << 20) | ($uimm << 15 ) | ($vd << 7));
  909. }
  910. sub vsm3me_vv {
  911. # vsm3me.vv vd, vs2, vs1
  912. my $template = 0b1000001_00000_00000_010_00000_1110111;
  913. my $vd = read_vreg shift;
  914. my $vs2 = read_vreg shift;
  915. my $vs1 = read_vreg shift;
  916. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15 ) | ($vd << 7));
  917. }
  918. 1;