2
0

aesfx-sparcv9.pl 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. #! /usr/bin/env perl
  2. # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License 2.0 (the "License"). You may not use
  5. # this file except in compliance with the License. You can obtain a copy
  6. # in the file LICENSE in the source distribution or at
  7. # https://www.openssl.org/source/license.html
  8. #
  9. # ====================================================================
  10. # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
  11. # project. The module is, however, dual licensed under OpenSSL and
  12. # CRYPTOGAMS licenses depending on where you obtain it. For further
  13. # details see http://www.openssl.org/~appro/cryptogams/.
  14. # ====================================================================
  15. # March 2016
  16. #
  17. # Initial support for Fujitsu SPARC64 X/X+ comprises minimally
  18. # required key setup and single-block procedures.
  19. #
  20. # April 2016
  21. #
  22. # Add "teaser" CBC and CTR mode-specific subroutines. "Teaser" means
  23. # that parallelizable nature of CBC decrypt and CTR is not utilized
  24. # yet. CBC encrypt on the other hand is as good as it can possibly
  25. # get processing one byte in 4.1 cycles with 128-bit key on SPARC64 X.
  26. # This is ~6x faster than pure software implementation...
  27. #
  28. # July 2016
  29. #
  30. # Switch from faligndata to fshiftorx, which allows to omit alignaddr
  31. # instructions and improve single-block and short-input performance
  32. # with misaligned data.
  33. $output = pop and open STDOUT,">$output";
  34. {
  35. my ($inp,$out,$key,$rounds,$tmp,$mask) = map("%o$_",(0..5));
  36. $code.=<<___;
  37. #ifndef __ASSEMBLER__
  38. # define __ASSEMBLER__ 1
  39. #endif
  40. #include "crypto/sparc_arch.h"
  41. #define LOCALS (STACK_BIAS+STACK_FRAME)
  42. .text
  43. .globl aes_fx_encrypt
  44. .align 32
  45. aes_fx_encrypt:
  46. and $inp, 7, $tmp ! is input aligned?
  47. andn $inp, 7, $inp
  48. ldd [$key + 0], %f6 ! round[0]
  49. ldd [$key + 8], %f8
  50. mov %o7, %g1
  51. ld [$key + 240], $rounds
  52. 1: call .+8
  53. add %o7, .Linp_align-1b, %o7
  54. sll $tmp, 3, $tmp
  55. ldd [$inp + 0], %f0 ! load input
  56. brz,pt $tmp, .Lenc_inp_aligned
  57. ldd [$inp + 8], %f2
  58. ldd [%o7 + $tmp], %f14 ! shift left params
  59. ldd [$inp + 16], %f4
  60. fshiftorx %f0, %f2, %f14, %f0
  61. fshiftorx %f2, %f4, %f14, %f2
  62. .Lenc_inp_aligned:
  63. ldd [$key + 16], %f10 ! round[1]
  64. ldd [$key + 24], %f12
  65. fxor %f0, %f6, %f0 ! ^=round[0]
  66. fxor %f2, %f8, %f2
  67. ldd [$key + 32], %f6 ! round[2]
  68. ldd [$key + 40], %f8
  69. add $key, 32, $key
  70. sub $rounds, 4, $rounds
  71. .Loop_enc:
  72. fmovd %f0, %f4
  73. faesencx %f2, %f10, %f0
  74. faesencx %f4, %f12, %f2
  75. ldd [$key + 16], %f10
  76. ldd [$key + 24], %f12
  77. add $key, 32, $key
  78. fmovd %f0, %f4
  79. faesencx %f2, %f6, %f0
  80. faesencx %f4, %f8, %f2
  81. ldd [$key + 0], %f6
  82. ldd [$key + 8], %f8
  83. brnz,a $rounds, .Loop_enc
  84. sub $rounds, 2, $rounds
  85. andcc $out, 7, $tmp ! is output aligned?
  86. andn $out, 7, $out
  87. mov 0xff, $mask
  88. srl $mask, $tmp, $mask
  89. add %o7, 64, %o7
  90. sll $tmp, 3, $tmp
  91. fmovd %f0, %f4
  92. faesencx %f2, %f10, %f0
  93. faesencx %f4, %f12, %f2
  94. ldd [%o7 + $tmp], %f14 ! shift right params
  95. fmovd %f0, %f4
  96. faesenclx %f2, %f6, %f0
  97. faesenclx %f4, %f8, %f2
  98. bnz,pn %icc, .Lenc_out_unaligned
  99. mov %g1, %o7
  100. std %f0, [$out + 0]
  101. retl
  102. std %f2, [$out + 8]
  103. .align 16
  104. .Lenc_out_unaligned:
  105. add $out, 16, $inp
  106. orn %g0, $mask, $tmp
  107. fshiftorx %f0, %f0, %f14, %f4
  108. fshiftorx %f0, %f2, %f14, %f6
  109. fshiftorx %f2, %f2, %f14, %f8
  110. stda %f4, [$out + $mask]0xc0 ! partial store
  111. std %f6, [$out + 8]
  112. stda %f8, [$inp + $tmp]0xc0 ! partial store
  113. retl
  114. nop
  115. .type aes_fx_encrypt,#function
  116. .size aes_fx_encrypt,.-aes_fx_encrypt
  117. .globl aes_fx_decrypt
  118. .align 32
  119. aes_fx_decrypt:
  120. and $inp, 7, $tmp ! is input aligned?
  121. andn $inp, 7, $inp
  122. ldd [$key + 0], %f6 ! round[0]
  123. ldd [$key + 8], %f8
  124. mov %o7, %g1
  125. ld [$key + 240], $rounds
  126. 1: call .+8
  127. add %o7, .Linp_align-1b, %o7
  128. sll $tmp, 3, $tmp
  129. ldd [$inp + 0], %f0 ! load input
  130. brz,pt $tmp, .Ldec_inp_aligned
  131. ldd [$inp + 8], %f2
  132. ldd [%o7 + $tmp], %f14 ! shift left params
  133. ldd [$inp + 16], %f4
  134. fshiftorx %f0, %f2, %f14, %f0
  135. fshiftorx %f2, %f4, %f14, %f2
  136. .Ldec_inp_aligned:
  137. ldd [$key + 16], %f10 ! round[1]
  138. ldd [$key + 24], %f12
  139. fxor %f0, %f6, %f0 ! ^=round[0]
  140. fxor %f2, %f8, %f2
  141. ldd [$key + 32], %f6 ! round[2]
  142. ldd [$key + 40], %f8
  143. add $key, 32, $key
  144. sub $rounds, 4, $rounds
  145. .Loop_dec:
  146. fmovd %f0, %f4
  147. faesdecx %f2, %f10, %f0
  148. faesdecx %f4, %f12, %f2
  149. ldd [$key + 16], %f10
  150. ldd [$key + 24], %f12
  151. add $key, 32, $key
  152. fmovd %f0, %f4
  153. faesdecx %f2, %f6, %f0
  154. faesdecx %f4, %f8, %f2
  155. ldd [$key + 0], %f6
  156. ldd [$key + 8], %f8
  157. brnz,a $rounds, .Loop_dec
  158. sub $rounds, 2, $rounds
  159. andcc $out, 7, $tmp ! is output aligned?
  160. andn $out, 7, $out
  161. mov 0xff, $mask
  162. srl $mask, $tmp, $mask
  163. add %o7, 64, %o7
  164. sll $tmp, 3, $tmp
  165. fmovd %f0, %f4
  166. faesdecx %f2, %f10, %f0
  167. faesdecx %f4, %f12, %f2
  168. ldd [%o7 + $tmp], %f14 ! shift right params
  169. fmovd %f0, %f4
  170. faesdeclx %f2, %f6, %f0
  171. faesdeclx %f4, %f8, %f2
  172. bnz,pn %icc, .Ldec_out_unaligned
  173. mov %g1, %o7
  174. std %f0, [$out + 0]
  175. retl
  176. std %f2, [$out + 8]
  177. .align 16
  178. .Ldec_out_unaligned:
  179. add $out, 16, $inp
  180. orn %g0, $mask, $tmp
  181. fshiftorx %f0, %f0, %f14, %f4
  182. fshiftorx %f0, %f2, %f14, %f6
  183. fshiftorx %f2, %f2, %f14, %f8
  184. stda %f4, [$out + $mask]0xc0 ! partial store
  185. std %f6, [$out + 8]
  186. stda %f8, [$inp + $tmp]0xc0 ! partial store
  187. retl
  188. nop
  189. .type aes_fx_decrypt,#function
  190. .size aes_fx_decrypt,.-aes_fx_decrypt
  191. ___
  192. }
  193. {
  194. my ($inp,$bits,$out,$tmp,$inc) = map("%o$_",(0..5));
  195. $code.=<<___;
  196. .globl aes_fx_set_decrypt_key
  197. .align 32
  198. aes_fx_set_decrypt_key:
  199. b .Lset_encrypt_key
  200. mov -1, $inc
  201. retl
  202. nop
  203. .type aes_fx_set_decrypt_key,#function
  204. .size aes_fx_set_decrypt_key,.-aes_fx_set_decrypt_key
  205. .globl aes_fx_set_encrypt_key
  206. .align 32
  207. aes_fx_set_encrypt_key:
  208. mov 1, $inc
  209. nop
  210. .Lset_encrypt_key:
  211. and $inp, 7, $tmp
  212. andn $inp, 7, $inp
  213. sll $tmp, 3, $tmp
  214. mov %o7, %g1
  215. 1: call .+8
  216. add %o7, .Linp_align-1b, %o7
  217. ldd [%o7 + $tmp], %f10 ! shift left params
  218. mov %g1, %o7
  219. cmp $bits, 192
  220. ldd [$inp + 0], %f0
  221. bl,pt %icc, .L128
  222. ldd [$inp + 8], %f2
  223. be,pt %icc, .L192
  224. ldd [$inp + 16], %f4
  225. brz,pt $tmp, .L256aligned
  226. ldd [$inp + 24], %f6
  227. ldd [$inp + 32], %f8
  228. fshiftorx %f0, %f2, %f10, %f0
  229. fshiftorx %f2, %f4, %f10, %f2
  230. fshiftorx %f4, %f6, %f10, %f4
  231. fshiftorx %f6, %f8, %f10, %f6
  232. .L256aligned:
  233. mov 14, $bits
  234. and $inc, `14*16`, $tmp
  235. st $bits, [$out + 240] ! store rounds
  236. add $out, $tmp, $out ! start or end of key schedule
  237. sllx $inc, 4, $inc ! 16 or -16
  238. ___
  239. for ($i=0; $i<6; $i++) {
  240. $code.=<<___;
  241. std %f0, [$out + 0]
  242. faeskeyx %f6, `0x10+$i`, %f0
  243. std %f2, [$out + 8]
  244. add $out, $inc, $out
  245. faeskeyx %f0, 0x00, %f2
  246. std %f4, [$out + 0]
  247. faeskeyx %f2, 0x01, %f4
  248. std %f6, [$out + 8]
  249. add $out, $inc, $out
  250. faeskeyx %f4, 0x00, %f6
  251. ___
  252. }
  253. $code.=<<___;
  254. std %f0, [$out + 0]
  255. faeskeyx %f6, `0x10+$i`, %f0
  256. std %f2, [$out + 8]
  257. add $out, $inc, $out
  258. faeskeyx %f0, 0x00, %f2
  259. std %f4,[$out + 0]
  260. std %f6,[$out + 8]
  261. add $out, $inc, $out
  262. std %f0,[$out + 0]
  263. std %f2,[$out + 8]
  264. retl
  265. xor %o0, %o0, %o0 ! return 0
  266. .align 16
  267. .L192:
  268. brz,pt $tmp, .L192aligned
  269. nop
  270. ldd [$inp + 24], %f6
  271. fshiftorx %f0, %f2, %f10, %f0
  272. fshiftorx %f2, %f4, %f10, %f2
  273. fshiftorx %f4, %f6, %f10, %f4
  274. .L192aligned:
  275. mov 12, $bits
  276. and $inc, `12*16`, $tmp
  277. st $bits, [$out + 240] ! store rounds
  278. add $out, $tmp, $out ! start or end of key schedule
  279. sllx $inc, 4, $inc ! 16 or -16
  280. ___
  281. for ($i=0; $i<8; $i+=2) {
  282. $code.=<<___;
  283. std %f0, [$out + 0]
  284. faeskeyx %f4, `0x10+$i`, %f0
  285. std %f2, [$out + 8]
  286. add $out, $inc, $out
  287. faeskeyx %f0, 0x00, %f2
  288. std %f4, [$out + 0]
  289. faeskeyx %f2, 0x00, %f4
  290. std %f0, [$out + 8]
  291. add $out, $inc, $out
  292. faeskeyx %f4, `0x10+$i+1`, %f0
  293. std %f2, [$out + 0]
  294. faeskeyx %f0, 0x00, %f2
  295. std %f4, [$out + 8]
  296. add $out, $inc, $out
  297. ___
  298. $code.=<<___ if ($i<6);
  299. faeskeyx %f2, 0x00, %f4
  300. ___
  301. }
  302. $code.=<<___;
  303. std %f0, [$out + 0]
  304. std %f2, [$out + 8]
  305. retl
  306. xor %o0, %o0, %o0 ! return 0
  307. .align 16
  308. .L128:
  309. brz,pt $tmp, .L128aligned
  310. nop
  311. ldd [$inp + 16], %f4
  312. fshiftorx %f0, %f2, %f10, %f0
  313. fshiftorx %f2, %f4, %f10, %f2
  314. .L128aligned:
  315. mov 10, $bits
  316. and $inc, `10*16`, $tmp
  317. st $bits, [$out + 240] ! store rounds
  318. add $out, $tmp, $out ! start or end of key schedule
  319. sllx $inc, 4, $inc ! 16 or -16
  320. ___
  321. for ($i=0; $i<10; $i++) {
  322. $code.=<<___;
  323. std %f0, [$out + 0]
  324. faeskeyx %f2, `0x10+$i`, %f0
  325. std %f2, [$out + 8]
  326. add $out, $inc, $out
  327. faeskeyx %f0, 0x00, %f2
  328. ___
  329. }
  330. $code.=<<___;
  331. std %f0, [$out + 0]
  332. std %f2, [$out + 8]
  333. retl
  334. xor %o0, %o0, %o0 ! return 0
  335. .type aes_fx_set_encrypt_key,#function
  336. .size aes_fx_set_encrypt_key,.-aes_fx_set_encrypt_key
  337. ___
  338. }
  339. {
  340. my ($inp,$out,$len,$key,$ivp,$dir) = map("%i$_",(0..5));
  341. my ($rounds,$inner,$end,$inc,$ialign,$oalign,$mask) = map("%l$_",(0..7));
  342. my ($iv0,$iv1,$r0hi,$r0lo,$rlhi,$rllo,$in0,$in1,$intail,$outhead,$fshift)
  343. = map("%f$_",grep { !($_ & 1) } (16 .. 62));
  344. my ($ileft,$iright) = ($ialign,$oalign);
  345. $code.=<<___;
  346. .globl aes_fx_cbc_encrypt
  347. .align 32
  348. aes_fx_cbc_encrypt:
  349. save %sp, -STACK_FRAME-16, %sp
  350. srln $len, 4, $len
  351. and $inp, 7, $ialign
  352. andn $inp, 7, $inp
  353. brz,pn $len, .Lcbc_no_data
  354. sll $ialign, 3, $ileft
  355. 1: call .+8
  356. add %o7, .Linp_align-1b, %o7
  357. ld [$key + 240], $rounds
  358. and $out, 7, $oalign
  359. ld [$ivp + 0], %f0 ! load ivec
  360. andn $out, 7, $out
  361. ld [$ivp + 4], %f1
  362. sll $oalign, 3, $mask
  363. ld [$ivp + 8], %f2
  364. ld [$ivp + 12], %f3
  365. sll $rounds, 4, $rounds
  366. add $rounds, $key, $end
  367. ldd [$key + 0], $r0hi ! round[0]
  368. ldd [$key + 8], $r0lo
  369. add $inp, 16, $inp
  370. sub $len, 1, $len
  371. ldd [$end + 0], $rlhi ! round[last]
  372. ldd [$end + 8], $rllo
  373. mov 16, $inc
  374. movrz $len, 0, $inc
  375. ldd [$key + 16], %f10 ! round[1]
  376. ldd [$key + 24], %f12
  377. ldd [%o7 + $ileft], $fshift ! shift left params
  378. add %o7, 64, %o7
  379. ldd [$inp - 16], $in0 ! load input
  380. ldd [$inp - 8], $in1
  381. ldda [$inp]0x82, $intail ! non-faulting load
  382. brz $dir, .Lcbc_decrypt
  383. add $inp, $inc, $inp ! inp+=16
  384. fxor $r0hi, %f0, %f0 ! ivec^=round[0]
  385. fxor $r0lo, %f2, %f2
  386. fshiftorx $in0, $in1, $fshift, $in0
  387. fshiftorx $in1, $intail, $fshift, $in1
  388. nop
  389. .Loop_cbc_enc:
  390. fxor $in0, %f0, %f0 ! inp^ivec^round[0]
  391. fxor $in1, %f2, %f2
  392. ldd [$key + 32], %f6 ! round[2]
  393. ldd [$key + 40], %f8
  394. add $key, 32, $end
  395. sub $rounds, 16*6, $inner
  396. .Lcbc_enc:
  397. fmovd %f0, %f4
  398. faesencx %f2, %f10, %f0
  399. faesencx %f4, %f12, %f2
  400. ldd [$end + 16], %f10
  401. ldd [$end + 24], %f12
  402. add $end, 32, $end
  403. fmovd %f0, %f4
  404. faesencx %f2, %f6, %f0
  405. faesencx %f4, %f8, %f2
  406. ldd [$end + 0], %f6
  407. ldd [$end + 8], %f8
  408. brnz,a $inner, .Lcbc_enc
  409. sub $inner, 16*2, $inner
  410. fmovd %f0, %f4
  411. faesencx %f2, %f10, %f0
  412. faesencx %f4, %f12, %f2
  413. ldd [$end + 16], %f10 ! round[last-1]
  414. ldd [$end + 24], %f12
  415. movrz $len, 0, $inc
  416. fmovd $intail, $in0
  417. ldd [$inp - 8], $in1 ! load next input block
  418. ldda [$inp]0x82, $intail ! non-faulting load
  419. add $inp, $inc, $inp ! inp+=16
  420. fmovd %f0, %f4
  421. faesencx %f2, %f6, %f0
  422. faesencx %f4, %f8, %f2
  423. fshiftorx $in0, $in1, $fshift, $in0
  424. fshiftorx $in1, $intail, $fshift, $in1
  425. fmovd %f0, %f4
  426. faesencx %f2, %f10, %f0
  427. faesencx %f4, %f12, %f2
  428. ldd [$key + 16], %f10 ! round[1]
  429. ldd [$key + 24], %f12
  430. fxor $r0hi, $in0, $in0 ! inp^=round[0]
  431. fxor $r0lo, $in1, $in1
  432. fmovd %f0, %f4
  433. faesenclx %f2, $rlhi, %f0
  434. faesenclx %f4, $rllo, %f2
  435. brnz,pn $oalign, .Lcbc_enc_unaligned_out
  436. nop
  437. std %f0, [$out + 0]
  438. std %f2, [$out + 8]
  439. add $out, 16, $out
  440. brnz,a $len, .Loop_cbc_enc
  441. sub $len, 1, $len
  442. st %f0, [$ivp + 0] ! output ivec
  443. st %f1, [$ivp + 4]
  444. st %f2, [$ivp + 8]
  445. st %f3, [$ivp + 12]
  446. .Lcbc_no_data:
  447. ret
  448. restore
  449. .align 32
  450. .Lcbc_enc_unaligned_out:
  451. ldd [%o7 + $mask], $fshift ! shift right params
  452. mov 0xff, $mask
  453. srl $mask, $oalign, $mask
  454. sub %g0, $ileft, $iright
  455. fshiftorx %f0, %f0, $fshift, %f6
  456. fshiftorx %f0, %f2, $fshift, %f8
  457. stda %f6, [$out + $mask]0xc0 ! partial store
  458. orn %g0, $mask, $mask
  459. std %f8, [$out + 8]
  460. add $out, 16, $out
  461. brz $len, .Lcbc_enc_unaligned_out_done
  462. sub $len, 1, $len
  463. b .Loop_cbc_enc_unaligned_out
  464. nop
  465. .align 32
  466. .Loop_cbc_enc_unaligned_out:
  467. fmovd %f2, $outhead
  468. fxor $in0, %f0, %f0 ! inp^ivec^round[0]
  469. fxor $in1, %f2, %f2
  470. ldd [$key + 32], %f6 ! round[2]
  471. ldd [$key + 40], %f8
  472. fmovd %f0, %f4
  473. faesencx %f2, %f10, %f0
  474. faesencx %f4, %f12, %f2
  475. ldd [$key + 48], %f10 ! round[3]
  476. ldd [$key + 56], %f12
  477. ldx [$inp - 16], %o0
  478. ldx [$inp - 8], %o1
  479. brz $ileft, .Lcbc_enc_aligned_inp
  480. movrz $len, 0, $inc
  481. ldx [$inp], %o2
  482. sllx %o0, $ileft, %o0
  483. srlx %o1, $iright, %g1
  484. sllx %o1, $ileft, %o1
  485. or %g1, %o0, %o0
  486. srlx %o2, $iright, %o2
  487. or %o2, %o1, %o1
  488. .Lcbc_enc_aligned_inp:
  489. fmovd %f0, %f4
  490. faesencx %f2, %f6, %f0
  491. faesencx %f4, %f8, %f2
  492. ldd [$key + 64], %f6 ! round[4]
  493. ldd [$key + 72], %f8
  494. add $key, 64, $end
  495. sub $rounds, 16*8, $inner
  496. stx %o0, [%sp + LOCALS + 0]
  497. stx %o1, [%sp + LOCALS + 8]
  498. add $inp, $inc, $inp ! inp+=16
  499. nop
  500. .Lcbc_enc_unaligned:
  501. fmovd %f0, %f4
  502. faesencx %f2, %f10, %f0
  503. faesencx %f4, %f12, %f2
  504. ldd [$end + 16], %f10
  505. ldd [$end + 24], %f12
  506. add $end, 32, $end
  507. fmovd %f0, %f4
  508. faesencx %f2, %f6, %f0
  509. faesencx %f4, %f8, %f2
  510. ldd [$end + 0], %f6
  511. ldd [$end + 8], %f8
  512. brnz,a $inner, .Lcbc_enc_unaligned
  513. sub $inner, 16*2, $inner
  514. fmovd %f0, %f4
  515. faesencx %f2, %f10, %f0
  516. faesencx %f4, %f12, %f2
  517. ldd [$end + 16], %f10 ! round[last-1]
  518. ldd [$end + 24], %f12
  519. fmovd %f0, %f4
  520. faesencx %f2, %f6, %f0
  521. faesencx %f4, %f8, %f2
  522. ldd [%sp + LOCALS + 0], $in0
  523. ldd [%sp + LOCALS + 8], $in1
  524. fmovd %f0, %f4
  525. faesencx %f2, %f10, %f0
  526. faesencx %f4, %f12, %f2
  527. ldd [$key + 16], %f10 ! round[1]
  528. ldd [$key + 24], %f12
  529. fxor $r0hi, $in0, $in0 ! inp^=round[0]
  530. fxor $r0lo, $in1, $in1
  531. fmovd %f0, %f4
  532. faesenclx %f2, $rlhi, %f0
  533. faesenclx %f4, $rllo, %f2
  534. fshiftorx $outhead, %f0, $fshift, %f6
  535. fshiftorx %f0, %f2, $fshift, %f8
  536. std %f6, [$out + 0]
  537. std %f8, [$out + 8]
  538. add $out, 16, $out
  539. brnz,a $len, .Loop_cbc_enc_unaligned_out
  540. sub $len, 1, $len
  541. .Lcbc_enc_unaligned_out_done:
  542. fshiftorx %f2, %f2, $fshift, %f8
  543. stda %f8, [$out + $mask]0xc0 ! partial store
  544. st %f0, [$ivp + 0] ! output ivec
  545. st %f1, [$ivp + 4]
  546. st %f2, [$ivp + 8]
  547. st %f3, [$ivp + 12]
  548. ret
  549. restore
  550. .align 32
  551. .Lcbc_decrypt:
  552. fshiftorx $in0, $in1, $fshift, $in0
  553. fshiftorx $in1, $intail, $fshift, $in1
  554. fmovd %f0, $iv0
  555. fmovd %f2, $iv1
  556. .Loop_cbc_dec:
  557. fxor $in0, $r0hi, %f0 ! inp^round[0]
  558. fxor $in1, $r0lo, %f2
  559. ldd [$key + 32], %f6 ! round[2]
  560. ldd [$key + 40], %f8
  561. add $key, 32, $end
  562. sub $rounds, 16*6, $inner
  563. .Lcbc_dec:
  564. fmovd %f0, %f4
  565. faesdecx %f2, %f10, %f0
  566. faesdecx %f4, %f12, %f2
  567. ldd [$end + 16], %f10
  568. ldd [$end + 24], %f12
  569. add $end, 32, $end
  570. fmovd %f0, %f4
  571. faesdecx %f2, %f6, %f0
  572. faesdecx %f4, %f8, %f2
  573. ldd [$end + 0], %f6
  574. ldd [$end + 8], %f8
  575. brnz,a $inner, .Lcbc_dec
  576. sub $inner, 16*2, $inner
  577. fmovd %f0, %f4
  578. faesdecx %f2, %f10, %f0
  579. faesdecx %f4, %f12, %f2
  580. ldd [$end + 16], %f10 ! round[last-1]
  581. ldd [$end + 24], %f12
  582. fmovd %f0, %f4
  583. faesdecx %f2, %f6, %f0
  584. faesdecx %f4, %f8, %f2
  585. fxor $iv0, $rlhi, %f6 ! ivec^round[last]
  586. fxor $iv1, $rllo, %f8
  587. fmovd $in0, $iv0
  588. fmovd $in1, $iv1
  589. movrz $len, 0, $inc
  590. fmovd $intail, $in0
  591. ldd [$inp - 8], $in1 ! load next input block
  592. ldda [$inp]0x82, $intail ! non-faulting load
  593. add $inp, $inc, $inp ! inp+=16
  594. fmovd %f0, %f4
  595. faesdecx %f2, %f10, %f0
  596. faesdecx %f4, %f12, %f2
  597. ldd [$key + 16], %f10 ! round[1]
  598. ldd [$key + 24], %f12
  599. fshiftorx $in0, $in1, $fshift, $in0
  600. fshiftorx $in1, $intail, $fshift, $in1
  601. fmovd %f0, %f4
  602. faesdeclx %f2, %f6, %f0
  603. faesdeclx %f4, %f8, %f2
  604. brnz,pn $oalign, .Lcbc_dec_unaligned_out
  605. nop
  606. std %f0, [$out + 0]
  607. std %f2, [$out + 8]
  608. add $out, 16, $out
  609. brnz,a $len, .Loop_cbc_dec
  610. sub $len, 1, $len
  611. st $iv0, [$ivp + 0] ! output ivec
  612. st $iv0#lo, [$ivp + 4]
  613. st $iv1, [$ivp + 8]
  614. st $iv1#lo, [$ivp + 12]
  615. ret
  616. restore
  617. .align 32
  618. .Lcbc_dec_unaligned_out:
  619. ldd [%o7 + $mask], $fshift ! shift right params
  620. mov 0xff, $mask
  621. srl $mask, $oalign, $mask
  622. sub %g0, $ileft, $iright
  623. fshiftorx %f0, %f0, $fshift, %f6
  624. fshiftorx %f0, %f2, $fshift, %f8
  625. stda %f6, [$out + $mask]0xc0 ! partial store
  626. orn %g0, $mask, $mask
  627. std %f8, [$out + 8]
  628. add $out, 16, $out
  629. brz $len, .Lcbc_dec_unaligned_out_done
  630. sub $len, 1, $len
  631. b .Loop_cbc_dec_unaligned_out
  632. nop
  633. .align 32
  634. .Loop_cbc_dec_unaligned_out:
  635. fmovd %f2, $outhead
  636. fxor $in0, $r0hi, %f0 ! inp^round[0]
  637. fxor $in1, $r0lo, %f2
  638. ldd [$key + 32], %f6 ! round[2]
  639. ldd [$key + 40], %f8
  640. fmovd %f0, %f4
  641. faesdecx %f2, %f10, %f0
  642. faesdecx %f4, %f12, %f2
  643. ldd [$key + 48], %f10 ! round[3]
  644. ldd [$key + 56], %f12
  645. ldx [$inp - 16], %o0
  646. ldx [$inp - 8], %o1
  647. brz $ileft, .Lcbc_dec_aligned_inp
  648. movrz $len, 0, $inc
  649. ldx [$inp], %o2
  650. sllx %o0, $ileft, %o0
  651. srlx %o1, $iright, %g1
  652. sllx %o1, $ileft, %o1
  653. or %g1, %o0, %o0
  654. srlx %o2, $iright, %o2
  655. or %o2, %o1, %o1
  656. .Lcbc_dec_aligned_inp:
  657. fmovd %f0, %f4
  658. faesdecx %f2, %f6, %f0
  659. faesdecx %f4, %f8, %f2
  660. ldd [$key + 64], %f6 ! round[4]
  661. ldd [$key + 72], %f8
  662. add $key, 64, $end
  663. sub $rounds, 16*8, $inner
  664. stx %o0, [%sp + LOCALS + 0]
  665. stx %o1, [%sp + LOCALS + 8]
  666. add $inp, $inc, $inp ! inp+=16
  667. nop
  668. .Lcbc_dec_unaligned:
  669. fmovd %f0, %f4
  670. faesdecx %f2, %f10, %f0
  671. faesdecx %f4, %f12, %f2
  672. ldd [$end + 16], %f10
  673. ldd [$end + 24], %f12
  674. add $end, 32, $end
  675. fmovd %f0, %f4
  676. faesdecx %f2, %f6, %f0
  677. faesdecx %f4, %f8, %f2
  678. ldd [$end + 0], %f6
  679. ldd [$end + 8], %f8
  680. brnz,a $inner, .Lcbc_dec_unaligned
  681. sub $inner, 16*2, $inner
  682. fmovd %f0, %f4
  683. faesdecx %f2, %f10, %f0
  684. faesdecx %f4, %f12, %f2
  685. ldd [$end + 16], %f10 ! round[last-1]
  686. ldd [$end + 24], %f12
  687. fmovd %f0, %f4
  688. faesdecx %f2, %f6, %f0
  689. faesdecx %f4, %f8, %f2
  690. fxor $iv0, $rlhi, %f6 ! ivec^round[last]
  691. fxor $iv1, $rllo, %f8
  692. fmovd $in0, $iv0
  693. fmovd $in1, $iv1
  694. ldd [%sp + LOCALS + 0], $in0
  695. ldd [%sp + LOCALS + 8], $in1
  696. fmovd %f0, %f4
  697. faesdecx %f2, %f10, %f0
  698. faesdecx %f4, %f12, %f2
  699. ldd [$key + 16], %f10 ! round[1]
  700. ldd [$key + 24], %f12
  701. fmovd %f0, %f4
  702. faesdeclx %f2, %f6, %f0
  703. faesdeclx %f4, %f8, %f2
  704. fshiftorx $outhead, %f0, $fshift, %f6
  705. fshiftorx %f0, %f2, $fshift, %f8
  706. std %f6, [$out + 0]
  707. std %f8, [$out + 8]
  708. add $out, 16, $out
  709. brnz,a $len, .Loop_cbc_dec_unaligned_out
  710. sub $len, 1, $len
  711. .Lcbc_dec_unaligned_out_done:
  712. fshiftorx %f2, %f2, $fshift, %f8
  713. stda %f8, [$out + $mask]0xc0 ! partial store
  714. st $iv0, [$ivp + 0] ! output ivec
  715. st $iv0#lo, [$ivp + 4]
  716. st $iv1, [$ivp + 8]
  717. st $iv1#lo, [$ivp + 12]
  718. ret
  719. restore
  720. .type aes_fx_cbc_encrypt,#function
  721. .size aes_fx_cbc_encrypt,.-aes_fx_cbc_encrypt
  722. ___
  723. }
  724. {
  725. my ($inp,$out,$len,$key,$ivp) = map("%i$_",(0..5));
  726. my ($rounds,$inner,$end,$inc,$ialign,$oalign,$mask) = map("%l$_",(0..7));
  727. my ($ctr0,$ctr1,$r0hi,$r0lo,$rlhi,$rllo,$in0,$in1,$intail,$outhead,$fshift)
  728. = map("%f$_",grep { !($_ & 1) } (16 .. 62));
  729. my ($ileft,$iright) = ($ialign, $oalign);
  730. my $one = "%f14";
  731. $code.=<<___;
  732. .globl aes_fx_ctr32_encrypt_blocks
  733. .align 32
  734. aes_fx_ctr32_encrypt_blocks:
  735. save %sp, -STACK_FRAME-16, %sp
  736. srln $len, 0, $len
  737. and $inp, 7, $ialign
  738. andn $inp, 7, $inp
  739. brz,pn $len, .Lctr32_no_data
  740. sll $ialign, 3, $ileft
  741. .Lpic: call .+8
  742. add %o7, .Linp_align - .Lpic, %o7
  743. ld [$key + 240], $rounds
  744. and $out, 7, $oalign
  745. ld [$ivp + 0], $ctr0 ! load counter
  746. andn $out, 7, $out
  747. ld [$ivp + 4], $ctr0#lo
  748. sll $oalign, 3, $mask
  749. ld [$ivp + 8], $ctr1
  750. ld [$ivp + 12], $ctr1#lo
  751. ldd [%o7 + 128], $one
  752. sll $rounds, 4, $rounds
  753. add $rounds, $key, $end
  754. ldd [$key + 0], $r0hi ! round[0]
  755. ldd [$key + 8], $r0lo
  756. add $inp, 16, $inp
  757. sub $len, 1, $len
  758. ldd [$key + 16], %f10 ! round[1]
  759. ldd [$key + 24], %f12
  760. mov 16, $inc
  761. movrz $len, 0, $inc
  762. ldd [$end + 0], $rlhi ! round[last]
  763. ldd [$end + 8], $rllo
  764. ldd [%o7 + $ileft], $fshift ! shiftleft params
  765. add %o7, 64, %o7
  766. ldd [$inp - 16], $in0 ! load input
  767. ldd [$inp - 8], $in1
  768. ldda [$inp]0x82, $intail ! non-faulting load
  769. add $inp, $inc, $inp ! inp+=16
  770. fshiftorx $in0, $in1, $fshift, $in0
  771. fshiftorx $in1, $intail, $fshift, $in1
  772. .Loop_ctr32:
  773. fxor $ctr0, $r0hi, %f0 ! counter^round[0]
  774. fxor $ctr1, $r0lo, %f2
  775. ldd [$key + 32], %f6 ! round[2]
  776. ldd [$key + 40], %f8
  777. add $key, 32, $end
  778. sub $rounds, 16*6, $inner
  779. .Lctr32_enc:
  780. fmovd %f0, %f4
  781. faesencx %f2, %f10, %f0
  782. faesencx %f4, %f12, %f2
  783. ldd [$end + 16], %f10
  784. ldd [$end + 24], %f12
  785. add $end, 32, $end
  786. fmovd %f0, %f4
  787. faesencx %f2, %f6, %f0
  788. faesencx %f4, %f8, %f2
  789. ldd [$end + 0], %f6
  790. ldd [$end + 8], %f8
  791. brnz,a $inner, .Lctr32_enc
  792. sub $inner, 16*2, $inner
  793. fmovd %f0, %f4
  794. faesencx %f2, %f10, %f0
  795. faesencx %f4, %f12, %f2
  796. ldd [$end + 16], %f10 ! round[last-1]
  797. ldd [$end + 24], %f12
  798. fmovd %f0, %f4
  799. faesencx %f2, %f6, %f0
  800. faesencx %f4, %f8, %f2
  801. fxor $in0, $rlhi, %f6 ! inp^round[last]
  802. fxor $in1, $rllo, %f8
  803. movrz $len, 0, $inc
  804. fmovd $intail, $in0
  805. ldd [$inp - 8], $in1 ! load next input block
  806. ldda [$inp]0x82, $intail ! non-faulting load
  807. add $inp, $inc, $inp ! inp+=16
  808. fmovd %f0, %f4
  809. faesencx %f2, %f10, %f0
  810. faesencx %f4, %f12, %f2
  811. ldd [$key + 16], %f10 ! round[1]
  812. ldd [$key + 24], %f12
  813. fshiftorx $in0, $in1, $fshift, $in0
  814. fshiftorx $in1, $intail, $fshift, $in1
  815. fpadd32 $ctr1, $one, $ctr1 ! increment counter
  816. fmovd %f0, %f4
  817. faesenclx %f2, %f6, %f0
  818. faesenclx %f4, %f8, %f2
  819. brnz,pn $oalign, .Lctr32_unaligned_out
  820. nop
  821. std %f0, [$out + 0]
  822. std %f2, [$out + 8]
  823. add $out, 16, $out
  824. brnz,a $len, .Loop_ctr32
  825. sub $len, 1, $len
  826. .Lctr32_no_data:
  827. ret
  828. restore
  829. .align 32
  830. .Lctr32_unaligned_out:
  831. ldd [%o7 + $mask], $fshift ! shift right params
  832. mov 0xff, $mask
  833. srl $mask, $oalign, $mask
  834. sub %g0, $ileft, $iright
  835. fshiftorx %f0, %f0, $fshift, %f6
  836. fshiftorx %f0, %f2, $fshift, %f8
  837. stda %f6, [$out + $mask]0xc0 ! partial store
  838. orn %g0, $mask, $mask
  839. std %f8, [$out + 8]
  840. add $out, 16, $out
  841. brz $len, .Lctr32_unaligned_out_done
  842. sub $len, 1, $len
  843. b .Loop_ctr32_unaligned_out
  844. nop
  845. .align 32
  846. .Loop_ctr32_unaligned_out:
  847. fmovd %f2, $outhead
  848. fxor $ctr0, $r0hi, %f0 ! counter^round[0]
  849. fxor $ctr1, $r0lo, %f2
  850. ldd [$key + 32], %f6 ! round[2]
  851. ldd [$key + 40], %f8
  852. fmovd %f0, %f4
  853. faesencx %f2, %f10, %f0
  854. faesencx %f4, %f12, %f2
  855. ldd [$key + 48], %f10 ! round[3]
  856. ldd [$key + 56], %f12
  857. ldx [$inp - 16], %o0
  858. ldx [$inp - 8], %o1
  859. brz $ileft, .Lctr32_aligned_inp
  860. movrz $len, 0, $inc
  861. ldx [$inp], %o2
  862. sllx %o0, $ileft, %o0
  863. srlx %o1, $iright, %g1
  864. sllx %o1, $ileft, %o1
  865. or %g1, %o0, %o0
  866. srlx %o2, $iright, %o2
  867. or %o2, %o1, %o1
  868. .Lctr32_aligned_inp:
  869. fmovd %f0, %f4
  870. faesencx %f2, %f6, %f0
  871. faesencx %f4, %f8, %f2
  872. ldd [$key + 64], %f6 ! round[4]
  873. ldd [$key + 72], %f8
  874. add $key, 64, $end
  875. sub $rounds, 16*8, $inner
  876. stx %o0, [%sp + LOCALS + 0]
  877. stx %o1, [%sp + LOCALS + 8]
  878. add $inp, $inc, $inp ! inp+=16
  879. nop
  880. .Lctr32_enc_unaligned:
  881. fmovd %f0, %f4
  882. faesencx %f2, %f10, %f0
  883. faesencx %f4, %f12, %f2
  884. ldd [$end + 16], %f10
  885. ldd [$end + 24], %f12
  886. add $end, 32, $end
  887. fmovd %f0, %f4
  888. faesencx %f2, %f6, %f0
  889. faesencx %f4, %f8, %f2
  890. ldd [$end + 0], %f6
  891. ldd [$end + 8], %f8
  892. brnz,a $inner, .Lctr32_enc_unaligned
  893. sub $inner, 16*2, $inner
  894. fmovd %f0, %f4
  895. faesencx %f2, %f10, %f0
  896. faesencx %f4, %f12, %f2
  897. ldd [$end + 16], %f10 ! round[last-1]
  898. ldd [$end + 24], %f12
  899. fpadd32 $ctr1, $one, $ctr1 ! increment counter
  900. fmovd %f0, %f4
  901. faesencx %f2, %f6, %f0
  902. faesencx %f4, %f8, %f2
  903. fxor $in0, $rlhi, %f6 ! inp^round[last]
  904. fxor $in1, $rllo, %f8
  905. ldd [%sp + LOCALS + 0], $in0
  906. ldd [%sp + LOCALS + 8], $in1
  907. fmovd %f0, %f4
  908. faesencx %f2, %f10, %f0
  909. faesencx %f4, %f12, %f2
  910. ldd [$key + 16], %f10 ! round[1]
  911. ldd [$key + 24], %f12
  912. fmovd %f0, %f4
  913. faesenclx %f2, %f6, %f0
  914. faesenclx %f4, %f8, %f2
  915. fshiftorx $outhead, %f0, $fshift, %f6
  916. fshiftorx %f0, %f2, $fshift, %f8
  917. std %f6, [$out + 0]
  918. std %f8, [$out + 8]
  919. add $out, 16, $out
  920. brnz,a $len, .Loop_ctr32_unaligned_out
  921. sub $len, 1, $len
  922. .Lctr32_unaligned_out_done:
  923. fshiftorx %f2, %f2, $fshift, %f8
  924. stda %f8, [$out + $mask]0xc0 ! partial store
  925. ret
  926. restore
  927. .type aes_fx_ctr32_encrypt_blocks,#function
  928. .size aes_fx_ctr32_encrypt_blocks,.-aes_fx_ctr32_encrypt_blocks
  929. .align 32
  930. .Linp_align: ! fshiftorx parameters for left shift toward %rs1
  931. .byte 0, 0, 64, 0, 0, 64, 0, -64
  932. .byte 0, 0, 56, 8, 0, 56, 8, -56
  933. .byte 0, 0, 48, 16, 0, 48, 16, -48
  934. .byte 0, 0, 40, 24, 0, 40, 24, -40
  935. .byte 0, 0, 32, 32, 0, 32, 32, -32
  936. .byte 0, 0, 24, 40, 0, 24, 40, -24
  937. .byte 0, 0, 16, 48, 0, 16, 48, -16
  938. .byte 0, 0, 8, 56, 0, 8, 56, -8
  939. .Lout_align: ! fshiftorx parameters for right shift toward %rs2
  940. .byte 0, 0, 0, 64, 0, 0, 64, 0
  941. .byte 0, 0, 8, 56, 0, 8, 56, -8
  942. .byte 0, 0, 16, 48, 0, 16, 48, -16
  943. .byte 0, 0, 24, 40, 0, 24, 40, -24
  944. .byte 0, 0, 32, 32, 0, 32, 32, -32
  945. .byte 0, 0, 40, 24, 0, 40, 24, -40
  946. .byte 0, 0, 48, 16, 0, 48, 16, -48
  947. .byte 0, 0, 56, 8, 0, 56, 8, -56
  948. .Lone:
  949. .word 0, 1
  950. .asciz "AES for Fujitsu SPARC64 X, CRYPTOGAMS by <appro\@openssl.org>"
  951. .align 4
  952. ___
  953. }
  954. # Purpose of these subroutines is to explicitly encode VIS instructions,
  955. # so that one can compile the module without having to specify VIS
  956. # extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
  957. # Idea is to reserve for option to produce "universal" binary and let
  958. # programmer detect if current CPU is VIS capable at run-time.
  959. sub unvis {
  960. my ($mnemonic,$rs1,$rs2,$rd)=@_;
  961. my ($ref,$opf);
  962. my %visopf = ( "faligndata" => 0x048,
  963. "bshuffle" => 0x04c,
  964. "fpadd32" => 0x052,
  965. "fxor" => 0x06c,
  966. "fsrc2" => 0x078 );
  967. $ref = "$mnemonic\t$rs1,$rs2,$rd";
  968. if ($opf=$visopf{$mnemonic}) {
  969. foreach ($rs1,$rs2,$rd) {
  970. return $ref if (!/%f([0-9]{1,2})/);
  971. $_=$1;
  972. if ($1>=32) {
  973. return $ref if ($1&1);
  974. # re-encode for upper double register addressing
  975. $_=($1|$1>>5)&31;
  976. }
  977. }
  978. return sprintf ".word\t0x%08x !%s",
  979. 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
  980. $ref;
  981. } else {
  982. return $ref;
  983. }
  984. }
  985. sub unvis3 {
  986. my ($mnemonic,$rs1,$rs2,$rd)=@_;
  987. my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
  988. my ($ref,$opf);
  989. my %visopf = ( "alignaddr" => 0x018,
  990. "bmask" => 0x019,
  991. "alignaddrl" => 0x01a );
  992. $ref = "$mnemonic\t$rs1,$rs2,$rd";
  993. if ($opf=$visopf{$mnemonic}) {
  994. foreach ($rs1,$rs2,$rd) {
  995. return $ref if (!/%([goli])([0-9])/);
  996. $_=$bias{$1}+$2;
  997. }
  998. return sprintf ".word\t0x%08x !%s",
  999. 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
  1000. $ref;
  1001. } else {
  1002. return $ref;
  1003. }
  1004. }
  1005. sub unfx {
  1006. my ($mnemonic,$rs1,$rs2,$rd)=@_;
  1007. my ($ref,$opf);
  1008. my %aesopf = ( "faesencx" => 0x90,
  1009. "faesdecx" => 0x91,
  1010. "faesenclx" => 0x92,
  1011. "faesdeclx" => 0x93,
  1012. "faeskeyx" => 0x94 );
  1013. $ref = "$mnemonic\t$rs1,$rs2,$rd";
  1014. if (defined($opf=$aesopf{$mnemonic})) {
  1015. $rs2 = ($rs2 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs2;
  1016. $rs2 = oct($rs2) if ($rs2 =~ /^0/);
  1017. foreach ($rs1,$rd) {
  1018. return $ref if (!/%f([0-9]{1,2})/);
  1019. $_=$1;
  1020. if ($1>=32) {
  1021. return $ref if ($1&1);
  1022. # re-encode for upper double register addressing
  1023. $_=($1|$1>>5)&31;
  1024. }
  1025. }
  1026. return sprintf ".word\t0x%08x !%s",
  1027. 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
  1028. $ref;
  1029. } else {
  1030. return $ref;
  1031. }
  1032. }
  1033. sub unfx3src {
  1034. my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
  1035. my ($ref,$opf);
  1036. my %aesopf = ( "fshiftorx" => 0x0b );
  1037. $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
  1038. if (defined($opf=$aesopf{$mnemonic})) {
  1039. foreach ($rs1,$rs2,$rs3,$rd) {
  1040. return $ref if (!/%f([0-9]{1,2})/);
  1041. $_=$1;
  1042. if ($1>=32) {
  1043. return $ref if ($1&1);
  1044. # re-encode for upper double register addressing
  1045. $_=($1|$1>>5)&31;
  1046. }
  1047. }
  1048. return sprintf ".word\t0x%08x !%s",
  1049. 2<<30|$rd<<25|0x37<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2,
  1050. $ref;
  1051. } else {
  1052. return $ref;
  1053. }
  1054. }
  1055. foreach (split("\n",$code)) {
  1056. s/\`([^\`]*)\`/eval $1/ge;
  1057. s/%f([0-9]+)#lo/sprintf "%%f%d",$1+1/ge;
  1058. s/\b(faes[^x]{3,4}x)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
  1059. &unfx($1,$2,$3,$4)
  1060. /ge or
  1061. s/\b([f][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
  1062. &unfx3src($1,$2,$3,$4,$5)
  1063. /ge or
  1064. s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
  1065. &unvis($1,$2,$3,$4)
  1066. /ge or
  1067. s/\b(alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
  1068. &unvis3($1,$2,$3,$4)
  1069. /ge;
  1070. print $_,"\n";
  1071. }
  1072. close STDOUT or die "error closing STDOUT: $!";