riscv.pm 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  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. # All rights reserved.
  15. #
  16. # Redistribution and use in source and binary forms, with or without
  17. # modification, are permitted provided that the following conditions
  18. # are met:
  19. # 1. Redistributions of source code must retain the above copyright
  20. # notice, this list of conditions and the following disclaimer.
  21. # 2. Redistributions in binary form must reproduce the above copyright
  22. # notice, this list of conditions and the following disclaimer in the
  23. # documentation and/or other materials provided with the distribution.
  24. #
  25. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  28. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  29. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  30. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  31. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  35. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. use strict;
  37. use warnings;
  38. # Set $have_stacktrace to 1 if we have Devel::StackTrace
  39. my $have_stacktrace = 0;
  40. if (eval {require Devel::StackTrace;1;}) {
  41. $have_stacktrace = 1;
  42. }
  43. my @regs = map("x$_",(0..31));
  44. # Mapping from the RISC-V psABI ABI mnemonic names to the register number.
  45. my @regaliases = ('zero','ra','sp','gp','tp','t0','t1','t2','s0','s1',
  46. map("a$_",(0..7)),
  47. map("s$_",(2..11)),
  48. map("t$_",(3..6))
  49. );
  50. my %reglookup;
  51. @reglookup{@regs} = @regs;
  52. @reglookup{@regaliases} = @regs;
  53. # Takes a register name, possibly an alias, and converts it to a register index
  54. # from 0 to 31
  55. sub read_reg {
  56. my $reg = lc shift;
  57. if (!exists($reglookup{$reg})) {
  58. my $trace = "";
  59. if ($have_stacktrace) {
  60. $trace = Devel::StackTrace->new->as_string;
  61. }
  62. die("Unknown register ".$reg."\n".$trace);
  63. }
  64. my $regstr = $reglookup{$reg};
  65. if (!($regstr =~ /^x([0-9]+)$/)) {
  66. my $trace = "";
  67. if ($have_stacktrace) {
  68. $trace = Devel::StackTrace->new->as_string;
  69. }
  70. die("Could not process register ".$reg."\n".$trace);
  71. }
  72. return $1;
  73. }
  74. my @vregs = map("v$_",(0..31));
  75. my %vreglookup;
  76. @vreglookup{@vregs} = @vregs;
  77. sub read_vreg {
  78. my $vreg = lc shift;
  79. if (!exists($vreglookup{$vreg})) {
  80. my $trace = "";
  81. if ($have_stacktrace) {
  82. $trace = Devel::StackTrace->new->as_string;
  83. }
  84. die("Unknown vector register ".$vreg."\n".$trace);
  85. }
  86. if (!($vreg =~ /^v([0-9]+)$/)) {
  87. my $trace = "";
  88. if ($have_stacktrace) {
  89. $trace = Devel::StackTrace->new->as_string;
  90. }
  91. die("Could not process vector register ".$vreg."\n".$trace);
  92. }
  93. return $1;
  94. }
  95. # Helper functions
  96. sub brev8_rv64i {
  97. # brev8 without `brev8` instruction (only in Zbkb)
  98. # Bit-reverses the first argument and needs two scratch registers
  99. my $val = shift;
  100. my $t0 = shift;
  101. my $t1 = shift;
  102. my $brev8_const = shift;
  103. my $seq = <<___;
  104. la $brev8_const, Lbrev8_const
  105. ld $t0, 0($brev8_const) # 0xAAAAAAAAAAAAAAAA
  106. slli $t1, $val, 1
  107. and $t1, $t1, $t0
  108. and $val, $val, $t0
  109. srli $val, $val, 1
  110. or $val, $t1, $val
  111. ld $t0, 8($brev8_const) # 0xCCCCCCCCCCCCCCCC
  112. slli $t1, $val, 2
  113. and $t1, $t1, $t0
  114. and $val, $val, $t0
  115. srli $val, $val, 2
  116. or $val, $t1, $val
  117. ld $t0, 16($brev8_const) # 0xF0F0F0F0F0F0F0F0
  118. slli $t1, $val, 4
  119. and $t1, $t1, $t0
  120. and $val, $val, $t0
  121. srli $val, $val, 4
  122. or $val, $t1, $val
  123. ___
  124. return $seq;
  125. }
  126. sub sd_rev8_rv64i {
  127. # rev8 without `rev8` instruction (only in Zbb or Zbkb)
  128. # Stores the given value byte-reversed and needs one scratch register
  129. my $val = shift;
  130. my $addr = shift;
  131. my $off = shift;
  132. my $tmp = shift;
  133. my $off0 = ($off + 0);
  134. my $off1 = ($off + 1);
  135. my $off2 = ($off + 2);
  136. my $off3 = ($off + 3);
  137. my $off4 = ($off + 4);
  138. my $off5 = ($off + 5);
  139. my $off6 = ($off + 6);
  140. my $off7 = ($off + 7);
  141. my $seq = <<___;
  142. sb $val, $off7($addr)
  143. srli $tmp, $val, 8
  144. sb $tmp, $off6($addr)
  145. srli $tmp, $val, 16
  146. sb $tmp, $off5($addr)
  147. srli $tmp, $val, 24
  148. sb $tmp, $off4($addr)
  149. srli $tmp, $val, 32
  150. sb $tmp, $off3($addr)
  151. srli $tmp, $val, 40
  152. sb $tmp, $off2($addr)
  153. srli $tmp, $val, 48
  154. sb $tmp, $off1($addr)
  155. srli $tmp, $val, 56
  156. sb $tmp, $off0($addr)
  157. ___
  158. return $seq;
  159. }
  160. # Scalar crypto instructions
  161. sub aes64ds {
  162. # Encoding for aes64ds rd, rs1, rs2 instruction on RV64
  163. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  164. my $template = 0b0011101_00000_00000_000_00000_0110011;
  165. my $rd = read_reg shift;
  166. my $rs1 = read_reg shift;
  167. my $rs2 = read_reg shift;
  168. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  169. }
  170. sub aes64dsm {
  171. # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64
  172. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  173. my $template = 0b0011111_00000_00000_000_00000_0110011;
  174. my $rd = read_reg shift;
  175. my $rs1 = read_reg shift;
  176. my $rs2 = read_reg shift;
  177. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  178. }
  179. sub aes64es {
  180. # Encoding for aes64es rd, rs1, rs2 instruction on RV64
  181. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  182. my $template = 0b0011001_00000_00000_000_00000_0110011;
  183. my $rd = read_reg shift;
  184. my $rs1 = read_reg shift;
  185. my $rs2 = read_reg shift;
  186. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  187. }
  188. sub aes64esm {
  189. # Encoding for aes64esm rd, rs1, rs2 instruction on RV64
  190. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  191. my $template = 0b0011011_00000_00000_000_00000_0110011;
  192. my $rd = read_reg shift;
  193. my $rs1 = read_reg shift;
  194. my $rs2 = read_reg shift;
  195. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  196. }
  197. sub aes64im {
  198. # Encoding for aes64im rd, rs1 instruction on RV64
  199. # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX
  200. my $template = 0b001100000000_00000_001_00000_0010011;
  201. my $rd = read_reg shift;
  202. my $rs1 = read_reg shift;
  203. return ".word ".($template | ($rs1 << 15) | ($rd << 7));
  204. }
  205. sub aes64ks1i {
  206. # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64
  207. # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX
  208. my $template = 0b00110001_0000_00000_001_00000_0010011;
  209. my $rd = read_reg shift;
  210. my $rs1 = read_reg shift;
  211. my $rnum = shift;
  212. return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7));
  213. }
  214. sub aes64ks2 {
  215. # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64
  216. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  217. my $template = 0b0111111_00000_00000_000_00000_0110011;
  218. my $rd = read_reg shift;
  219. my $rs1 = read_reg shift;
  220. my $rs2 = read_reg shift;
  221. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  222. }
  223. sub brev8 {
  224. # brev8 rd, rs
  225. my $template = 0b011010000111_00000_101_00000_0010011;
  226. my $rd = read_reg shift;
  227. my $rs = read_reg shift;
  228. return ".word ".($template | ($rs << 15) | ($rd << 7));
  229. }
  230. sub clmul {
  231. # Encoding for clmul rd, rs1, rs2 instruction on RV64
  232. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  233. my $template = 0b0000101_00000_00000_001_00000_0110011;
  234. my $rd = read_reg shift;
  235. my $rs1 = read_reg shift;
  236. my $rs2 = read_reg shift;
  237. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  238. }
  239. sub clmulh {
  240. # Encoding for clmulh rd, rs1, rs2 instruction on RV64
  241. # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
  242. my $template = 0b0000101_00000_00000_011_00000_0110011;
  243. my $rd = read_reg shift;
  244. my $rs1 = read_reg shift;
  245. my $rs2 = read_reg shift;
  246. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
  247. }
  248. sub rev8 {
  249. # Encoding for rev8 rd, rs instruction on RV64
  250. # XXXXXXXXXXXXX_ rs _XXX_ rd _XXXXXXX
  251. my $template = 0b011010111000_00000_101_00000_0010011;
  252. my $rd = read_reg shift;
  253. my $rs = read_reg shift;
  254. return ".word ".($template | ($rs << 15) | ($rd << 7));
  255. }
  256. # Vector instructions
  257. sub vle32_v {
  258. # vle32.v vd, (rs1)
  259. my $template = 0b0000001_00000_00000_110_00000_0000111;
  260. my $vd = read_vreg shift;
  261. my $rs1 = read_reg shift;
  262. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  263. }
  264. sub vle64_v {
  265. # vle64.v vd, (rs1)
  266. my $template = 0b0000001_00000_00000_111_00000_0000111;
  267. my $vd = read_vreg shift;
  268. my $rs1 = read_reg shift;
  269. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  270. }
  271. sub vlse64_v {
  272. # vlse64.v vd, (rs1), rs2
  273. my $template = 0b0000101_00000_00000_111_00000_0000111;
  274. my $vd = read_vreg shift;
  275. my $rs1 = read_reg shift;
  276. my $rs2 = read_reg shift;
  277. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vd << 7));
  278. }
  279. sub vmerge_vim {
  280. # vmerge.vim vd, vs2, imm, v0
  281. my $template = 0b0101110_00000_00000_011_00000_1010111;
  282. my $vd = read_vreg shift;
  283. my $vs2 = read_vreg shift;
  284. my $imm = shift;
  285. return ".word ".($template | ($vs2 << 20) | ($imm << 15) | ($vd << 7));
  286. }
  287. sub vmv_v_i {
  288. # vmv.v.i vd, imm
  289. my $template = 0b0101111_00000_00000_011_00000_1010111;
  290. my $vd = read_vreg shift;
  291. my $imm = shift;
  292. return ".word ".($template | ($imm << 15) | ($vd << 7));
  293. }
  294. sub vmv_v_v {
  295. # vmv.v.v vd, vs1
  296. my $template = 0b0101111_00000_00000_000_00000_1010111;
  297. my $vd = read_vreg shift;
  298. my $vs1 = read_vreg shift;
  299. return ".word ".($template | ($vs1 << 15) | ($vd << 7));
  300. }
  301. sub vor_vv_v0t {
  302. # vor.vv vd, vs2, vs1, v0.t
  303. my $template = 0b0010100_00000_00000_000_00000_1010111;
  304. my $vd = read_vreg shift;
  305. my $vs2 = read_vreg shift;
  306. my $vs1 = read_vreg shift;
  307. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  308. }
  309. sub vse32_v {
  310. # vse32.v vd, (rs1)
  311. my $template = 0b0000001_00000_00000_110_00000_0100111;
  312. my $vd = read_vreg shift;
  313. my $rs1 = read_reg shift;
  314. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  315. }
  316. sub vse64_v {
  317. # vse64.v vd, (rs1)
  318. my $template = 0b0000001_00000_00000_111_00000_0100111;
  319. my $vd = read_vreg shift;
  320. my $rs1 = read_reg shift;
  321. return ".word ".($template | ($rs1 << 15) | ($vd << 7));
  322. }
  323. sub vsetivli__x0_2_e64_m1_tu_mu {
  324. # vsetivli x0, 2, e64, m1, tu, mu
  325. return ".word 0xc1817057";
  326. }
  327. sub vsetivli__x0_4_e32_m1_tu_mu {
  328. # vsetivli x0, 4, e32, m1, tu, mu
  329. return ".word 0xc1027057";
  330. }
  331. sub vslidedown_vi {
  332. # vslidedown.vi vd, vs2, uimm
  333. my $template = 0b0011111_00000_00000_011_00000_1010111;
  334. my $vd = read_vreg shift;
  335. my $vs2 = read_vreg shift;
  336. my $uimm = shift;
  337. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  338. }
  339. sub vslideup_vi_v0t {
  340. # vslideup.vi vd, vs2, uimm, v0.t
  341. my $template = 0b0011100_00000_00000_011_00000_1010111;
  342. my $vd = read_vreg shift;
  343. my $vs2 = read_vreg shift;
  344. my $uimm = shift;
  345. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  346. }
  347. sub vslideup_vi {
  348. # vslideup.vi vd, vs2, uimm
  349. my $template = 0b0011101_00000_00000_011_00000_1010111;
  350. my $vd = read_vreg shift;
  351. my $vs2 = read_vreg shift;
  352. my $uimm = shift;
  353. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  354. }
  355. sub vsll_vi {
  356. # vsll.vi vd, vs2, uimm, vm
  357. my $template = 0b1001011_00000_00000_011_00000_1010111;
  358. my $vd = read_vreg shift;
  359. my $vs2 = read_vreg shift;
  360. my $uimm = shift;
  361. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  362. }
  363. sub vsrl_vx {
  364. # vsrl.vx vd, vs2, rs1
  365. my $template = 0b1010001_00000_00000_100_00000_1010111;
  366. my $vd = read_vreg shift;
  367. my $vs2 = read_vreg shift;
  368. my $rs1 = read_reg shift;
  369. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  370. }
  371. sub vsse64_v {
  372. # vsse64.v vs3, (rs1), rs2
  373. my $template = 0b0000101_00000_00000_111_00000_0100111;
  374. my $vs3 = read_vreg shift;
  375. my $rs1 = read_reg shift;
  376. my $rs2 = read_reg shift;
  377. return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($vs3 << 7));
  378. }
  379. sub vxor_vv_v0t {
  380. # vxor.vv vd, vs2, vs1, v0.t
  381. my $template = 0b0010110_00000_00000_000_00000_1010111;
  382. my $vd = read_vreg shift;
  383. my $vs2 = read_vreg shift;
  384. my $vs1 = read_vreg shift;
  385. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  386. }
  387. sub vxor_vv {
  388. # vxor.vv vd, vs2, vs1
  389. my $template = 0b0010111_00000_00000_000_00000_1010111;
  390. my $vd = read_vreg shift;
  391. my $vs2 = read_vreg shift;
  392. my $vs1 = read_vreg shift;
  393. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  394. }
  395. # Vector crypto instructions
  396. ## Zvbb instructions
  397. sub vrev8_v {
  398. # vrev8.v vd, vs2
  399. my $template = 0b0100101_00000_01001_010_00000_1010111;
  400. my $vd = read_vreg shift;
  401. my $vs2 = read_vreg shift;
  402. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  403. }
  404. ## Zvbc instructions
  405. sub vclmulh_vx {
  406. # vclmulh.vx vd, vs2, rs1
  407. my $template = 0b0011011_00000_00000_110_00000_1010111;
  408. my $vd = read_vreg shift;
  409. my $vs2 = read_vreg shift;
  410. my $rs1 = read_reg shift;
  411. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  412. }
  413. sub vclmul_vx_v0t {
  414. # vclmul.vx vd, vs2, rs1, v0.t
  415. my $template = 0b0011000_00000_00000_110_00000_1010111;
  416. my $vd = read_vreg shift;
  417. my $vs2 = read_vreg shift;
  418. my $rs1 = read_reg shift;
  419. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  420. }
  421. sub vclmul_vx {
  422. # vclmul.vx vd, vs2, rs1
  423. my $template = 0b0011001_00000_00000_110_00000_1010111;
  424. my $vd = read_vreg shift;
  425. my $vs2 = read_vreg shift;
  426. my $rs1 = read_reg shift;
  427. return ".word ".($template | ($vs2 << 20) | ($rs1 << 15) | ($vd << 7));
  428. }
  429. ## Zvkg instructions
  430. sub vghsh_vv {
  431. # vghsh.vv vd, vs2, vs1
  432. my $template = 0b1011001_00000_00000_010_00000_1110111;
  433. my $vd = read_vreg shift;
  434. my $vs2 = read_vreg shift;
  435. my $vs1 = read_vreg shift;
  436. return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7));
  437. }
  438. sub vgmul_vv {
  439. # vgmul.vv vd, vs2
  440. my $template = 0b1010001_00000_10001_010_00000_1110111;
  441. my $vd = read_vreg shift;
  442. my $vs2 = read_vreg shift;
  443. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  444. }
  445. ## Zvkned instructions
  446. sub vaesdf_vs {
  447. # vaesdf.vs vd, vs2
  448. my $template = 0b101001_1_00000_00001_010_00000_1110111;
  449. my $vd = read_vreg shift;
  450. my $vs2 = read_vreg shift;
  451. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  452. }
  453. sub vaesdm_vs {
  454. # vaesdm.vs vd, vs2
  455. my $template = 0b101001_1_00000_00000_010_00000_1110111;
  456. my $vd = read_vreg shift;
  457. my $vs2 = read_vreg shift;
  458. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  459. }
  460. sub vaesef_vs {
  461. # vaesef.vs vd, vs2
  462. my $template = 0b101001_1_00000_00011_010_00000_1110111;
  463. my $vd = read_vreg shift;
  464. my $vs2 = read_vreg shift;
  465. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  466. }
  467. sub vaesem_vs {
  468. # vaesem.vs vd, vs2
  469. my $template = 0b101001_1_00000_00010_010_00000_1110111;
  470. my $vd = read_vreg shift;
  471. my $vs2 = read_vreg shift;
  472. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  473. }
  474. sub vaeskf1_vi {
  475. # vaeskf1.vi vd, vs2, uimmm
  476. my $template = 0b100010_1_00000_00000_010_00000_1110111;
  477. my $vd = read_vreg shift;
  478. my $vs2 = read_vreg shift;
  479. my $uimm = shift;
  480. return ".word ".($template | ($uimm << 15) | ($vs2 << 20) | ($vd << 7));
  481. }
  482. sub vaeskf2_vi {
  483. # vaeskf2.vi vd, vs2, uimm
  484. my $template = 0b101010_1_00000_00000_010_00000_1110111;
  485. my $vd = read_vreg shift;
  486. my $vs2 = read_vreg shift;
  487. my $uimm = shift;
  488. return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7));
  489. }
  490. sub vaesz_vs {
  491. # vaesz.vs vd, vs2
  492. my $template = 0b101001_1_00000_00111_010_00000_1110111;
  493. my $vd = read_vreg shift;
  494. my $vs2 = read_vreg shift;
  495. return ".word ".($template | ($vs2 << 20) | ($vd << 7));
  496. }
  497. 1;