1289848Sjkim#!/usr/bin/env perl 2289848Sjkim# 3289848Sjkim# ==================================================================== 4289848Sjkim# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL 5289848Sjkim# project. The module is, however, dual licensed under OpenSSL and 6289848Sjkim# CRYPTOGAMS licenses depending on where you obtain it. For further 7289848Sjkim# details see http://www.openssl.org/~appro/cryptogams/. 8289848Sjkim# ==================================================================== 9289848Sjkim# 10289848Sjkim# This module implements support for ARMv8 AES instructions. The 11289848Sjkim# module is endian-agnostic in sense that it supports both big- and 12289848Sjkim# little-endian cases. As does it support both 32- and 64-bit modes 13289848Sjkim# of operation. Latter is achieved by limiting amount of utilized 14289848Sjkim# registers to 16, which implies additional NEON load and integer 15289848Sjkim# instructions. This has no effect on mighty Apple A7, where results 16289848Sjkim# are literally equal to the theoretical estimates based on AES 17289848Sjkim# instruction latencies and issue rates. On Cortex-A53, an in-order 18289848Sjkim# execution core, this costs up to 10-15%, which is partially 19289848Sjkim# compensated by implementing dedicated code path for 128-bit 20289848Sjkim# CBC encrypt case. On Cortex-A57 parallelizable mode performance 21289848Sjkim# seems to be limited by sheer amount of NEON instructions... 22289848Sjkim# 23289848Sjkim# Performance in cycles per byte processed with 128-bit key: 24289848Sjkim# 25289848Sjkim# CBC enc CBC dec CTR 26289848Sjkim# Apple A7 2.39 1.20 1.20 27289848Sjkim# Cortex-A53 1.32 1.29 1.46 28289848Sjkim# Cortex-A57(*) 1.95 0.85 0.93 29289848Sjkim# Denver 1.96 0.86 0.80 30289848Sjkim# 31289848Sjkim# (*) original 3.64/1.34/1.32 results were for r0p0 revision 32289848Sjkim# and are still same even for updated module; 33289848Sjkim 34289848Sjkim$flavour = shift; 35289848Sjkimopen STDOUT,">".shift; 36289848Sjkim 37289848Sjkim$prefix="aes_v8"; 38289848Sjkim 39289848Sjkim$code=<<___; 40289848Sjkim#include "arm_arch.h" 41289848Sjkim 42289848Sjkim#if __ARM_MAX_ARCH__>=7 43289848Sjkim.text 44289848Sjkim___ 45325333Sjkim# $code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/); 46289848Sjkim$code.=".arch armv7-a\n.fpu neon\n.code 32\n" if ($flavour !~ /64/); 47289848Sjkim #^^^^^^ this is done to simplify adoption by not depending 48289848Sjkim # on latest binutils. 49289848Sjkim 50289848Sjkim# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax, 51289848Sjkim# NEON is mostly 32-bit mnemonics, integer - mostly 64. Goal is to 52289848Sjkim# maintain both 32- and 64-bit codes within single module and 53289848Sjkim# transliterate common code to either flavour with regex vodoo. 54289848Sjkim# 55289848Sjkim{{{ 56289848Sjkimmy ($inp,$bits,$out,$ptr,$rounds)=("x0","w1","x2","x3","w12"); 57289848Sjkimmy ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)= 58289848Sjkim $flavour=~/64/? map("q$_",(0..6)) : map("q$_",(0..3,8..10)); 59289848Sjkim 60289848Sjkim 61289848Sjkim$code.=<<___; 62289848Sjkim.align 5 63289848Sjkimrcon: 64289848Sjkim.long 0x01,0x01,0x01,0x01 65289848Sjkim.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat 66289848Sjkim.long 0x1b,0x1b,0x1b,0x1b 67289848Sjkim 68289848Sjkim.globl ${prefix}_set_encrypt_key 69289848Sjkim.type ${prefix}_set_encrypt_key,%function 70289848Sjkim.align 5 71289848Sjkim${prefix}_set_encrypt_key: 72289848Sjkim.Lenc_key: 73289848Sjkim___ 74289848Sjkim$code.=<<___ if ($flavour =~ /64/); 75289848Sjkim stp x29,x30,[sp,#-16]! 76289848Sjkim add x29,sp,#0 77289848Sjkim___ 78289848Sjkim$code.=<<___; 79289848Sjkim mov $ptr,#-1 80289848Sjkim cmp $inp,#0 81289848Sjkim b.eq .Lenc_key_abort 82289848Sjkim cmp $out,#0 83289848Sjkim b.eq .Lenc_key_abort 84289848Sjkim mov $ptr,#-2 85289848Sjkim cmp $bits,#128 86289848Sjkim b.lt .Lenc_key_abort 87289848Sjkim cmp $bits,#256 88289848Sjkim b.gt .Lenc_key_abort 89289848Sjkim tst $bits,#0x3f 90289848Sjkim b.ne .Lenc_key_abort 91289848Sjkim 92289848Sjkim adr $ptr,rcon 93289848Sjkim cmp $bits,#192 94289848Sjkim 95289848Sjkim veor $zero,$zero,$zero 96289848Sjkim vld1.8 {$in0},[$inp],#16 97289848Sjkim mov $bits,#8 // reuse $bits 98289848Sjkim vld1.32 {$rcon,$mask},[$ptr],#32 99289848Sjkim 100289848Sjkim b.lt .Loop128 101289848Sjkim b.eq .L192 102289848Sjkim b .L256 103289848Sjkim 104289848Sjkim.align 4 105289848Sjkim.Loop128: 106289848Sjkim vtbl.8 $key,{$in0},$mask 107289848Sjkim vext.8 $tmp,$zero,$in0,#12 108289848Sjkim vst1.32 {$in0},[$out],#16 109289848Sjkim aese $key,$zero 110289848Sjkim subs $bits,$bits,#1 111289848Sjkim 112289848Sjkim veor $in0,$in0,$tmp 113289848Sjkim vext.8 $tmp,$zero,$tmp,#12 114289848Sjkim veor $in0,$in0,$tmp 115289848Sjkim vext.8 $tmp,$zero,$tmp,#12 116289848Sjkim veor $key,$key,$rcon 117289848Sjkim veor $in0,$in0,$tmp 118289848Sjkim vshl.u8 $rcon,$rcon,#1 119289848Sjkim veor $in0,$in0,$key 120289848Sjkim b.ne .Loop128 121289848Sjkim 122289848Sjkim vld1.32 {$rcon},[$ptr] 123289848Sjkim 124289848Sjkim vtbl.8 $key,{$in0},$mask 125289848Sjkim vext.8 $tmp,$zero,$in0,#12 126289848Sjkim vst1.32 {$in0},[$out],#16 127289848Sjkim aese $key,$zero 128289848Sjkim 129289848Sjkim veor $in0,$in0,$tmp 130289848Sjkim vext.8 $tmp,$zero,$tmp,#12 131289848Sjkim veor $in0,$in0,$tmp 132289848Sjkim vext.8 $tmp,$zero,$tmp,#12 133289848Sjkim veor $key,$key,$rcon 134289848Sjkim veor $in0,$in0,$tmp 135289848Sjkim vshl.u8 $rcon,$rcon,#1 136289848Sjkim veor $in0,$in0,$key 137289848Sjkim 138289848Sjkim vtbl.8 $key,{$in0},$mask 139289848Sjkim vext.8 $tmp,$zero,$in0,#12 140289848Sjkim vst1.32 {$in0},[$out],#16 141289848Sjkim aese $key,$zero 142289848Sjkim 143289848Sjkim veor $in0,$in0,$tmp 144289848Sjkim vext.8 $tmp,$zero,$tmp,#12 145289848Sjkim veor $in0,$in0,$tmp 146289848Sjkim vext.8 $tmp,$zero,$tmp,#12 147289848Sjkim veor $key,$key,$rcon 148289848Sjkim veor $in0,$in0,$tmp 149289848Sjkim veor $in0,$in0,$key 150289848Sjkim vst1.32 {$in0},[$out] 151289848Sjkim add $out,$out,#0x50 152289848Sjkim 153289848Sjkim mov $rounds,#10 154289848Sjkim b .Ldone 155289848Sjkim 156289848Sjkim.align 4 157289848Sjkim.L192: 158289848Sjkim vld1.8 {$in1},[$inp],#8 159289848Sjkim vmov.i8 $key,#8 // borrow $key 160289848Sjkim vst1.32 {$in0},[$out],#16 161289848Sjkim vsub.i8 $mask,$mask,$key // adjust the mask 162289848Sjkim 163289848Sjkim.Loop192: 164289848Sjkim vtbl.8 $key,{$in1},$mask 165289848Sjkim vext.8 $tmp,$zero,$in0,#12 166289848Sjkim vst1.32 {$in1},[$out],#8 167289848Sjkim aese $key,$zero 168289848Sjkim subs $bits,$bits,#1 169289848Sjkim 170289848Sjkim veor $in0,$in0,$tmp 171289848Sjkim vext.8 $tmp,$zero,$tmp,#12 172289848Sjkim veor $in0,$in0,$tmp 173289848Sjkim vext.8 $tmp,$zero,$tmp,#12 174289848Sjkim veor $in0,$in0,$tmp 175289848Sjkim 176289848Sjkim vdup.32 $tmp,${in0}[3] 177289848Sjkim veor $tmp,$tmp,$in1 178289848Sjkim veor $key,$key,$rcon 179289848Sjkim vext.8 $in1,$zero,$in1,#12 180289848Sjkim vshl.u8 $rcon,$rcon,#1 181289848Sjkim veor $in1,$in1,$tmp 182289848Sjkim veor $in0,$in0,$key 183289848Sjkim veor $in1,$in1,$key 184289848Sjkim vst1.32 {$in0},[$out],#16 185289848Sjkim b.ne .Loop192 186289848Sjkim 187289848Sjkim mov $rounds,#12 188289848Sjkim add $out,$out,#0x20 189289848Sjkim b .Ldone 190289848Sjkim 191289848Sjkim.align 4 192289848Sjkim.L256: 193289848Sjkim vld1.8 {$in1},[$inp] 194289848Sjkim mov $bits,#7 195289848Sjkim mov $rounds,#14 196289848Sjkim vst1.32 {$in0},[$out],#16 197289848Sjkim 198289848Sjkim.Loop256: 199289848Sjkim vtbl.8 $key,{$in1},$mask 200289848Sjkim vext.8 $tmp,$zero,$in0,#12 201289848Sjkim vst1.32 {$in1},[$out],#16 202289848Sjkim aese $key,$zero 203289848Sjkim subs $bits,$bits,#1 204289848Sjkim 205289848Sjkim veor $in0,$in0,$tmp 206289848Sjkim vext.8 $tmp,$zero,$tmp,#12 207289848Sjkim veor $in0,$in0,$tmp 208289848Sjkim vext.8 $tmp,$zero,$tmp,#12 209289848Sjkim veor $key,$key,$rcon 210289848Sjkim veor $in0,$in0,$tmp 211289848Sjkim vshl.u8 $rcon,$rcon,#1 212289848Sjkim veor $in0,$in0,$key 213289848Sjkim vst1.32 {$in0},[$out],#16 214289848Sjkim b.eq .Ldone 215289848Sjkim 216289848Sjkim vdup.32 $key,${in0}[3] // just splat 217289848Sjkim vext.8 $tmp,$zero,$in1,#12 218289848Sjkim aese $key,$zero 219289848Sjkim 220289848Sjkim veor $in1,$in1,$tmp 221289848Sjkim vext.8 $tmp,$zero,$tmp,#12 222289848Sjkim veor $in1,$in1,$tmp 223289848Sjkim vext.8 $tmp,$zero,$tmp,#12 224289848Sjkim veor $in1,$in1,$tmp 225289848Sjkim 226289848Sjkim veor $in1,$in1,$key 227289848Sjkim b .Loop256 228289848Sjkim 229289848Sjkim.Ldone: 230289848Sjkim str $rounds,[$out] 231289848Sjkim mov $ptr,#0 232289848Sjkim 233289848Sjkim.Lenc_key_abort: 234289848Sjkim mov x0,$ptr // return value 235289848Sjkim `"ldr x29,[sp],#16" if ($flavour =~ /64/)` 236289848Sjkim ret 237289848Sjkim.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key 238289848Sjkim 239289848Sjkim.globl ${prefix}_set_decrypt_key 240289848Sjkim.type ${prefix}_set_decrypt_key,%function 241289848Sjkim.align 5 242289848Sjkim${prefix}_set_decrypt_key: 243289848Sjkim___ 244289848Sjkim$code.=<<___ if ($flavour =~ /64/); 245289848Sjkim stp x29,x30,[sp,#-16]! 246289848Sjkim add x29,sp,#0 247289848Sjkim___ 248289848Sjkim$code.=<<___ if ($flavour !~ /64/); 249289848Sjkim stmdb sp!,{r4,lr} 250289848Sjkim___ 251289848Sjkim$code.=<<___; 252289848Sjkim bl .Lenc_key 253289848Sjkim 254289848Sjkim cmp x0,#0 255289848Sjkim b.ne .Ldec_key_abort 256289848Sjkim 257289848Sjkim sub $out,$out,#240 // restore original $out 258289848Sjkim mov x4,#-16 259289848Sjkim add $inp,$out,x12,lsl#4 // end of key schedule 260289848Sjkim 261289848Sjkim vld1.32 {v0.16b},[$out] 262289848Sjkim vld1.32 {v1.16b},[$inp] 263289848Sjkim vst1.32 {v0.16b},[$inp],x4 264289848Sjkim vst1.32 {v1.16b},[$out],#16 265289848Sjkim 266289848Sjkim.Loop_imc: 267289848Sjkim vld1.32 {v0.16b},[$out] 268289848Sjkim vld1.32 {v1.16b},[$inp] 269289848Sjkim aesimc v0.16b,v0.16b 270289848Sjkim aesimc v1.16b,v1.16b 271289848Sjkim vst1.32 {v0.16b},[$inp],x4 272289848Sjkim vst1.32 {v1.16b},[$out],#16 273289848Sjkim cmp $inp,$out 274289848Sjkim b.hi .Loop_imc 275289848Sjkim 276289848Sjkim vld1.32 {v0.16b},[$out] 277289848Sjkim aesimc v0.16b,v0.16b 278289848Sjkim vst1.32 {v0.16b},[$inp] 279289848Sjkim 280289848Sjkim eor x0,x0,x0 // return value 281289848Sjkim.Ldec_key_abort: 282289848Sjkim___ 283289848Sjkim$code.=<<___ if ($flavour !~ /64/); 284289848Sjkim ldmia sp!,{r4,pc} 285289848Sjkim___ 286289848Sjkim$code.=<<___ if ($flavour =~ /64/); 287289848Sjkim ldp x29,x30,[sp],#16 288289848Sjkim ret 289289848Sjkim___ 290289848Sjkim$code.=<<___; 291289848Sjkim.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key 292289848Sjkim___ 293289848Sjkim}}} 294289848Sjkim{{{ 295289848Sjkimsub gen_block () { 296289848Sjkimmy $dir = shift; 297289848Sjkimmy ($e,$mc) = $dir eq "en" ? ("e","mc") : ("d","imc"); 298289848Sjkimmy ($inp,$out,$key)=map("x$_",(0..2)); 299289848Sjkimmy $rounds="w3"; 300289848Sjkimmy ($rndkey0,$rndkey1,$inout)=map("q$_",(0..3)); 301289848Sjkim 302289848Sjkim$code.=<<___; 303289848Sjkim.globl ${prefix}_${dir}crypt 304289848Sjkim.type ${prefix}_${dir}crypt,%function 305289848Sjkim.align 5 306289848Sjkim${prefix}_${dir}crypt: 307289848Sjkim ldr $rounds,[$key,#240] 308289848Sjkim vld1.32 {$rndkey0},[$key],#16 309289848Sjkim vld1.8 {$inout},[$inp] 310289848Sjkim sub $rounds,$rounds,#2 311289848Sjkim vld1.32 {$rndkey1},[$key],#16 312289848Sjkim 313289848Sjkim.Loop_${dir}c: 314289848Sjkim aes$e $inout,$rndkey0 315289848Sjkim aes$mc $inout,$inout 316289848Sjkim vld1.32 {$rndkey0},[$key],#16 317289848Sjkim subs $rounds,$rounds,#2 318289848Sjkim aes$e $inout,$rndkey1 319289848Sjkim aes$mc $inout,$inout 320289848Sjkim vld1.32 {$rndkey1},[$key],#16 321289848Sjkim b.gt .Loop_${dir}c 322289848Sjkim 323289848Sjkim aes$e $inout,$rndkey0 324289848Sjkim aes$mc $inout,$inout 325289848Sjkim vld1.32 {$rndkey0},[$key] 326289848Sjkim aes$e $inout,$rndkey1 327289848Sjkim veor $inout,$inout,$rndkey0 328289848Sjkim 329289848Sjkim vst1.8 {$inout},[$out] 330289848Sjkim ret 331289848Sjkim.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt 332289848Sjkim___ 333289848Sjkim} 334289848Sjkim&gen_block("en"); 335289848Sjkim&gen_block("de"); 336289848Sjkim}}} 337289848Sjkim{{{ 338289848Sjkimmy ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5"; 339289848Sjkimmy ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12"); 340289848Sjkimmy ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); 341289848Sjkim 342289848Sjkimmy ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); 343289848Sjkimmy ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key); 344289848Sjkim 345289848Sjkim### q8-q15 preloaded key schedule 346289848Sjkim 347289848Sjkim$code.=<<___; 348289848Sjkim.globl ${prefix}_cbc_encrypt 349289848Sjkim.type ${prefix}_cbc_encrypt,%function 350289848Sjkim.align 5 351289848Sjkim${prefix}_cbc_encrypt: 352289848Sjkim___ 353289848Sjkim$code.=<<___ if ($flavour =~ /64/); 354289848Sjkim stp x29,x30,[sp,#-16]! 355289848Sjkim add x29,sp,#0 356289848Sjkim___ 357289848Sjkim$code.=<<___ if ($flavour !~ /64/); 358289848Sjkim mov ip,sp 359289848Sjkim stmdb sp!,{r4-r8,lr} 360289848Sjkim vstmdb sp!,{d8-d15} @ ABI specification says so 361289848Sjkim ldmia ip,{r4-r5} @ load remaining args 362289848Sjkim___ 363289848Sjkim$code.=<<___; 364289848Sjkim subs $len,$len,#16 365289848Sjkim mov $step,#16 366289848Sjkim b.lo .Lcbc_abort 367289848Sjkim cclr $step,eq 368289848Sjkim 369289848Sjkim cmp $enc,#0 // en- or decrypting? 370289848Sjkim ldr $rounds,[$key,#240] 371289848Sjkim and $len,$len,#-16 372289848Sjkim vld1.8 {$ivec},[$ivp] 373289848Sjkim vld1.8 {$dat},[$inp],$step 374289848Sjkim 375289848Sjkim vld1.32 {q8-q9},[$key] // load key schedule... 376289848Sjkim sub $rounds,$rounds,#6 377289848Sjkim add $key_,$key,x5,lsl#4 // pointer to last 7 round keys 378289848Sjkim sub $rounds,$rounds,#2 379289848Sjkim vld1.32 {q10-q11},[$key_],#32 380289848Sjkim vld1.32 {q12-q13},[$key_],#32 381289848Sjkim vld1.32 {q14-q15},[$key_],#32 382289848Sjkim vld1.32 {$rndlast},[$key_] 383289848Sjkim 384289848Sjkim add $key_,$key,#32 385289848Sjkim mov $cnt,$rounds 386289848Sjkim b.eq .Lcbc_dec 387289848Sjkim 388289848Sjkim cmp $rounds,#2 389289848Sjkim veor $dat,$dat,$ivec 390289848Sjkim veor $rndzero_n_last,q8,$rndlast 391289848Sjkim b.eq .Lcbc_enc128 392289848Sjkim 393289848Sjkim vld1.32 {$in0-$in1},[$key_] 394289848Sjkim add $key_,$key,#16 395289848Sjkim add $key4,$key,#16*4 396289848Sjkim add $key5,$key,#16*5 397289848Sjkim aese $dat,q8 398289848Sjkim aesmc $dat,$dat 399289848Sjkim add $key6,$key,#16*6 400289848Sjkim add $key7,$key,#16*7 401289848Sjkim b .Lenter_cbc_enc 402289848Sjkim 403289848Sjkim.align 4 404289848Sjkim.Loop_cbc_enc: 405289848Sjkim aese $dat,q8 406289848Sjkim aesmc $dat,$dat 407289848Sjkim vst1.8 {$ivec},[$out],#16 408289848Sjkim.Lenter_cbc_enc: 409289848Sjkim aese $dat,q9 410289848Sjkim aesmc $dat,$dat 411289848Sjkim aese $dat,$in0 412289848Sjkim aesmc $dat,$dat 413289848Sjkim vld1.32 {q8},[$key4] 414289848Sjkim cmp $rounds,#4 415289848Sjkim aese $dat,$in1 416289848Sjkim aesmc $dat,$dat 417289848Sjkim vld1.32 {q9},[$key5] 418289848Sjkim b.eq .Lcbc_enc192 419289848Sjkim 420289848Sjkim aese $dat,q8 421289848Sjkim aesmc $dat,$dat 422289848Sjkim vld1.32 {q8},[$key6] 423289848Sjkim aese $dat,q9 424289848Sjkim aesmc $dat,$dat 425289848Sjkim vld1.32 {q9},[$key7] 426289848Sjkim nop 427289848Sjkim 428289848Sjkim.Lcbc_enc192: 429289848Sjkim aese $dat,q8 430289848Sjkim aesmc $dat,$dat 431289848Sjkim subs $len,$len,#16 432289848Sjkim aese $dat,q9 433289848Sjkim aesmc $dat,$dat 434289848Sjkim cclr $step,eq 435289848Sjkim aese $dat,q10 436289848Sjkim aesmc $dat,$dat 437289848Sjkim aese $dat,q11 438289848Sjkim aesmc $dat,$dat 439289848Sjkim vld1.8 {q8},[$inp],$step 440289848Sjkim aese $dat,q12 441289848Sjkim aesmc $dat,$dat 442289848Sjkim veor q8,q8,$rndzero_n_last 443289848Sjkim aese $dat,q13 444289848Sjkim aesmc $dat,$dat 445289848Sjkim vld1.32 {q9},[$key_] // re-pre-load rndkey[1] 446289848Sjkim aese $dat,q14 447289848Sjkim aesmc $dat,$dat 448289848Sjkim aese $dat,q15 449289848Sjkim veor $ivec,$dat,$rndlast 450289848Sjkim b.hs .Loop_cbc_enc 451289848Sjkim 452289848Sjkim vst1.8 {$ivec},[$out],#16 453289848Sjkim b .Lcbc_done 454289848Sjkim 455289848Sjkim.align 5 456289848Sjkim.Lcbc_enc128: 457289848Sjkim vld1.32 {$in0-$in1},[$key_] 458289848Sjkim aese $dat,q8 459289848Sjkim aesmc $dat,$dat 460289848Sjkim b .Lenter_cbc_enc128 461289848Sjkim.Loop_cbc_enc128: 462289848Sjkim aese $dat,q8 463289848Sjkim aesmc $dat,$dat 464289848Sjkim vst1.8 {$ivec},[$out],#16 465289848Sjkim.Lenter_cbc_enc128: 466289848Sjkim aese $dat,q9 467289848Sjkim aesmc $dat,$dat 468289848Sjkim subs $len,$len,#16 469289848Sjkim aese $dat,$in0 470289848Sjkim aesmc $dat,$dat 471289848Sjkim cclr $step,eq 472289848Sjkim aese $dat,$in1 473289848Sjkim aesmc $dat,$dat 474289848Sjkim aese $dat,q10 475289848Sjkim aesmc $dat,$dat 476289848Sjkim aese $dat,q11 477289848Sjkim aesmc $dat,$dat 478289848Sjkim vld1.8 {q8},[$inp],$step 479289848Sjkim aese $dat,q12 480289848Sjkim aesmc $dat,$dat 481289848Sjkim aese $dat,q13 482289848Sjkim aesmc $dat,$dat 483289848Sjkim aese $dat,q14 484289848Sjkim aesmc $dat,$dat 485289848Sjkim veor q8,q8,$rndzero_n_last 486289848Sjkim aese $dat,q15 487289848Sjkim veor $ivec,$dat,$rndlast 488289848Sjkim b.hs .Loop_cbc_enc128 489289848Sjkim 490289848Sjkim vst1.8 {$ivec},[$out],#16 491289848Sjkim b .Lcbc_done 492289848Sjkim___ 493289848Sjkim{ 494289848Sjkimmy ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); 495289848Sjkim$code.=<<___; 496289848Sjkim.align 5 497289848Sjkim.Lcbc_dec: 498289848Sjkim vld1.8 {$dat2},[$inp],#16 499289848Sjkim subs $len,$len,#32 // bias 500289848Sjkim add $cnt,$rounds,#2 501289848Sjkim vorr $in1,$dat,$dat 502289848Sjkim vorr $dat1,$dat,$dat 503289848Sjkim vorr $in2,$dat2,$dat2 504289848Sjkim b.lo .Lcbc_dec_tail 505289848Sjkim 506289848Sjkim vorr $dat1,$dat2,$dat2 507289848Sjkim vld1.8 {$dat2},[$inp],#16 508289848Sjkim vorr $in0,$dat,$dat 509289848Sjkim vorr $in1,$dat1,$dat1 510289848Sjkim vorr $in2,$dat2,$dat2 511289848Sjkim 512289848Sjkim.Loop3x_cbc_dec: 513289848Sjkim aesd $dat0,q8 514289848Sjkim aesimc $dat0,$dat0 515289848Sjkim aesd $dat1,q8 516289848Sjkim aesimc $dat1,$dat1 517289848Sjkim aesd $dat2,q8 518289848Sjkim aesimc $dat2,$dat2 519289848Sjkim vld1.32 {q8},[$key_],#16 520289848Sjkim subs $cnt,$cnt,#2 521289848Sjkim aesd $dat0,q9 522289848Sjkim aesimc $dat0,$dat0 523289848Sjkim aesd $dat1,q9 524289848Sjkim aesimc $dat1,$dat1 525289848Sjkim aesd $dat2,q9 526289848Sjkim aesimc $dat2,$dat2 527289848Sjkim vld1.32 {q9},[$key_],#16 528289848Sjkim b.gt .Loop3x_cbc_dec 529289848Sjkim 530289848Sjkim aesd $dat0,q8 531289848Sjkim aesimc $dat0,$dat0 532289848Sjkim aesd $dat1,q8 533289848Sjkim aesimc $dat1,$dat1 534289848Sjkim aesd $dat2,q8 535289848Sjkim aesimc $dat2,$dat2 536289848Sjkim veor $tmp0,$ivec,$rndlast 537289848Sjkim subs $len,$len,#0x30 538289848Sjkim veor $tmp1,$in0,$rndlast 539289848Sjkim mov.lo x6,$len // x6, $cnt, is zero at this point 540289848Sjkim aesd $dat0,q9 541289848Sjkim aesimc $dat0,$dat0 542289848Sjkim aesd $dat1,q9 543289848Sjkim aesimc $dat1,$dat1 544289848Sjkim aesd $dat2,q9 545289848Sjkim aesimc $dat2,$dat2 546289848Sjkim veor $tmp2,$in1,$rndlast 547289848Sjkim add $inp,$inp,x6 // $inp is adjusted in such way that 548289848Sjkim // at exit from the loop $dat1-$dat2 549289848Sjkim // are loaded with last "words" 550289848Sjkim vorr $ivec,$in2,$in2 551289848Sjkim mov $key_,$key 552289848Sjkim aesd $dat0,q12 553289848Sjkim aesimc $dat0,$dat0 554289848Sjkim aesd $dat1,q12 555289848Sjkim aesimc $dat1,$dat1 556289848Sjkim aesd $dat2,q12 557289848Sjkim aesimc $dat2,$dat2 558289848Sjkim vld1.8 {$in0},[$inp],#16 559289848Sjkim aesd $dat0,q13 560289848Sjkim aesimc $dat0,$dat0 561289848Sjkim aesd $dat1,q13 562289848Sjkim aesimc $dat1,$dat1 563289848Sjkim aesd $dat2,q13 564289848Sjkim aesimc $dat2,$dat2 565289848Sjkim vld1.8 {$in1},[$inp],#16 566289848Sjkim aesd $dat0,q14 567289848Sjkim aesimc $dat0,$dat0 568289848Sjkim aesd $dat1,q14 569289848Sjkim aesimc $dat1,$dat1 570289848Sjkim aesd $dat2,q14 571289848Sjkim aesimc $dat2,$dat2 572289848Sjkim vld1.8 {$in2},[$inp],#16 573289848Sjkim aesd $dat0,q15 574289848Sjkim aesd $dat1,q15 575289848Sjkim aesd $dat2,q15 576289848Sjkim vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] 577289848Sjkim add $cnt,$rounds,#2 578289848Sjkim veor $tmp0,$tmp0,$dat0 579289848Sjkim veor $tmp1,$tmp1,$dat1 580289848Sjkim veor $dat2,$dat2,$tmp2 581289848Sjkim vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] 582289848Sjkim vst1.8 {$tmp0},[$out],#16 583289848Sjkim vorr $dat0,$in0,$in0 584289848Sjkim vst1.8 {$tmp1},[$out],#16 585289848Sjkim vorr $dat1,$in1,$in1 586289848Sjkim vst1.8 {$dat2},[$out],#16 587289848Sjkim vorr $dat2,$in2,$in2 588289848Sjkim b.hs .Loop3x_cbc_dec 589289848Sjkim 590289848Sjkim cmn $len,#0x30 591289848Sjkim b.eq .Lcbc_done 592289848Sjkim nop 593289848Sjkim 594289848Sjkim.Lcbc_dec_tail: 595289848Sjkim aesd $dat1,q8 596289848Sjkim aesimc $dat1,$dat1 597289848Sjkim aesd $dat2,q8 598289848Sjkim aesimc $dat2,$dat2 599289848Sjkim vld1.32 {q8},[$key_],#16 600289848Sjkim subs $cnt,$cnt,#2 601289848Sjkim aesd $dat1,q9 602289848Sjkim aesimc $dat1,$dat1 603289848Sjkim aesd $dat2,q9 604289848Sjkim aesimc $dat2,$dat2 605289848Sjkim vld1.32 {q9},[$key_],#16 606289848Sjkim b.gt .Lcbc_dec_tail 607289848Sjkim 608289848Sjkim aesd $dat1,q8 609289848Sjkim aesimc $dat1,$dat1 610289848Sjkim aesd $dat2,q8 611289848Sjkim aesimc $dat2,$dat2 612289848Sjkim aesd $dat1,q9 613289848Sjkim aesimc $dat1,$dat1 614289848Sjkim aesd $dat2,q9 615289848Sjkim aesimc $dat2,$dat2 616289848Sjkim aesd $dat1,q12 617289848Sjkim aesimc $dat1,$dat1 618289848Sjkim aesd $dat2,q12 619289848Sjkim aesimc $dat2,$dat2 620289848Sjkim cmn $len,#0x20 621289848Sjkim aesd $dat1,q13 622289848Sjkim aesimc $dat1,$dat1 623289848Sjkim aesd $dat2,q13 624289848Sjkim aesimc $dat2,$dat2 625289848Sjkim veor $tmp1,$ivec,$rndlast 626289848Sjkim aesd $dat1,q14 627289848Sjkim aesimc $dat1,$dat1 628289848Sjkim aesd $dat2,q14 629289848Sjkim aesimc $dat2,$dat2 630289848Sjkim veor $tmp2,$in1,$rndlast 631289848Sjkim aesd $dat1,q15 632289848Sjkim aesd $dat2,q15 633289848Sjkim b.eq .Lcbc_dec_one 634289848Sjkim veor $tmp1,$tmp1,$dat1 635289848Sjkim veor $tmp2,$tmp2,$dat2 636289848Sjkim vorr $ivec,$in2,$in2 637289848Sjkim vst1.8 {$tmp1},[$out],#16 638289848Sjkim vst1.8 {$tmp2},[$out],#16 639289848Sjkim b .Lcbc_done 640289848Sjkim 641289848Sjkim.Lcbc_dec_one: 642289848Sjkim veor $tmp1,$tmp1,$dat2 643289848Sjkim vorr $ivec,$in2,$in2 644289848Sjkim vst1.8 {$tmp1},[$out],#16 645289848Sjkim 646289848Sjkim.Lcbc_done: 647289848Sjkim vst1.8 {$ivec},[$ivp] 648289848Sjkim.Lcbc_abort: 649289848Sjkim___ 650289848Sjkim} 651289848Sjkim$code.=<<___ if ($flavour !~ /64/); 652289848Sjkim vldmia sp!,{d8-d15} 653289848Sjkim ldmia sp!,{r4-r8,pc} 654289848Sjkim___ 655289848Sjkim$code.=<<___ if ($flavour =~ /64/); 656289848Sjkim ldr x29,[sp],#16 657289848Sjkim ret 658289848Sjkim___ 659289848Sjkim$code.=<<___; 660289848Sjkim.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt 661289848Sjkim___ 662289848Sjkim}}} 663289848Sjkim{{{ 664289848Sjkimmy ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); 665289848Sjkimmy ($rounds,$cnt,$key_)=("w5","w6","x7"); 666289848Sjkimmy ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12)); 667289848Sjkimmy $step="x12"; # aliases with $tctr2 668289848Sjkim 669289848Sjkimmy ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); 670289848Sjkimmy ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); 671289848Sjkim 672289848Sjkimmy ($dat,$tmp)=($dat0,$tmp0); 673289848Sjkim 674289848Sjkim### q8-q15 preloaded key schedule 675289848Sjkim 676289848Sjkim$code.=<<___; 677289848Sjkim.globl ${prefix}_ctr32_encrypt_blocks 678289848Sjkim.type ${prefix}_ctr32_encrypt_blocks,%function 679289848Sjkim.align 5 680289848Sjkim${prefix}_ctr32_encrypt_blocks: 681289848Sjkim___ 682289848Sjkim$code.=<<___ if ($flavour =~ /64/); 683289848Sjkim stp x29,x30,[sp,#-16]! 684289848Sjkim add x29,sp,#0 685289848Sjkim___ 686289848Sjkim$code.=<<___ if ($flavour !~ /64/); 687289848Sjkim mov ip,sp 688289848Sjkim stmdb sp!,{r4-r10,lr} 689289848Sjkim vstmdb sp!,{d8-d15} @ ABI specification says so 690289848Sjkim ldr r4, [ip] @ load remaining arg 691289848Sjkim___ 692289848Sjkim$code.=<<___; 693289848Sjkim ldr $rounds,[$key,#240] 694289848Sjkim 695289848Sjkim ldr $ctr, [$ivp, #12] 696289848Sjkim vld1.32 {$dat0},[$ivp] 697289848Sjkim 698289848Sjkim vld1.32 {q8-q9},[$key] // load key schedule... 699289848Sjkim sub $rounds,$rounds,#4 700289848Sjkim mov $step,#16 701289848Sjkim cmp $len,#2 702289848Sjkim add $key_,$key,x5,lsl#4 // pointer to last 5 round keys 703289848Sjkim sub $rounds,$rounds,#2 704289848Sjkim vld1.32 {q12-q13},[$key_],#32 705289848Sjkim vld1.32 {q14-q15},[$key_],#32 706289848Sjkim vld1.32 {$rndlast},[$key_] 707289848Sjkim add $key_,$key,#32 708289848Sjkim mov $cnt,$rounds 709289848Sjkim cclr $step,lo 710289848Sjkim#ifndef __ARMEB__ 711289848Sjkim rev $ctr, $ctr 712289848Sjkim#endif 713289848Sjkim vorr $dat1,$dat0,$dat0 714289848Sjkim add $tctr1, $ctr, #1 715289848Sjkim vorr $dat2,$dat0,$dat0 716289848Sjkim add $ctr, $ctr, #2 717289848Sjkim vorr $ivec,$dat0,$dat0 718289848Sjkim rev $tctr1, $tctr1 719289848Sjkim vmov.32 ${dat1}[3],$tctr1 720289848Sjkim b.ls .Lctr32_tail 721289848Sjkim rev $tctr2, $ctr 722289848Sjkim sub $len,$len,#3 // bias 723289848Sjkim vmov.32 ${dat2}[3],$tctr2 724289848Sjkim b .Loop3x_ctr32 725289848Sjkim 726289848Sjkim.align 4 727289848Sjkim.Loop3x_ctr32: 728289848Sjkim aese $dat0,q8 729289848Sjkim aesmc $dat0,$dat0 730289848Sjkim aese $dat1,q8 731289848Sjkim aesmc $dat1,$dat1 732289848Sjkim aese $dat2,q8 733289848Sjkim aesmc $dat2,$dat2 734289848Sjkim vld1.32 {q8},[$key_],#16 735289848Sjkim subs $cnt,$cnt,#2 736289848Sjkim aese $dat0,q9 737289848Sjkim aesmc $dat0,$dat0 738289848Sjkim aese $dat1,q9 739289848Sjkim aesmc $dat1,$dat1 740289848Sjkim aese $dat2,q9 741289848Sjkim aesmc $dat2,$dat2 742289848Sjkim vld1.32 {q9},[$key_],#16 743289848Sjkim b.gt .Loop3x_ctr32 744289848Sjkim 745289848Sjkim aese $dat0,q8 746289848Sjkim aesmc $tmp0,$dat0 747289848Sjkim aese $dat1,q8 748289848Sjkim aesmc $tmp1,$dat1 749289848Sjkim vld1.8 {$in0},[$inp],#16 750289848Sjkim vorr $dat0,$ivec,$ivec 751289848Sjkim aese $dat2,q8 752289848Sjkim aesmc $dat2,$dat2 753289848Sjkim vld1.8 {$in1},[$inp],#16 754289848Sjkim vorr $dat1,$ivec,$ivec 755289848Sjkim aese $tmp0,q9 756289848Sjkim aesmc $tmp0,$tmp0 757289848Sjkim aese $tmp1,q9 758289848Sjkim aesmc $tmp1,$tmp1 759289848Sjkim vld1.8 {$in2},[$inp],#16 760289848Sjkim mov $key_,$key 761289848Sjkim aese $dat2,q9 762289848Sjkim aesmc $tmp2,$dat2 763289848Sjkim vorr $dat2,$ivec,$ivec 764289848Sjkim add $tctr0,$ctr,#1 765289848Sjkim aese $tmp0,q12 766289848Sjkim aesmc $tmp0,$tmp0 767289848Sjkim aese $tmp1,q12 768289848Sjkim aesmc $tmp1,$tmp1 769289848Sjkim veor $in0,$in0,$rndlast 770289848Sjkim add $tctr1,$ctr,#2 771289848Sjkim aese $tmp2,q12 772289848Sjkim aesmc $tmp2,$tmp2 773289848Sjkim veor $in1,$in1,$rndlast 774289848Sjkim add $ctr,$ctr,#3 775289848Sjkim aese $tmp0,q13 776289848Sjkim aesmc $tmp0,$tmp0 777289848Sjkim aese $tmp1,q13 778289848Sjkim aesmc $tmp1,$tmp1 779289848Sjkim veor $in2,$in2,$rndlast 780289848Sjkim rev $tctr0,$tctr0 781289848Sjkim aese $tmp2,q13 782289848Sjkim aesmc $tmp2,$tmp2 783289848Sjkim vmov.32 ${dat0}[3], $tctr0 784289848Sjkim rev $tctr1,$tctr1 785289848Sjkim aese $tmp0,q14 786289848Sjkim aesmc $tmp0,$tmp0 787289848Sjkim aese $tmp1,q14 788289848Sjkim aesmc $tmp1,$tmp1 789289848Sjkim vmov.32 ${dat1}[3], $tctr1 790289848Sjkim rev $tctr2,$ctr 791289848Sjkim aese $tmp2,q14 792289848Sjkim aesmc $tmp2,$tmp2 793289848Sjkim vmov.32 ${dat2}[3], $tctr2 794289848Sjkim subs $len,$len,#3 795289848Sjkim aese $tmp0,q15 796289848Sjkim aese $tmp1,q15 797289848Sjkim aese $tmp2,q15 798289848Sjkim 799289848Sjkim veor $in0,$in0,$tmp0 800289848Sjkim vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] 801289848Sjkim vst1.8 {$in0},[$out],#16 802289848Sjkim veor $in1,$in1,$tmp1 803289848Sjkim mov $cnt,$rounds 804289848Sjkim vst1.8 {$in1},[$out],#16 805289848Sjkim veor $in2,$in2,$tmp2 806289848Sjkim vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] 807289848Sjkim vst1.8 {$in2},[$out],#16 808289848Sjkim b.hs .Loop3x_ctr32 809289848Sjkim 810289848Sjkim adds $len,$len,#3 811289848Sjkim b.eq .Lctr32_done 812289848Sjkim cmp $len,#1 813289848Sjkim mov $step,#16 814289848Sjkim cclr $step,eq 815289848Sjkim 816289848Sjkim.Lctr32_tail: 817289848Sjkim aese $dat0,q8 818289848Sjkim aesmc $dat0,$dat0 819289848Sjkim aese $dat1,q8 820289848Sjkim aesmc $dat1,$dat1 821289848Sjkim vld1.32 {q8},[$key_],#16 822289848Sjkim subs $cnt,$cnt,#2 823289848Sjkim aese $dat0,q9 824289848Sjkim aesmc $dat0,$dat0 825289848Sjkim aese $dat1,q9 826289848Sjkim aesmc $dat1,$dat1 827289848Sjkim vld1.32 {q9},[$key_],#16 828289848Sjkim b.gt .Lctr32_tail 829289848Sjkim 830289848Sjkim aese $dat0,q8 831289848Sjkim aesmc $dat0,$dat0 832289848Sjkim aese $dat1,q8 833289848Sjkim aesmc $dat1,$dat1 834289848Sjkim aese $dat0,q9 835289848Sjkim aesmc $dat0,$dat0 836289848Sjkim aese $dat1,q9 837289848Sjkim aesmc $dat1,$dat1 838289848Sjkim vld1.8 {$in0},[$inp],$step 839289848Sjkim aese $dat0,q12 840289848Sjkim aesmc $dat0,$dat0 841289848Sjkim aese $dat1,q12 842289848Sjkim aesmc $dat1,$dat1 843289848Sjkim vld1.8 {$in1},[$inp] 844289848Sjkim aese $dat0,q13 845289848Sjkim aesmc $dat0,$dat0 846289848Sjkim aese $dat1,q13 847289848Sjkim aesmc $dat1,$dat1 848289848Sjkim veor $in0,$in0,$rndlast 849289848Sjkim aese $dat0,q14 850289848Sjkim aesmc $dat0,$dat0 851289848Sjkim aese $dat1,q14 852289848Sjkim aesmc $dat1,$dat1 853289848Sjkim veor $in1,$in1,$rndlast 854289848Sjkim aese $dat0,q15 855289848Sjkim aese $dat1,q15 856289848Sjkim 857289848Sjkim cmp $len,#1 858289848Sjkim veor $in0,$in0,$dat0 859289848Sjkim veor $in1,$in1,$dat1 860289848Sjkim vst1.8 {$in0},[$out],#16 861289848Sjkim b.eq .Lctr32_done 862289848Sjkim vst1.8 {$in1},[$out] 863289848Sjkim 864289848Sjkim.Lctr32_done: 865289848Sjkim___ 866289848Sjkim$code.=<<___ if ($flavour !~ /64/); 867289848Sjkim vldmia sp!,{d8-d15} 868289848Sjkim ldmia sp!,{r4-r10,pc} 869289848Sjkim___ 870289848Sjkim$code.=<<___ if ($flavour =~ /64/); 871289848Sjkim ldr x29,[sp],#16 872289848Sjkim ret 873289848Sjkim___ 874289848Sjkim$code.=<<___; 875289848Sjkim.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks 876289848Sjkim___ 877289848Sjkim}}} 878289848Sjkim$code.=<<___; 879289848Sjkim#endif 880289848Sjkim___ 881289848Sjkim######################################## 882289848Sjkimif ($flavour =~ /64/) { ######## 64-bit code 883289848Sjkim my %opcode = ( 884289848Sjkim "aesd" => 0x4e285800, "aese" => 0x4e284800, 885289848Sjkim "aesimc"=> 0x4e287800, "aesmc" => 0x4e286800 ); 886289848Sjkim 887289848Sjkim local *unaes = sub { 888289848Sjkim my ($mnemonic,$arg)=@_; 889289848Sjkim 890289848Sjkim $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o && 891289848Sjkim sprintf ".inst\t0x%08x\t//%s %s", 892289848Sjkim $opcode{$mnemonic}|$1|($2<<5), 893289848Sjkim $mnemonic,$arg; 894289848Sjkim }; 895289848Sjkim 896289848Sjkim foreach(split("\n",$code)) { 897289848Sjkim s/\`([^\`]*)\`/eval($1)/geo; 898289848Sjkim 899289848Sjkim s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers 900289848Sjkim s/@\s/\/\//o; # old->new style commentary 901289848Sjkim 902289848Sjkim #s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or 903289848Sjkim s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or 904289848Sjkim s/mov\.([a-z]+)\s+([wx][0-9]+),\s*([wx][0-9]+)/csel $2,$3,$2,$1/o or 905289848Sjkim s/vmov\.i8/movi/o or # fix up legacy mnemonics 906289848Sjkim s/vext\.8/ext/o or 907289848Sjkim s/vrev32\.8/rev32/o or 908289848Sjkim s/vtst\.8/cmtst/o or 909289848Sjkim s/vshr/ushr/o or 910289848Sjkim s/^(\s+)v/$1/o or # strip off v prefix 911289848Sjkim s/\bbx\s+lr\b/ret/o; 912289848Sjkim 913289848Sjkim # fix up remainig legacy suffixes 914289848Sjkim s/\.[ui]?8//o; 915289848Sjkim m/\],#8/o and s/\.16b/\.8b/go; 916289848Sjkim s/\.[ui]?32//o and s/\.16b/\.4s/go; 917289848Sjkim s/\.[ui]?64//o and s/\.16b/\.2d/go; 918289848Sjkim s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o; 919289848Sjkim 920289848Sjkim print $_,"\n"; 921289848Sjkim } 922289848Sjkim} else { ######## 32-bit code 923289848Sjkim my %opcode = ( 924289848Sjkim "aesd" => 0xf3b00340, "aese" => 0xf3b00300, 925289848Sjkim "aesimc"=> 0xf3b003c0, "aesmc" => 0xf3b00380 ); 926289848Sjkim 927289848Sjkim local *unaes = sub { 928289848Sjkim my ($mnemonic,$arg)=@_; 929289848Sjkim 930289848Sjkim if ($arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o) { 931289848Sjkim my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) 932289848Sjkim |(($2&7)<<1) |(($2&8)<<2); 933289848Sjkim # since ARMv7 instructions are always encoded little-endian. 934289848Sjkim # correct solution is to use .inst directive, but older 935289848Sjkim # assemblers don't implement it:-( 936289848Sjkim sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", 937289848Sjkim $word&0xff,($word>>8)&0xff, 938289848Sjkim ($word>>16)&0xff,($word>>24)&0xff, 939289848Sjkim $mnemonic,$arg; 940289848Sjkim } 941289848Sjkim }; 942289848Sjkim 943289848Sjkim sub unvtbl { 944289848Sjkim my $arg=shift; 945289848Sjkim 946289848Sjkim $arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o && 947289848Sjkim sprintf "vtbl.8 d%d,{q%d},d%d\n\t". 948289848Sjkim "vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1; 949289848Sjkim } 950289848Sjkim 951289848Sjkim sub unvdup32 { 952289848Sjkim my $arg=shift; 953289848Sjkim 954289848Sjkim $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o && 955289848Sjkim sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1; 956289848Sjkim } 957289848Sjkim 958289848Sjkim sub unvmov32 { 959289848Sjkim my $arg=shift; 960289848Sjkim 961289848Sjkim $arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o && 962289848Sjkim sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3; 963289848Sjkim } 964289848Sjkim 965289848Sjkim foreach(split("\n",$code)) { 966289848Sjkim s/\`([^\`]*)\`/eval($1)/geo; 967289848Sjkim 968289848Sjkim s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers 969289848Sjkim s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers 970289848Sjkim s/\/\/\s?/@ /o; # new->old style commentary 971289848Sjkim 972289848Sjkim # fix up remainig new-style suffixes 973289848Sjkim s/\{q([0-9]+)\},\s*\[(.+)\],#8/sprintf "{d%d},[$2]!",2*$1/eo or 974289848Sjkim s/\],#[0-9]+/]!/o; 975289848Sjkim 976289848Sjkim s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or 977289848Sjkim s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or 978289848Sjkim s/vtbl\.8\s+(.*)/unvtbl($1)/geo or 979289848Sjkim s/vdup\.32\s+(.*)/unvdup32($1)/geo or 980289848Sjkim s/vmov\.32\s+(.*)/unvmov32($1)/geo or 981289848Sjkim s/^(\s+)b\./$1b/o or 982289848Sjkim s/^(\s+)mov\./$1mov/o or 983289848Sjkim s/^(\s+)ret/$1bx\tlr/o; 984289848Sjkim 985289848Sjkim print $_,"\n"; 986289848Sjkim } 987289848Sjkim} 988289848Sjkim 989289848Sjkimclose STDOUT; 990