123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272 |
- #! /usr/bin/env perl
- # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
- #
- # Licensed under the Apache License 2.0 (the "License"). You may not use
- # this file except in compliance with the License. You can obtain a copy
- # in the file LICENSE in the source distribution or at
- # https://www.openssl.org/source/license.html
- #
- # ====================================================================
- # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
- # project. The module is, however, dual licensed under OpenSSL and
- # CRYPTOGAMS licenses depending on where you obtain it. For further
- # details see http://www.openssl.org/~appro/cryptogams/.
- # ====================================================================
- # March 2016
- #
- # Initial support for Fujitsu SPARC64 X/X+ comprises minimally
- # required key setup and single-block procedures.
- #
- # April 2016
- #
- # Add "teaser" CBC and CTR mode-specific subroutines. "Teaser" means
- # that parallelizable nature of CBC decrypt and CTR is not utilized
- # yet. CBC encrypt on the other hand is as good as it can possibly
- # get processing one byte in 4.1 cycles with 128-bit key on SPARC64 X.
- # This is ~6x faster than pure software implementation...
- #
- # July 2016
- #
- # Switch from faligndata to fshiftorx, which allows to omit alignaddr
- # instructions and improve single-block and short-input performance
- # with misaligned data.
- $output = pop and open STDOUT,">$output";
- {
- my ($inp,$out,$key,$rounds,$tmp,$mask) = map("%o$_",(0..5));
- $code.=<<___;
- #ifndef __ASSEMBLER__
- # define __ASSEMBLER__ 1
- #endif
- #include "crypto/sparc_arch.h"
- #define LOCALS (STACK_BIAS+STACK_FRAME)
- .text
- .globl aes_fx_encrypt
- .align 32
- aes_fx_encrypt:
- and $inp, 7, $tmp ! is input aligned?
- andn $inp, 7, $inp
- ldd [$key + 0], %f6 ! round[0]
- ldd [$key + 8], %f8
- mov %o7, %g1
- ld [$key + 240], $rounds
- 1: call .+8
- add %o7, .Linp_align-1b, %o7
- sll $tmp, 3, $tmp
- ldd [$inp + 0], %f0 ! load input
- brz,pt $tmp, .Lenc_inp_aligned
- ldd [$inp + 8], %f2
- ldd [%o7 + $tmp], %f14 ! shift left params
- ldd [$inp + 16], %f4
- fshiftorx %f0, %f2, %f14, %f0
- fshiftorx %f2, %f4, %f14, %f2
- .Lenc_inp_aligned:
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fxor %f0, %f6, %f0 ! ^=round[0]
- fxor %f2, %f8, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- add $key, 32, $key
- sub $rounds, 4, $rounds
- .Loop_enc:
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 16], %f10
- ldd [$key + 24], %f12
- add $key, 32, $key
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$key + 0], %f6
- ldd [$key + 8], %f8
- brnz,a $rounds, .Loop_enc
- sub $rounds, 2, $rounds
- andcc $out, 7, $tmp ! is output aligned?
- andn $out, 7, $out
- mov 0xff, $mask
- srl $mask, $tmp, $mask
- add %o7, 64, %o7
- sll $tmp, 3, $tmp
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [%o7 + $tmp], %f14 ! shift right params
- fmovd %f0, %f4
- faesenclx %f2, %f6, %f0
- faesenclx %f4, %f8, %f2
- bnz,pn %icc, .Lenc_out_unaligned
- mov %g1, %o7
- std %f0, [$out + 0]
- retl
- std %f2, [$out + 8]
- .align 16
- .Lenc_out_unaligned:
- add $out, 16, $inp
- orn %g0, $mask, $tmp
- fshiftorx %f0, %f0, %f14, %f4
- fshiftorx %f0, %f2, %f14, %f6
- fshiftorx %f2, %f2, %f14, %f8
- stda %f4, [$out + $mask]0xc0 ! partial store
- std %f6, [$out + 8]
- stda %f8, [$inp + $tmp]0xc0 ! partial store
- retl
- nop
- .type aes_fx_encrypt,#function
- .size aes_fx_encrypt,.-aes_fx_encrypt
- .globl aes_fx_decrypt
- .align 32
- aes_fx_decrypt:
- and $inp, 7, $tmp ! is input aligned?
- andn $inp, 7, $inp
- ldd [$key + 0], %f6 ! round[0]
- ldd [$key + 8], %f8
- mov %o7, %g1
- ld [$key + 240], $rounds
- 1: call .+8
- add %o7, .Linp_align-1b, %o7
- sll $tmp, 3, $tmp
- ldd [$inp + 0], %f0 ! load input
- brz,pt $tmp, .Ldec_inp_aligned
- ldd [$inp + 8], %f2
- ldd [%o7 + $tmp], %f14 ! shift left params
- ldd [$inp + 16], %f4
- fshiftorx %f0, %f2, %f14, %f0
- fshiftorx %f2, %f4, %f14, %f2
- .Ldec_inp_aligned:
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fxor %f0, %f6, %f0 ! ^=round[0]
- fxor %f2, %f8, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- add $key, 32, $key
- sub $rounds, 4, $rounds
- .Loop_dec:
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$key + 16], %f10
- ldd [$key + 24], %f12
- add $key, 32, $key
- fmovd %f0, %f4
- faesdecx %f2, %f6, %f0
- faesdecx %f4, %f8, %f2
- ldd [$key + 0], %f6
- ldd [$key + 8], %f8
- brnz,a $rounds, .Loop_dec
- sub $rounds, 2, $rounds
- andcc $out, 7, $tmp ! is output aligned?
- andn $out, 7, $out
- mov 0xff, $mask
- srl $mask, $tmp, $mask
- add %o7, 64, %o7
- sll $tmp, 3, $tmp
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [%o7 + $tmp], %f14 ! shift right params
- fmovd %f0, %f4
- faesdeclx %f2, %f6, %f0
- faesdeclx %f4, %f8, %f2
- bnz,pn %icc, .Ldec_out_unaligned
- mov %g1, %o7
- std %f0, [$out + 0]
- retl
- std %f2, [$out + 8]
- .align 16
- .Ldec_out_unaligned:
- add $out, 16, $inp
- orn %g0, $mask, $tmp
- fshiftorx %f0, %f0, %f14, %f4
- fshiftorx %f0, %f2, %f14, %f6
- fshiftorx %f2, %f2, %f14, %f8
- stda %f4, [$out + $mask]0xc0 ! partial store
- std %f6, [$out + 8]
- stda %f8, [$inp + $tmp]0xc0 ! partial store
- retl
- nop
- .type aes_fx_decrypt,#function
- .size aes_fx_decrypt,.-aes_fx_decrypt
- ___
- }
- {
- my ($inp,$bits,$out,$tmp,$inc) = map("%o$_",(0..5));
- $code.=<<___;
- .globl aes_fx_set_decrypt_key
- .align 32
- aes_fx_set_decrypt_key:
- b .Lset_encrypt_key
- mov -1, $inc
- retl
- nop
- .type aes_fx_set_decrypt_key,#function
- .size aes_fx_set_decrypt_key,.-aes_fx_set_decrypt_key
- .globl aes_fx_set_encrypt_key
- .align 32
- aes_fx_set_encrypt_key:
- mov 1, $inc
- nop
- .Lset_encrypt_key:
- and $inp, 7, $tmp
- andn $inp, 7, $inp
- sll $tmp, 3, $tmp
- mov %o7, %g1
- 1: call .+8
- add %o7, .Linp_align-1b, %o7
- ldd [%o7 + $tmp], %f10 ! shift left params
- mov %g1, %o7
- cmp $bits, 192
- ldd [$inp + 0], %f0
- bl,pt %icc, .L128
- ldd [$inp + 8], %f2
- be,pt %icc, .L192
- ldd [$inp + 16], %f4
- brz,pt $tmp, .L256aligned
- ldd [$inp + 24], %f6
- ldd [$inp + 32], %f8
- fshiftorx %f0, %f2, %f10, %f0
- fshiftorx %f2, %f4, %f10, %f2
- fshiftorx %f4, %f6, %f10, %f4
- fshiftorx %f6, %f8, %f10, %f6
- .L256aligned:
- mov 14, $bits
- and $inc, `14*16`, $tmp
- st $bits, [$out + 240] ! store rounds
- add $out, $tmp, $out ! start or end of key schedule
- sllx $inc, 4, $inc ! 16 or -16
- ___
- for ($i=0; $i<6; $i++) {
- $code.=<<___;
- std %f0, [$out + 0]
- faeskeyx %f6, `0x10+$i`, %f0
- std %f2, [$out + 8]
- add $out, $inc, $out
- faeskeyx %f0, 0x00, %f2
- std %f4, [$out + 0]
- faeskeyx %f2, 0x01, %f4
- std %f6, [$out + 8]
- add $out, $inc, $out
- faeskeyx %f4, 0x00, %f6
- ___
- }
- $code.=<<___;
- std %f0, [$out + 0]
- faeskeyx %f6, `0x10+$i`, %f0
- std %f2, [$out + 8]
- add $out, $inc, $out
- faeskeyx %f0, 0x00, %f2
- std %f4,[$out + 0]
- std %f6,[$out + 8]
- add $out, $inc, $out
- std %f0,[$out + 0]
- std %f2,[$out + 8]
- retl
- xor %o0, %o0, %o0 ! return 0
- .align 16
- .L192:
- brz,pt $tmp, .L192aligned
- nop
- ldd [$inp + 24], %f6
- fshiftorx %f0, %f2, %f10, %f0
- fshiftorx %f2, %f4, %f10, %f2
- fshiftorx %f4, %f6, %f10, %f4
- .L192aligned:
- mov 12, $bits
- and $inc, `12*16`, $tmp
- st $bits, [$out + 240] ! store rounds
- add $out, $tmp, $out ! start or end of key schedule
- sllx $inc, 4, $inc ! 16 or -16
- ___
- for ($i=0; $i<8; $i+=2) {
- $code.=<<___;
- std %f0, [$out + 0]
- faeskeyx %f4, `0x10+$i`, %f0
- std %f2, [$out + 8]
- add $out, $inc, $out
- faeskeyx %f0, 0x00, %f2
- std %f4, [$out + 0]
- faeskeyx %f2, 0x00, %f4
- std %f0, [$out + 8]
- add $out, $inc, $out
- faeskeyx %f4, `0x10+$i+1`, %f0
- std %f2, [$out + 0]
- faeskeyx %f0, 0x00, %f2
- std %f4, [$out + 8]
- add $out, $inc, $out
- ___
- $code.=<<___ if ($i<6);
- faeskeyx %f2, 0x00, %f4
- ___
- }
- $code.=<<___;
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- retl
- xor %o0, %o0, %o0 ! return 0
- .align 16
- .L128:
- brz,pt $tmp, .L128aligned
- nop
- ldd [$inp + 16], %f4
- fshiftorx %f0, %f2, %f10, %f0
- fshiftorx %f2, %f4, %f10, %f2
- .L128aligned:
- mov 10, $bits
- and $inc, `10*16`, $tmp
- st $bits, [$out + 240] ! store rounds
- add $out, $tmp, $out ! start or end of key schedule
- sllx $inc, 4, $inc ! 16 or -16
- ___
- for ($i=0; $i<10; $i++) {
- $code.=<<___;
- std %f0, [$out + 0]
- faeskeyx %f2, `0x10+$i`, %f0
- std %f2, [$out + 8]
- add $out, $inc, $out
- faeskeyx %f0, 0x00, %f2
- ___
- }
- $code.=<<___;
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- retl
- xor %o0, %o0, %o0 ! return 0
- .type aes_fx_set_encrypt_key,#function
- .size aes_fx_set_encrypt_key,.-aes_fx_set_encrypt_key
- ___
- }
- {
- my ($inp,$out,$len,$key,$ivp,$dir) = map("%i$_",(0..5));
- my ($rounds,$inner,$end,$inc,$ialign,$oalign,$mask) = map("%l$_",(0..7));
- my ($iv0,$iv1,$r0hi,$r0lo,$rlhi,$rllo,$in0,$in1,$intail,$outhead,$fshift)
- = map("%f$_",grep { !($_ & 1) } (16 .. 62));
- my ($ileft,$iright) = ($ialign,$oalign);
- $code.=<<___;
- .globl aes_fx_cbc_encrypt
- .align 32
- aes_fx_cbc_encrypt:
- save %sp, -STACK_FRAME-16, %sp
- srln $len, 4, $len
- and $inp, 7, $ialign
- andn $inp, 7, $inp
- brz,pn $len, .Lcbc_no_data
- sll $ialign, 3, $ileft
- 1: call .+8
- add %o7, .Linp_align-1b, %o7
- ld [$key + 240], $rounds
- and $out, 7, $oalign
- ld [$ivp + 0], %f0 ! load ivec
- andn $out, 7, $out
- ld [$ivp + 4], %f1
- sll $oalign, 3, $mask
- ld [$ivp + 8], %f2
- ld [$ivp + 12], %f3
- sll $rounds, 4, $rounds
- add $rounds, $key, $end
- ldd [$key + 0], $r0hi ! round[0]
- ldd [$key + 8], $r0lo
- add $inp, 16, $inp
- sub $len, 1, $len
- ldd [$end + 0], $rlhi ! round[last]
- ldd [$end + 8], $rllo
- mov 16, $inc
- movrz $len, 0, $inc
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- ldd [%o7 + $ileft], $fshift ! shift left params
- add %o7, 64, %o7
- ldd [$inp - 16], $in0 ! load input
- ldd [$inp - 8], $in1
- ldda [$inp]0x82, $intail ! non-faulting load
- brz $dir, .Lcbc_decrypt
- add $inp, $inc, $inp ! inp+=16
- fxor $r0hi, %f0, %f0 ! ivec^=round[0]
- fxor $r0lo, %f2, %f2
- fshiftorx $in0, $in1, $fshift, $in0
- fshiftorx $in1, $intail, $fshift, $in1
- nop
- .Loop_cbc_enc:
- fxor $in0, %f0, %f0 ! inp^ivec^round[0]
- fxor $in1, %f2, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- add $key, 32, $end
- sub $rounds, 16*6, $inner
- .Lcbc_enc:
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10
- ldd [$end + 24], %f12
- add $end, 32, $end
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$end + 0], %f6
- ldd [$end + 8], %f8
- brnz,a $inner, .Lcbc_enc
- sub $inner, 16*2, $inner
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10 ! round[last-1]
- ldd [$end + 24], %f12
- movrz $len, 0, $inc
- fmovd $intail, $in0
- ldd [$inp - 8], $in1 ! load next input block
- ldda [$inp]0x82, $intail ! non-faulting load
- add $inp, $inc, $inp ! inp+=16
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- fshiftorx $in0, $in1, $fshift, $in0
- fshiftorx $in1, $intail, $fshift, $in1
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fxor $r0hi, $in0, $in0 ! inp^=round[0]
- fxor $r0lo, $in1, $in1
- fmovd %f0, %f4
- faesenclx %f2, $rlhi, %f0
- faesenclx %f4, $rllo, %f2
- brnz,pn $oalign, .Lcbc_enc_unaligned_out
- nop
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- add $out, 16, $out
- brnz,a $len, .Loop_cbc_enc
- sub $len, 1, $len
- st %f0, [$ivp + 0] ! output ivec
- st %f1, [$ivp + 4]
- st %f2, [$ivp + 8]
- st %f3, [$ivp + 12]
- .Lcbc_no_data:
- ret
- restore
- .align 32
- .Lcbc_enc_unaligned_out:
- ldd [%o7 + $mask], $fshift ! shift right params
- mov 0xff, $mask
- srl $mask, $oalign, $mask
- sub %g0, $ileft, $iright
- fshiftorx %f0, %f0, $fshift, %f6
- fshiftorx %f0, %f2, $fshift, %f8
- stda %f6, [$out + $mask]0xc0 ! partial store
- orn %g0, $mask, $mask
- std %f8, [$out + 8]
- add $out, 16, $out
- brz $len, .Lcbc_enc_unaligned_out_done
- sub $len, 1, $len
- b .Loop_cbc_enc_unaligned_out
- nop
- .align 32
- .Loop_cbc_enc_unaligned_out:
- fmovd %f2, $outhead
- fxor $in0, %f0, %f0 ! inp^ivec^round[0]
- fxor $in1, %f2, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 48], %f10 ! round[3]
- ldd [$key + 56], %f12
- ldx [$inp - 16], %o0
- ldx [$inp - 8], %o1
- brz $ileft, .Lcbc_enc_aligned_inp
- movrz $len, 0, $inc
- ldx [$inp], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
- .Lcbc_enc_aligned_inp:
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$key + 64], %f6 ! round[4]
- ldd [$key + 72], %f8
- add $key, 64, $end
- sub $rounds, 16*8, $inner
- stx %o0, [%sp + LOCALS + 0]
- stx %o1, [%sp + LOCALS + 8]
- add $inp, $inc, $inp ! inp+=16
- nop
- .Lcbc_enc_unaligned:
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10
- ldd [$end + 24], %f12
- add $end, 32, $end
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$end + 0], %f6
- ldd [$end + 8], %f8
- brnz,a $inner, .Lcbc_enc_unaligned
- sub $inner, 16*2, $inner
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10 ! round[last-1]
- ldd [$end + 24], %f12
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [%sp + LOCALS + 0], $in0
- ldd [%sp + LOCALS + 8], $in1
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fxor $r0hi, $in0, $in0 ! inp^=round[0]
- fxor $r0lo, $in1, $in1
- fmovd %f0, %f4
- faesenclx %f2, $rlhi, %f0
- faesenclx %f4, $rllo, %f2
- fshiftorx $outhead, %f0, $fshift, %f6
- fshiftorx %f0, %f2, $fshift, %f8
- std %f6, [$out + 0]
- std %f8, [$out + 8]
- add $out, 16, $out
- brnz,a $len, .Loop_cbc_enc_unaligned_out
- sub $len, 1, $len
- .Lcbc_enc_unaligned_out_done:
- fshiftorx %f2, %f2, $fshift, %f8
- stda %f8, [$out + $mask]0xc0 ! partial store
- st %f0, [$ivp + 0] ! output ivec
- st %f1, [$ivp + 4]
- st %f2, [$ivp + 8]
- st %f3, [$ivp + 12]
- ret
- restore
- .align 32
- .Lcbc_decrypt:
- fshiftorx $in0, $in1, $fshift, $in0
- fshiftorx $in1, $intail, $fshift, $in1
- fmovd %f0, $iv0
- fmovd %f2, $iv1
- .Loop_cbc_dec:
- fxor $in0, $r0hi, %f0 ! inp^round[0]
- fxor $in1, $r0lo, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- add $key, 32, $end
- sub $rounds, 16*6, $inner
- .Lcbc_dec:
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$end + 16], %f10
- ldd [$end + 24], %f12
- add $end, 32, $end
- fmovd %f0, %f4
- faesdecx %f2, %f6, %f0
- faesdecx %f4, %f8, %f2
- ldd [$end + 0], %f6
- ldd [$end + 8], %f8
- brnz,a $inner, .Lcbc_dec
- sub $inner, 16*2, $inner
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$end + 16], %f10 ! round[last-1]
- ldd [$end + 24], %f12
- fmovd %f0, %f4
- faesdecx %f2, %f6, %f0
- faesdecx %f4, %f8, %f2
- fxor $iv0, $rlhi, %f6 ! ivec^round[last]
- fxor $iv1, $rllo, %f8
- fmovd $in0, $iv0
- fmovd $in1, $iv1
- movrz $len, 0, $inc
- fmovd $intail, $in0
- ldd [$inp - 8], $in1 ! load next input block
- ldda [$inp]0x82, $intail ! non-faulting load
- add $inp, $inc, $inp ! inp+=16
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fshiftorx $in0, $in1, $fshift, $in0
- fshiftorx $in1, $intail, $fshift, $in1
- fmovd %f0, %f4
- faesdeclx %f2, %f6, %f0
- faesdeclx %f4, %f8, %f2
- brnz,pn $oalign, .Lcbc_dec_unaligned_out
- nop
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- add $out, 16, $out
- brnz,a $len, .Loop_cbc_dec
- sub $len, 1, $len
- st $iv0, [$ivp + 0] ! output ivec
- st $iv0#lo, [$ivp + 4]
- st $iv1, [$ivp + 8]
- st $iv1#lo, [$ivp + 12]
- ret
- restore
- .align 32
- .Lcbc_dec_unaligned_out:
- ldd [%o7 + $mask], $fshift ! shift right params
- mov 0xff, $mask
- srl $mask, $oalign, $mask
- sub %g0, $ileft, $iright
- fshiftorx %f0, %f0, $fshift, %f6
- fshiftorx %f0, %f2, $fshift, %f8
- stda %f6, [$out + $mask]0xc0 ! partial store
- orn %g0, $mask, $mask
- std %f8, [$out + 8]
- add $out, 16, $out
- brz $len, .Lcbc_dec_unaligned_out_done
- sub $len, 1, $len
- b .Loop_cbc_dec_unaligned_out
- nop
- .align 32
- .Loop_cbc_dec_unaligned_out:
- fmovd %f2, $outhead
- fxor $in0, $r0hi, %f0 ! inp^round[0]
- fxor $in1, $r0lo, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$key + 48], %f10 ! round[3]
- ldd [$key + 56], %f12
- ldx [$inp - 16], %o0
- ldx [$inp - 8], %o1
- brz $ileft, .Lcbc_dec_aligned_inp
- movrz $len, 0, $inc
- ldx [$inp], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
- .Lcbc_dec_aligned_inp:
- fmovd %f0, %f4
- faesdecx %f2, %f6, %f0
- faesdecx %f4, %f8, %f2
- ldd [$key + 64], %f6 ! round[4]
- ldd [$key + 72], %f8
- add $key, 64, $end
- sub $rounds, 16*8, $inner
- stx %o0, [%sp + LOCALS + 0]
- stx %o1, [%sp + LOCALS + 8]
- add $inp, $inc, $inp ! inp+=16
- nop
- .Lcbc_dec_unaligned:
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$end + 16], %f10
- ldd [$end + 24], %f12
- add $end, 32, $end
- fmovd %f0, %f4
- faesdecx %f2, %f6, %f0
- faesdecx %f4, %f8, %f2
- ldd [$end + 0], %f6
- ldd [$end + 8], %f8
- brnz,a $inner, .Lcbc_dec_unaligned
- sub $inner, 16*2, $inner
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$end + 16], %f10 ! round[last-1]
- ldd [$end + 24], %f12
- fmovd %f0, %f4
- faesdecx %f2, %f6, %f0
- faesdecx %f4, %f8, %f2
- fxor $iv0, $rlhi, %f6 ! ivec^round[last]
- fxor $iv1, $rllo, %f8
- fmovd $in0, $iv0
- fmovd $in1, $iv1
- ldd [%sp + LOCALS + 0], $in0
- ldd [%sp + LOCALS + 8], $in1
- fmovd %f0, %f4
- faesdecx %f2, %f10, %f0
- faesdecx %f4, %f12, %f2
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fmovd %f0, %f4
- faesdeclx %f2, %f6, %f0
- faesdeclx %f4, %f8, %f2
- fshiftorx $outhead, %f0, $fshift, %f6
- fshiftorx %f0, %f2, $fshift, %f8
- std %f6, [$out + 0]
- std %f8, [$out + 8]
- add $out, 16, $out
- brnz,a $len, .Loop_cbc_dec_unaligned_out
- sub $len, 1, $len
- .Lcbc_dec_unaligned_out_done:
- fshiftorx %f2, %f2, $fshift, %f8
- stda %f8, [$out + $mask]0xc0 ! partial store
- st $iv0, [$ivp + 0] ! output ivec
- st $iv0#lo, [$ivp + 4]
- st $iv1, [$ivp + 8]
- st $iv1#lo, [$ivp + 12]
- ret
- restore
- .type aes_fx_cbc_encrypt,#function
- .size aes_fx_cbc_encrypt,.-aes_fx_cbc_encrypt
- ___
- }
- {
- my ($inp,$out,$len,$key,$ivp) = map("%i$_",(0..5));
- my ($rounds,$inner,$end,$inc,$ialign,$oalign,$mask) = map("%l$_",(0..7));
- my ($ctr0,$ctr1,$r0hi,$r0lo,$rlhi,$rllo,$in0,$in1,$intail,$outhead,$fshift)
- = map("%f$_",grep { !($_ & 1) } (16 .. 62));
- my ($ileft,$iright) = ($ialign, $oalign);
- my $one = "%f14";
- $code.=<<___;
- .globl aes_fx_ctr32_encrypt_blocks
- .align 32
- aes_fx_ctr32_encrypt_blocks:
- save %sp, -STACK_FRAME-16, %sp
- srln $len, 0, $len
- and $inp, 7, $ialign
- andn $inp, 7, $inp
- brz,pn $len, .Lctr32_no_data
- sll $ialign, 3, $ileft
- .Lpic: call .+8
- add %o7, .Linp_align - .Lpic, %o7
- ld [$key + 240], $rounds
- and $out, 7, $oalign
- ld [$ivp + 0], $ctr0 ! load counter
- andn $out, 7, $out
- ld [$ivp + 4], $ctr0#lo
- sll $oalign, 3, $mask
- ld [$ivp + 8], $ctr1
- ld [$ivp + 12], $ctr1#lo
- ldd [%o7 + 128], $one
- sll $rounds, 4, $rounds
- add $rounds, $key, $end
- ldd [$key + 0], $r0hi ! round[0]
- ldd [$key + 8], $r0lo
- add $inp, 16, $inp
- sub $len, 1, $len
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- mov 16, $inc
- movrz $len, 0, $inc
- ldd [$end + 0], $rlhi ! round[last]
- ldd [$end + 8], $rllo
- ldd [%o7 + $ileft], $fshift ! shiftleft params
- add %o7, 64, %o7
- ldd [$inp - 16], $in0 ! load input
- ldd [$inp - 8], $in1
- ldda [$inp]0x82, $intail ! non-faulting load
- add $inp, $inc, $inp ! inp+=16
- fshiftorx $in0, $in1, $fshift, $in0
- fshiftorx $in1, $intail, $fshift, $in1
- .Loop_ctr32:
- fxor $ctr0, $r0hi, %f0 ! counter^round[0]
- fxor $ctr1, $r0lo, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- add $key, 32, $end
- sub $rounds, 16*6, $inner
- .Lctr32_enc:
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10
- ldd [$end + 24], %f12
- add $end, 32, $end
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$end + 0], %f6
- ldd [$end + 8], %f8
- brnz,a $inner, .Lctr32_enc
- sub $inner, 16*2, $inner
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10 ! round[last-1]
- ldd [$end + 24], %f12
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- fxor $in0, $rlhi, %f6 ! inp^round[last]
- fxor $in1, $rllo, %f8
- movrz $len, 0, $inc
- fmovd $intail, $in0
- ldd [$inp - 8], $in1 ! load next input block
- ldda [$inp]0x82, $intail ! non-faulting load
- add $inp, $inc, $inp ! inp+=16
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fshiftorx $in0, $in1, $fshift, $in0
- fshiftorx $in1, $intail, $fshift, $in1
- fpadd32 $ctr1, $one, $ctr1 ! increment counter
- fmovd %f0, %f4
- faesenclx %f2, %f6, %f0
- faesenclx %f4, %f8, %f2
- brnz,pn $oalign, .Lctr32_unaligned_out
- nop
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- add $out, 16, $out
- brnz,a $len, .Loop_ctr32
- sub $len, 1, $len
- .Lctr32_no_data:
- ret
- restore
- .align 32
- .Lctr32_unaligned_out:
- ldd [%o7 + $mask], $fshift ! shift right params
- mov 0xff, $mask
- srl $mask, $oalign, $mask
- sub %g0, $ileft, $iright
- fshiftorx %f0, %f0, $fshift, %f6
- fshiftorx %f0, %f2, $fshift, %f8
- stda %f6, [$out + $mask]0xc0 ! partial store
- orn %g0, $mask, $mask
- std %f8, [$out + 8]
- add $out, 16, $out
- brz $len, .Lctr32_unaligned_out_done
- sub $len, 1, $len
- b .Loop_ctr32_unaligned_out
- nop
- .align 32
- .Loop_ctr32_unaligned_out:
- fmovd %f2, $outhead
- fxor $ctr0, $r0hi, %f0 ! counter^round[0]
- fxor $ctr1, $r0lo, %f2
- ldd [$key + 32], %f6 ! round[2]
- ldd [$key + 40], %f8
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 48], %f10 ! round[3]
- ldd [$key + 56], %f12
- ldx [$inp - 16], %o0
- ldx [$inp - 8], %o1
- brz $ileft, .Lctr32_aligned_inp
- movrz $len, 0, $inc
- ldx [$inp], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
- .Lctr32_aligned_inp:
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$key + 64], %f6 ! round[4]
- ldd [$key + 72], %f8
- add $key, 64, $end
- sub $rounds, 16*8, $inner
- stx %o0, [%sp + LOCALS + 0]
- stx %o1, [%sp + LOCALS + 8]
- add $inp, $inc, $inp ! inp+=16
- nop
- .Lctr32_enc_unaligned:
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10
- ldd [$end + 24], %f12
- add $end, 32, $end
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- ldd [$end + 0], %f6
- ldd [$end + 8], %f8
- brnz,a $inner, .Lctr32_enc_unaligned
- sub $inner, 16*2, $inner
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$end + 16], %f10 ! round[last-1]
- ldd [$end + 24], %f12
- fpadd32 $ctr1, $one, $ctr1 ! increment counter
- fmovd %f0, %f4
- faesencx %f2, %f6, %f0
- faesencx %f4, %f8, %f2
- fxor $in0, $rlhi, %f6 ! inp^round[last]
- fxor $in1, $rllo, %f8
- ldd [%sp + LOCALS + 0], $in0
- ldd [%sp + LOCALS + 8], $in1
- fmovd %f0, %f4
- faesencx %f2, %f10, %f0
- faesencx %f4, %f12, %f2
- ldd [$key + 16], %f10 ! round[1]
- ldd [$key + 24], %f12
- fmovd %f0, %f4
- faesenclx %f2, %f6, %f0
- faesenclx %f4, %f8, %f2
- fshiftorx $outhead, %f0, $fshift, %f6
- fshiftorx %f0, %f2, $fshift, %f8
- std %f6, [$out + 0]
- std %f8, [$out + 8]
- add $out, 16, $out
- brnz,a $len, .Loop_ctr32_unaligned_out
- sub $len, 1, $len
- .Lctr32_unaligned_out_done:
- fshiftorx %f2, %f2, $fshift, %f8
- stda %f8, [$out + $mask]0xc0 ! partial store
- ret
- restore
- .type aes_fx_ctr32_encrypt_blocks,#function
- .size aes_fx_ctr32_encrypt_blocks,.-aes_fx_ctr32_encrypt_blocks
- .align 32
- .Linp_align: ! fshiftorx parameters for left shift toward %rs1
- .byte 0, 0, 64, 0, 0, 64, 0, -64
- .byte 0, 0, 56, 8, 0, 56, 8, -56
- .byte 0, 0, 48, 16, 0, 48, 16, -48
- .byte 0, 0, 40, 24, 0, 40, 24, -40
- .byte 0, 0, 32, 32, 0, 32, 32, -32
- .byte 0, 0, 24, 40, 0, 24, 40, -24
- .byte 0, 0, 16, 48, 0, 16, 48, -16
- .byte 0, 0, 8, 56, 0, 8, 56, -8
- .Lout_align: ! fshiftorx parameters for right shift toward %rs2
- .byte 0, 0, 0, 64, 0, 0, 64, 0
- .byte 0, 0, 8, 56, 0, 8, 56, -8
- .byte 0, 0, 16, 48, 0, 16, 48, -16
- .byte 0, 0, 24, 40, 0, 24, 40, -24
- .byte 0, 0, 32, 32, 0, 32, 32, -32
- .byte 0, 0, 40, 24, 0, 40, 24, -40
- .byte 0, 0, 48, 16, 0, 48, 16, -48
- .byte 0, 0, 56, 8, 0, 56, 8, -56
- .Lone:
- .word 0, 1
- .asciz "AES for Fujitsu SPARC64 X, CRYPTOGAMS by <appro\@openssl.org>"
- .align 4
- ___
- }
- # Purpose of these subroutines is to explicitly encode VIS instructions,
- # so that one can compile the module without having to specify VIS
- # extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
- # Idea is to reserve for option to produce "universal" binary and let
- # programmer detect if current CPU is VIS capable at run-time.
- sub unvis {
- my ($mnemonic,$rs1,$rs2,$rd)=@_;
- my ($ref,$opf);
- my %visopf = ( "faligndata" => 0x048,
- "bshuffle" => 0x04c,
- "fpadd32" => 0x052,
- "fxor" => 0x06c,
- "fsrc2" => 0x078 );
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
- if ($opf=$visopf{$mnemonic}) {
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
- return sprintf ".word\t0x%08x !%s",
- 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
- }
- sub unvis3 {
- my ($mnemonic,$rs1,$rs2,$rd)=@_;
- my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
- my ($ref,$opf);
- my %visopf = ( "alignaddr" => 0x018,
- "bmask" => 0x019,
- "alignaddrl" => 0x01a );
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
- if ($opf=$visopf{$mnemonic}) {
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%([goli])([0-9])/);
- $_=$bias{$1}+$2;
- }
- return sprintf ".word\t0x%08x !%s",
- 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
- }
- sub unfx {
- my ($mnemonic,$rs1,$rs2,$rd)=@_;
- my ($ref,$opf);
- my %aesopf = ( "faesencx" => 0x90,
- "faesdecx" => 0x91,
- "faesenclx" => 0x92,
- "faesdeclx" => 0x93,
- "faeskeyx" => 0x94 );
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
- if (defined($opf=$aesopf{$mnemonic})) {
- $rs2 = ($rs2 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs2;
- $rs2 = oct($rs2) if ($rs2 =~ /^0/);
- foreach ($rs1,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
- }
- sub unfx3src {
- my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
- my ($ref,$opf);
- my %aesopf = ( "fshiftorx" => 0x0b );
- $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
- if (defined($opf=$aesopf{$mnemonic})) {
- foreach ($rs1,$rs2,$rs3,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x37<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
- }
- foreach (split("\n",$code)) {
- s/\`([^\`]*)\`/eval $1/ge;
- s/%f([0-9]+)#lo/sprintf "%%f%d",$1+1/ge;
- s/\b(faes[^x]{3,4}x)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
- &unfx($1,$2,$3,$4)
- /ge or
- 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})/
- &unfx3src($1,$2,$3,$4,$5)
- /ge or
- s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
- &unvis($1,$2,$3,$4)
- /ge or
- s/\b(alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
- &unvis3($1,$2,$3,$4)
- /ge;
- print $_,"\n";
- }
- close STDOUT or die "error closing STDOUT: $!";
|