| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env perl | |
| 2 # | |
| 3 # ==================================================================== | |
| 4 # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL | |
| 5 # project. The module is, however, dual licensed under OpenSSL and | |
| 6 # CRYPTOGAMS licenses depending on where you obtain it. For further | |
| 7 # details see http://www.openssl.org/~appro/cryptogams/. | |
| 8 # ==================================================================== | |
| 9 # | |
| 10 # July 2004 | |
| 11 # | |
| 12 # 2.22x RC4 tune-up:-) It should be noted though that my hand [as in | |
| 13 # "hand-coded assembler"] doesn't stand for the whole improvement | |
| 14 # coefficient. It turned out that eliminating RC4_CHAR from config | |
| 15 # line results in ~40% improvement (yes, even for C implementation). | |
| 16 # Presumably it has everything to do with AMD cache architecture and | |
| 17 # RAW or whatever penalties. Once again! The module *requires* config | |
| 18 # line *without* RC4_CHAR! As for coding "secret," I bet on partial | |
| 19 # register arithmetics. For example instead of 'inc %r8; and $255,%r8' | |
| 20 # I simply 'inc %r8b'. Even though optimization manual discourages | |
| 21 # to operate on partial registers, it turned out to be the best bet. | |
| 22 # At least for AMD... How IA32E would perform remains to be seen... | |
| 23 | |
| 24 # November 2004 | |
| 25 # | |
| 26 # As was shown by Marc Bevand reordering of couple of load operations | |
| 27 # results in even higher performance gain of 3.3x:-) At least on | |
| 28 # Opteron... For reference, 1x in this case is RC4_CHAR C-code | |
| 29 # compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock. | |
| 30 # Latter means that if you want to *estimate* what to expect from | |
| 31 # *your* Opteron, then multiply 54 by 3.3 and clock frequency in GHz. | |
| 32 | |
| 33 # November 2004 | |
| 34 # | |
| 35 # Intel P4 EM64T core was found to run the AMD64 code really slow... | |
| 36 # The only way to achieve comparable performance on P4 was to keep | |
| 37 # RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to | |
| 38 # compose blended code, which would perform even within 30% marginal | |
| 39 # on either AMD and Intel platforms, I implement both cases. See | |
| 40 # rc4_skey.c for further details... | |
| 41 | |
| 42 # April 2005 | |
| 43 # | |
| 44 # P4 EM64T core appears to be "allergic" to 64-bit inc/dec. Replacing | |
| 45 # those with add/sub results in 50% performance improvement of folded | |
| 46 # loop... | |
| 47 | |
| 48 # May 2005 | |
| 49 # | |
| 50 # As was shown by Zou Nanhai loop unrolling can improve Intel EM64T | |
| 51 # performance by >30% [unlike P4 32-bit case that is]. But this is | |
| 52 # provided that loads are reordered even more aggressively! Both code | |
| 53 # pathes, AMD64 and EM64T, reorder loads in essentially same manner | |
| 54 # as my IA-64 implementation. On Opteron this resulted in modest 5% | |
| 55 # improvement [I had to test it], while final Intel P4 performance | |
| 56 # achieves respectful 432MBps on 2.8GHz processor now. For reference. | |
| 57 # If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than | |
| 58 # RC4_INT code-path. While if executed on Opteron, it's only 25% | |
| 59 # slower than the RC4_INT one [meaning that if CPU µ-arch detection | |
| 60 # is not implemented, then this final RC4_CHAR code-path should be | |
| 61 # preferred, as it provides better *all-round* performance]. | |
| 62 | |
| 63 # March 2007 | |
| 64 # | |
| 65 # Intel Core2 was observed to perform poorly on both code paths:-( It | |
| 66 # apparently suffers from some kind of partial register stall, which | |
| 67 # occurs in 64-bit mode only [as virtually identical 32-bit loop was | |
| 68 # observed to outperform 64-bit one by almost 50%]. Adding two movzb to | |
| 69 # cloop1 boosts its performance by 80%! This loop appears to be optimal | |
| 70 # fit for Core2 and therefore the code was modified to skip cloop8 on | |
| 71 # this CPU. | |
| 72 | |
| 73 # May 2010 | |
| 74 # | |
| 75 # Intel Westmere was observed to perform suboptimally. Adding yet | |
| 76 # another movzb to cloop1 improved performance by almost 50%! Core2 | |
| 77 # performance is improved too, but nominally... | |
| 78 | |
| 79 # May 2011 | |
| 80 # | |
| 81 # The only code path that was not modified is P4-specific one. Non-P4 | |
| 82 # Intel code path optimization is heavily based on submission by Maxim | |
| 83 # Perminov, Maxim Locktyukhin and Jim Guilford of Intel. I've used | |
| 84 # some of the ideas even in attempt to optmize the original RC4_INT | |
| 85 # code path... Current performance in cycles per processed byte (less | |
| 86 # is better) and improvement coefficients relative to previous | |
| 87 # version of this module are: | |
| 88 # | |
| 89 # Opteron 5.3/+0%(*) | |
| 90 # P4 6.5 | |
| 91 # Core2 6.2/+15%(**) | |
| 92 # Westmere 4.2/+60% | |
| 93 # Sandy Bridge 4.2/+120% | |
| 94 # Atom 9.3/+80% | |
| 95 # | |
| 96 # (*) But corresponding loop has less instructions, which should have | |
| 97 # positive effect on upcoming Bulldozer, which has one less ALU. | |
| 98 # For reference, Intel code runs at 6.8 cpb rate on Opteron. | |
| 99 # (**) Note that Core2 result is ~15% lower than corresponding result | |
| 100 # for 32-bit code, meaning that it's possible to improve it, | |
| 101 # but more than likely at the cost of the others (see rc4-586.pl | |
| 102 # to get the idea)... | |
| 103 | |
| 104 $flavour = shift; | |
| 105 $output = shift; | |
| 106 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } | |
| 107 | |
| 108 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); | |
| 109 | |
| 110 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; | |
| 111 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or | |
| 112 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or | |
| 113 die "can't locate x86_64-xlate.pl"; | |
| 114 | |
| 115 open OUT,"| \"$^X\" $xlate $flavour $output"; | |
| 116 *STDOUT=*OUT; | |
| 117 | |
| 118 $dat="%rdi"; # arg1 | |
| 119 $len="%rsi"; # arg2 | |
| 120 $inp="%rdx"; # arg3 | |
| 121 $out="%rcx"; # arg4 | |
| 122 | |
| 123 { | |
| 124 $code=<<___; | |
| 125 .text | |
| 126 .extern OPENSSL_ia32cap_P | |
| 127 | |
| 128 .globl RC4 | |
| 129 .type RC4,\@function,4 | |
| 130 .align 16 | |
| 131 RC4: or $len,$len | |
| 132 jne .Lentry | |
| 133 ret | |
| 134 .Lentry: | |
| 135 push %rbx | |
| 136 push %r12 | |
| 137 push %r13 | |
| 138 .Lprologue: | |
| 139 mov $len,%r11 | |
| 140 mov $inp,%r12 | |
| 141 mov $out,%r13 | |
| 142 ___ | |
| 143 my $len="%r11"; # reassign input arguments | |
| 144 my $inp="%r12"; | |
| 145 my $out="%r13"; | |
| 146 | |
| 147 my @XX=("%r10","%rsi"); | |
| 148 my @TX=("%rax","%rbx"); | |
| 149 my $YY="%rcx"; | |
| 150 my $TY="%rdx"; | |
| 151 | |
| 152 $code.=<<___; | |
| 153 xor $XX[0],$XX[0] | |
| 154 xor $YY,$YY | |
| 155 | |
| 156 lea 8($dat),$dat | |
| 157 mov -8($dat),$XX[0]#b | |
| 158 mov -4($dat),$YY#b | |
| 159 cmpl \$-1,256($dat) | |
| 160 je .LRC4_CHAR | |
| 161 mov OPENSSL_ia32cap_P(%rip),%r8d | |
| 162 xor $TX[1],$TX[1] | |
| 163 inc $XX[0]#b | |
| 164 sub $XX[0],$TX[1] | |
| 165 sub $inp,$out | |
| 166 movl ($dat,$XX[0],4),$TX[0]#d | |
| 167 test \$-16,$len | |
| 168 jz .Lloop1 | |
| 169 bt \$30,%r8d # Intel CPU? | |
| 170 jc .Lintel | |
| 171 and \$7,$TX[1] | |
| 172 lea 1($XX[0]),$XX[1] | |
| 173 jz .Loop8 | |
| 174 sub $TX[1],$len | |
| 175 .Loop8_warmup: | |
| 176 add $TX[0]#b,$YY#b | |
| 177 movl ($dat,$YY,4),$TY#d | |
| 178 movl $TX[0]#d,($dat,$YY,4) | |
| 179 movl $TY#d,($dat,$XX[0],4) | |
| 180 add $TY#b,$TX[0]#b | |
| 181 inc $XX[0]#b | |
| 182 movl ($dat,$TX[0],4),$TY#d | |
| 183 movl ($dat,$XX[0],4),$TX[0]#d | |
| 184 xorb ($inp),$TY#b | |
| 185 movb $TY#b,($out,$inp) | |
| 186 lea 1($inp),$inp | |
| 187 dec $TX[1] | |
| 188 jnz .Loop8_warmup | |
| 189 | |
| 190 lea 1($XX[0]),$XX[1] | |
| 191 jmp .Loop8 | |
| 192 .align 16 | |
| 193 .Loop8: | |
| 194 ___ | |
| 195 for ($i=0;$i<8;$i++) { | |
| 196 $code.=<<___ if ($i==7); | |
| 197 add \$8,$XX[1]#b | |
| 198 ___ | |
| 199 $code.=<<___; | |
| 200 add $TX[0]#b,$YY#b | |
| 201 movl ($dat,$YY,4),$TY#d | |
| 202 movl $TX[0]#d,($dat,$YY,4) | |
| 203 movl `4*($i==7?-1:$i)`($dat,$XX[1],4),$TX[1]#d | |
| 204 ror \$8,%r8 # ror is redundant when $i=0 | |
| 205 movl $TY#d,4*$i($dat,$XX[0],4) | |
| 206 add $TX[0]#b,$TY#b | |
| 207 movb ($dat,$TY,4),%r8b | |
| 208 ___ | |
| 209 push(@TX,shift(@TX)); #push(@XX,shift(@XX)); # "rotate" registers | |
| 210 } | |
| 211 $code.=<<___; | |
| 212 add \$8,$XX[0]#b | |
| 213 ror \$8,%r8 | |
| 214 sub \$8,$len | |
| 215 | |
| 216 xor ($inp),%r8 | |
| 217 mov %r8,($out,$inp) | |
| 218 lea 8($inp),$inp | |
| 219 | |
| 220 test \$-8,$len | |
| 221 jnz .Loop8 | |
| 222 cmp \$0,$len | |
| 223 jne .Lloop1 | |
| 224 jmp .Lexit | |
| 225 | |
| 226 .align 16 | |
| 227 .Lintel: | |
| 228 test \$-32,$len | |
| 229 jz .Lloop1 | |
| 230 and \$15,$TX[1] | |
| 231 jz .Loop16_is_hot | |
| 232 sub $TX[1],$len | |
| 233 .Loop16_warmup: | |
| 234 add $TX[0]#b,$YY#b | |
| 235 movl ($dat,$YY,4),$TY#d | |
| 236 movl $TX[0]#d,($dat,$YY,4) | |
| 237 movl $TY#d,($dat,$XX[0],4) | |
| 238 add $TY#b,$TX[0]#b | |
| 239 inc $XX[0]#b | |
| 240 movl ($dat,$TX[0],4),$TY#d | |
| 241 movl ($dat,$XX[0],4),$TX[0]#d | |
| 242 xorb ($inp),$TY#b | |
| 243 movb $TY#b,($out,$inp) | |
| 244 lea 1($inp),$inp | |
| 245 dec $TX[1] | |
| 246 jnz .Loop16_warmup | |
| 247 | |
| 248 mov $YY,$TX[1] | |
| 249 xor $YY,$YY | |
| 250 mov $TX[1]#b,$YY#b | |
| 251 | |
| 252 .Loop16_is_hot: | |
| 253 lea ($dat,$XX[0],4),$XX[1] | |
| 254 ___ | |
| 255 sub RC4_loop { | |
| 256 my $i=shift; | |
| 257 my $j=$i<0?0:$i; | |
| 258 my $xmm="%xmm".($j&1); | |
| 259 | |
| 260 $code.=" add \$16,$XX[0]#b\n" if ($i==15); | |
| 261 $code.=" movdqu ($inp),%xmm2\n" if ($i==15); | |
| 262 $code.=" add $TX[0]#b,$YY#b\n" if ($i<=0); | |
| 263 $code.=" movl ($dat,$YY,4),$TY#d\n"; | |
| 264 $code.=" pxor %xmm0,%xmm2\n" if ($i==0); | |
| 265 $code.=" psllq \$8,%xmm1\n" if ($i==0); | |
| 266 $code.=" pxor $xmm,$xmm\n" if ($i<=1); | |
| 267 $code.=" movl $TX[0]#d,($dat,$YY,4)\n"; | |
| 268 $code.=" add $TY#b,$TX[0]#b\n"; | |
| 269 $code.=" movl `4*($j+1)`($XX[1]),$TX[1]#d\n" if ($i<15); | |
| 270 $code.=" movz $TX[0]#b,$TX[0]#d\n"; | |
| 271 $code.=" movl $TY#d,4*$j($XX[1])\n"; | |
| 272 $code.=" pxor %xmm1,%xmm2\n" if ($i==0); | |
| 273 $code.=" lea ($dat,$XX[0],4),$XX[1]\n" if ($i==15); | |
| 274 $code.=" add $TX[1]#b,$YY#b\n" if ($i<15); | |
| 275 $code.=" pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n"; | |
| 276 $code.=" movdqu %xmm2,($out,$inp)\n" if ($i==0); | |
| 277 $code.=" lea 16($inp),$inp\n" if ($i==0); | |
| 278 $code.=" movl ($XX[1]),$TX[1]#d\n" if ($i==15); | |
| 279 } | |
| 280 RC4_loop(-1); | |
| 281 $code.=<<___; | |
| 282 jmp .Loop16_enter | |
| 283 .align 16 | |
| 284 .Loop16: | |
| 285 ___ | |
| 286 | |
| 287 for ($i=0;$i<16;$i++) { | |
| 288 $code.=".Loop16_enter:\n" if ($i==1); | |
| 289 RC4_loop($i); | |
| 290 push(@TX,shift(@TX)); # "rotate" registers | |
| 291 } | |
| 292 $code.=<<___; | |
| 293 mov $YY,$TX[1] | |
| 294 xor $YY,$YY # keyword to partial register | |
| 295 sub \$16,$len | |
| 296 mov $TX[1]#b,$YY#b | |
| 297 test \$-16,$len | |
| 298 jnz .Loop16 | |
| 299 | |
| 300 psllq \$8,%xmm1 | |
| 301 pxor %xmm0,%xmm2 | |
| 302 pxor %xmm1,%xmm2 | |
| 303 movdqu %xmm2,($out,$inp) | |
| 304 lea 16($inp),$inp | |
| 305 | |
| 306 cmp \$0,$len | |
| 307 jne .Lloop1 | |
| 308 jmp .Lexit | |
| 309 | |
| 310 .align 16 | |
| 311 .Lloop1: | |
| 312 add $TX[0]#b,$YY#b | |
| 313 movl ($dat,$YY,4),$TY#d | |
| 314 movl $TX[0]#d,($dat,$YY,4) | |
| 315 movl $TY#d,($dat,$XX[0],4) | |
| 316 add $TY#b,$TX[0]#b | |
| 317 inc $XX[0]#b | |
| 318 movl ($dat,$TX[0],4),$TY#d | |
| 319 movl ($dat,$XX[0],4),$TX[0]#d | |
| 320 xorb ($inp),$TY#b | |
| 321 movb $TY#b,($out,$inp) | |
| 322 lea 1($inp),$inp | |
| 323 dec $len | |
| 324 jnz .Lloop1 | |
| 325 jmp .Lexit | |
| 326 | |
| 327 .align 16 | |
| 328 .LRC4_CHAR: | |
| 329 add \$1,$XX[0]#b | |
| 330 movzb ($dat,$XX[0]),$TX[0]#d | |
| 331 test \$-8,$len | |
| 332 jz .Lcloop1 | |
| 333 jmp .Lcloop8 | |
| 334 .align 16 | |
| 335 .Lcloop8: | |
| 336 mov ($inp),%r8d | |
| 337 mov 4($inp),%r9d | |
| 338 ___ | |
| 339 # unroll 2x4-wise, because 64-bit rotates kill Intel P4... | |
| 340 for ($i=0;$i<4;$i++) { | |
| 341 $code.=<<___; | |
| 342 add $TX[0]#b,$YY#b | |
| 343 lea 1($XX[0]),$XX[1] | |
| 344 movzb ($dat,$YY),$TY#d | |
| 345 movzb $XX[1]#b,$XX[1]#d | |
| 346 movzb ($dat,$XX[1]),$TX[1]#d | |
| 347 movb $TX[0]#b,($dat,$YY) | |
| 348 cmp $XX[1],$YY | |
| 349 movb $TY#b,($dat,$XX[0]) | |
| 350 jne .Lcmov$i # Intel cmov is sloooow... | |
| 351 mov $TX[0],$TX[1] | |
| 352 .Lcmov$i: | |
| 353 add $TX[0]#b,$TY#b | |
| 354 xor ($dat,$TY),%r8b | |
| 355 ror \$8,%r8d | |
| 356 ___ | |
| 357 push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers | |
| 358 } | |
| 359 for ($i=4;$i<8;$i++) { | |
| 360 $code.=<<___; | |
| 361 add $TX[0]#b,$YY#b | |
| 362 lea 1($XX[0]),$XX[1] | |
| 363 movzb ($dat,$YY),$TY#d | |
| 364 movzb $XX[1]#b,$XX[1]#d | |
| 365 movzb ($dat,$XX[1]),$TX[1]#d | |
| 366 movb $TX[0]#b,($dat,$YY) | |
| 367 cmp $XX[1],$YY | |
| 368 movb $TY#b,($dat,$XX[0]) | |
| 369 jne .Lcmov$i # Intel cmov is sloooow... | |
| 370 mov $TX[0],$TX[1] | |
| 371 .Lcmov$i: | |
| 372 add $TX[0]#b,$TY#b | |
| 373 xor ($dat,$TY),%r9b | |
| 374 ror \$8,%r9d | |
| 375 ___ | |
| 376 push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers | |
| 377 } | |
| 378 $code.=<<___; | |
| 379 lea -8($len),$len | |
| 380 mov %r8d,($out) | |
| 381 lea 8($inp),$inp | |
| 382 mov %r9d,4($out) | |
| 383 lea 8($out),$out | |
| 384 | |
| 385 test \$-8,$len | |
| 386 jnz .Lcloop8 | |
| 387 cmp \$0,$len | |
| 388 jne .Lcloop1 | |
| 389 jmp .Lexit | |
| 390 ___ | |
| 391 $code.=<<___; | |
| 392 .align 16 | |
| 393 .Lcloop1: | |
| 394 add $TX[0]#b,$YY#b | |
| 395 movzb $YY#b,$YY#d | |
| 396 movzb ($dat,$YY),$TY#d | |
| 397 movb $TX[0]#b,($dat,$YY) | |
| 398 movb $TY#b,($dat,$XX[0]) | |
| 399 add $TX[0]#b,$TY#b | |
| 400 add \$1,$XX[0]#b | |
| 401 movzb $TY#b,$TY#d | |
| 402 movzb $XX[0]#b,$XX[0]#d | |
| 403 movzb ($dat,$TY),$TY#d | |
| 404 movzb ($dat,$XX[0]),$TX[0]#d | |
| 405 xorb ($inp),$TY#b | |
| 406 lea 1($inp),$inp | |
| 407 movb $TY#b,($out) | |
| 408 lea 1($out),$out | |
| 409 sub \$1,$len | |
| 410 jnz .Lcloop1 | |
| 411 jmp .Lexit | |
| 412 | |
| 413 .align 16 | |
| 414 .Lexit: | |
| 415 sub \$1,$XX[0]#b | |
| 416 movl $XX[0]#d,-8($dat) | |
| 417 movl $YY#d,-4($dat) | |
| 418 | |
| 419 mov (%rsp),%r13 | |
| 420 mov 8(%rsp),%r12 | |
| 421 mov 16(%rsp),%rbx | |
| 422 add \$24,%rsp | |
| 423 .Lepilogue: | |
| 424 ret | |
| 425 .size RC4,.-RC4 | |
| 426 ___ | |
| 427 } | |
| 428 | |
| 429 $idx="%r8"; | |
| 430 $ido="%r9"; | |
| 431 | |
| 432 $code.=<<___; | |
| 433 .globl private_RC4_set_key | |
| 434 .type private_RC4_set_key,\@function,3 | |
| 435 .align 16 | |
| 436 private_RC4_set_key: | |
| 437 lea 8($dat),$dat | |
| 438 lea ($inp,$len),$inp | |
| 439 neg $len | |
| 440 mov $len,%rcx | |
| 441 xor %eax,%eax | |
| 442 xor $ido,$ido | |
| 443 xor %r10,%r10 | |
| 444 xor %r11,%r11 | |
| 445 | |
| 446 mov OPENSSL_ia32cap_P(%rip),$idx#d | |
| 447 bt \$20,$idx#d # RC4_CHAR? | |
| 448 jc .Lc1stloop | |
| 449 jmp .Lw1stloop | |
| 450 | |
| 451 .align 16 | |
| 452 .Lw1stloop: | |
| 453 mov %eax,($dat,%rax,4) | |
| 454 add \$1,%al | |
| 455 jnc .Lw1stloop | |
| 456 | |
| 457 xor $ido,$ido | |
| 458 xor $idx,$idx | |
| 459 .align 16 | |
| 460 .Lw2ndloop: | |
| 461 mov ($dat,$ido,4),%r10d | |
| 462 add ($inp,$len,1),$idx#b | |
| 463 add %r10b,$idx#b | |
| 464 add \$1,$len | |
| 465 mov ($dat,$idx,4),%r11d | |
| 466 cmovz %rcx,$len | |
| 467 mov %r10d,($dat,$idx,4) | |
| 468 mov %r11d,($dat,$ido,4) | |
| 469 add \$1,$ido#b | |
| 470 jnc .Lw2ndloop | |
| 471 jmp .Lexit_key | |
| 472 | |
| 473 .align 16 | |
| 474 .Lc1stloop: | |
| 475 mov %al,($dat,%rax) | |
| 476 add \$1,%al | |
| 477 jnc .Lc1stloop | |
| 478 | |
| 479 xor $ido,$ido | |
| 480 xor $idx,$idx | |
| 481 .align 16 | |
| 482 .Lc2ndloop: | |
| 483 mov ($dat,$ido),%r10b | |
| 484 add ($inp,$len),$idx#b | |
| 485 add %r10b,$idx#b | |
| 486 add \$1,$len | |
| 487 mov ($dat,$idx),%r11b | |
| 488 jnz .Lcnowrap | |
| 489 mov %rcx,$len | |
| 490 .Lcnowrap: | |
| 491 mov %r10b,($dat,$idx) | |
| 492 mov %r11b,($dat,$ido) | |
| 493 add \$1,$ido#b | |
| 494 jnc .Lc2ndloop | |
| 495 movl \$-1,256($dat) | |
| 496 | |
| 497 .align 16 | |
| 498 .Lexit_key: | |
| 499 xor %eax,%eax | |
| 500 mov %eax,-8($dat) | |
| 501 mov %eax,-4($dat) | |
| 502 ret | |
| 503 .size private_RC4_set_key,.-private_RC4_set_key | |
| 504 | |
| 505 .globl RC4_options | |
| 506 .type RC4_options,\@abi-omnipotent | |
| 507 .align 16 | |
| 508 RC4_options: | |
| 509 lea .Lopts(%rip),%rax | |
| 510 mov OPENSSL_ia32cap_P(%rip),%edx | |
| 511 bt \$20,%edx | |
| 512 jc .L8xchar | |
| 513 bt \$30,%edx | |
| 514 jnc .Ldone | |
| 515 add \$25,%rax | |
| 516 ret | |
| 517 .L8xchar: | |
| 518 add \$12,%rax | |
| 519 .Ldone: | |
| 520 ret | |
| 521 .align 64 | |
| 522 .Lopts: | |
| 523 .asciz "rc4(8x,int)" | |
| 524 .asciz "rc4(8x,char)" | |
| 525 .asciz "rc4(16x,int)" | |
| 526 .asciz "RC4 for x86_64, CRYPTOGAMS by <appro\@openssl.org>" | |
| 527 .align 64 | |
| 528 .size RC4_options,.-RC4_options | |
| 529 ___ | |
| 530 | |
| 531 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, | |
| 532 # CONTEXT *context,DISPATCHER_CONTEXT *disp) | |
| 533 if ($win64) { | |
| 534 $rec="%rcx"; | |
| 535 $frame="%rdx"; | |
| 536 $context="%r8"; | |
| 537 $disp="%r9"; | |
| 538 | |
| 539 $code.=<<___; | |
| 540 .extern __imp_RtlVirtualUnwind | |
| 541 .type stream_se_handler,\@abi-omnipotent | |
| 542 .align 16 | |
| 543 stream_se_handler: | |
| 544 push %rsi | |
| 545 push %rdi | |
| 546 push %rbx | |
| 547 push %rbp | |
| 548 push %r12 | |
| 549 push %r13 | |
| 550 push %r14 | |
| 551 push %r15 | |
| 552 pushfq | |
| 553 sub \$64,%rsp | |
| 554 | |
| 555 mov 120($context),%rax # pull context->Rax | |
| 556 mov 248($context),%rbx # pull context->Rip | |
| 557 | |
| 558 lea .Lprologue(%rip),%r10 | |
| 559 cmp %r10,%rbx # context->Rip<prologue label | |
| 560 jb .Lin_prologue | |
| 561 | |
| 562 mov 152($context),%rax # pull context->Rsp | |
| 563 | |
| 564 lea .Lepilogue(%rip),%r10 | |
| 565 cmp %r10,%rbx # context->Rip>=epilogue label | |
| 566 jae .Lin_prologue | |
| 567 | |
| 568 lea 24(%rax),%rax | |
| 569 | |
| 570 mov -8(%rax),%rbx | |
| 571 mov -16(%rax),%r12 | |
| 572 mov -24(%rax),%r13 | |
| 573 mov %rbx,144($context) # restore context->Rbx | |
| 574 mov %r12,216($context) # restore context->R12 | |
| 575 mov %r13,224($context) # restore context->R13 | |
| 576 | |
| 577 .Lin_prologue: | |
| 578 mov 8(%rax),%rdi | |
| 579 mov 16(%rax),%rsi | |
| 580 mov %rax,152($context) # restore context->Rsp | |
| 581 mov %rsi,168($context) # restore context->Rsi | |
| 582 mov %rdi,176($context) # restore context->Rdi | |
| 583 | |
| 584 jmp .Lcommon_seh_exit | |
| 585 .size stream_se_handler,.-stream_se_handler | |
| 586 | |
| 587 .type key_se_handler,\@abi-omnipotent | |
| 588 .align 16 | |
| 589 key_se_handler: | |
| 590 push %rsi | |
| 591 push %rdi | |
| 592 push %rbx | |
| 593 push %rbp | |
| 594 push %r12 | |
| 595 push %r13 | |
| 596 push %r14 | |
| 597 push %r15 | |
| 598 pushfq | |
| 599 sub \$64,%rsp | |
| 600 | |
| 601 mov 152($context),%rax # pull context->Rsp | |
| 602 mov 8(%rax),%rdi | |
| 603 mov 16(%rax),%rsi | |
| 604 mov %rsi,168($context) # restore context->Rsi | |
| 605 mov %rdi,176($context) # restore context->Rdi | |
| 606 | |
| 607 .Lcommon_seh_exit: | |
| 608 | |
| 609 mov 40($disp),%rdi # disp->ContextRecord | |
| 610 mov $context,%rsi # context | |
| 611 mov \$154,%ecx # sizeof(CONTEXT) | |
| 612 .long 0xa548f3fc # cld; rep movsq | |
| 613 | |
| 614 mov $disp,%rsi | |
| 615 xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER | |
| 616 mov 8(%rsi),%rdx # arg2, disp->ImageBase | |
| 617 mov 0(%rsi),%r8 # arg3, disp->ControlPc | |
| 618 mov 16(%rsi),%r9 # arg4, disp->FunctionEntry | |
| 619 mov 40(%rsi),%r10 # disp->ContextRecord | |
| 620 lea 56(%rsi),%r11 # &disp->HandlerData | |
| 621 lea 24(%rsi),%r12 # &disp->EstablisherFrame | |
| 622 mov %r10,32(%rsp) # arg5 | |
| 623 mov %r11,40(%rsp) # arg6 | |
| 624 mov %r12,48(%rsp) # arg7 | |
| 625 mov %rcx,56(%rsp) # arg8, (NULL) | |
| 626 call *__imp_RtlVirtualUnwind(%rip) | |
| 627 | |
| 628 mov \$1,%eax # ExceptionContinueSearch | |
| 629 add \$64,%rsp | |
| 630 popfq | |
| 631 pop %r15 | |
| 632 pop %r14 | |
| 633 pop %r13 | |
| 634 pop %r12 | |
| 635 pop %rbp | |
| 636 pop %rbx | |
| 637 pop %rdi | |
| 638 pop %rsi | |
| 639 ret | |
| 640 .size key_se_handler,.-key_se_handler | |
| 641 | |
| 642 .section .pdata | |
| 643 .align 4 | |
| 644 .rva .LSEH_begin_RC4 | |
| 645 .rva .LSEH_end_RC4 | |
| 646 .rva .LSEH_info_RC4 | |
| 647 | |
| 648 .rva .LSEH_begin_private_RC4_set_key | |
| 649 .rva .LSEH_end_private_RC4_set_key | |
| 650 .rva .LSEH_info_private_RC4_set_key | |
| 651 | |
| 652 .section .xdata | |
| 653 .align 8 | |
| 654 .LSEH_info_RC4: | |
| 655 .byte 9,0,0,0 | |
| 656 .rva stream_se_handler | |
| 657 .LSEH_info_private_RC4_set_key: | |
| 658 .byte 9,0,0,0 | |
| 659 .rva key_se_handler | |
| 660 ___ | |
| 661 } | |
| 662 | |
| 663 sub reg_part { | |
| 664 my ($reg,$conv)=@_; | |
| 665 if ($reg =~ /%r[0-9]+/) { $reg .= $conv; } | |
| 666 elsif ($conv eq "b") { $reg =~ s/%[er]([^x]+)x?/%$1l/; } | |
| 667 elsif ($conv eq "w") { $reg =~ s/%[er](.+)/%$1/; } | |
| 668 elsif ($conv eq "d") { $reg =~ s/%[er](.+)/%e$1/; } | |
| 669 return $reg; | |
| 670 } | |
| 671 | |
| 672 $code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem; | |
| 673 $code =~ s/\`([^\`]*)\`/eval $1/gem; | |
| 674 | |
| 675 print $code; | |
| 676 | |
| 677 close STDOUT; | |
| OLD | NEW |