55553f719b521a0bb4deab6efc944cd30c1a56aada#!/usr/bin/env perl
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# ====================================================================
55553f719b521a0bb4deab6efc944cd30c1a56aada# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
55553f719b521a0bb4deab6efc944cd30c1a56aada# project. The module is, however, dual licensed under OpenSSL and
55553f719b521a0bb4deab6efc944cd30c1a56aada# CRYPTOGAMS licenses depending on where you obtain it. For further
55553f719b521a0bb4deab6efc944cd30c1a56aada# details see http://www.openssl.org/~appro/cryptogams/.
55553f719b521a0bb4deab6efc944cd30c1a56aada# ====================================================================
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# 2.22x RC4 tune-up:-) It should be noted though that my hand [as in
55553f719b521a0bb4deab6efc944cd30c1a56aada# "hand-coded assembler"] doesn't stand for the whole improvement
55553f719b521a0bb4deab6efc944cd30c1a56aada# coefficient. It turned out that eliminating RC4_CHAR from config
55553f719b521a0bb4deab6efc944cd30c1a56aada# line results in ~40% improvement (yes, even for C implementation).
55553f719b521a0bb4deab6efc944cd30c1a56aada# Presumably it has everything to do with AMD cache architecture and
55553f719b521a0bb4deab6efc944cd30c1a56aada# RAW or whatever penalties. Once again! The module *requires* config
55553f719b521a0bb4deab6efc944cd30c1a56aada# line *without* RC4_CHAR! As for coding "secret," I bet on partial
55553f719b521a0bb4deab6efc944cd30c1a56aada# register arithmetics. For example instead of 'inc %r8; and $255,%r8'
55553f719b521a0bb4deab6efc944cd30c1a56aada# I simply 'inc %r8b'. Even though optimization manual discourages
55553f719b521a0bb4deab6efc944cd30c1a56aada# to operate on partial registers, it turned out to be the best bet.
55553f719b521a0bb4deab6efc944cd30c1a56aada# At least for AMD... How IA32E would perform remains to be seen...
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# As was shown by Marc Bevand reordering of couple of load operations
55553f719b521a0bb4deab6efc944cd30c1a56aada# results in even higher performance gain of 3.3x:-) At least on
55553f719b521a0bb4deab6efc944cd30c1a56aada# Opteron... For reference, 1x in this case is RC4_CHAR C-code
55553f719b521a0bb4deab6efc944cd30c1a56aada# compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock.
55553f719b521a0bb4deab6efc944cd30c1a56aada# Latter means that if you want to *estimate* what to expect from
55553f719b521a0bb4deab6efc944cd30c1a56aada# *your* Opteron, then multiply 54 by 3.3 and clock frequency in GHz.
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# Intel P4 EM64T core was found to run the AMD64 code really slow...
55553f719b521a0bb4deab6efc944cd30c1a56aada# The only way to achieve comparable performance on P4 was to keep
55553f719b521a0bb4deab6efc944cd30c1a56aada# RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to
55553f719b521a0bb4deab6efc944cd30c1a56aada# compose blended code, which would perform even within 30% marginal
55553f719b521a0bb4deab6efc944cd30c1a56aada# on either AMD and Intel platforms, I implement both cases. See
55553f719b521a0bb4deab6efc944cd30c1a56aada# rc4_skey.c for further details...
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# P4 EM64T core appears to be "allergic" to 64-bit inc/dec. Replacing
55553f719b521a0bb4deab6efc944cd30c1a56aada# those with add/sub results in 50% performance improvement of folded
55553f719b521a0bb4deab6efc944cd30c1a56aada# loop...
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# As was shown by Zou Nanhai loop unrolling can improve Intel EM64T
55553f719b521a0bb4deab6efc944cd30c1a56aada# performance by >30% [unlike P4 32-bit case that is]. But this is
55553f719b521a0bb4deab6efc944cd30c1a56aada# provided that loads are reordered even more aggressively! Both code
55553f719b521a0bb4deab6efc944cd30c1a56aada# pathes, AMD64 and EM64T, reorder loads in essentially same manner
55553f719b521a0bb4deab6efc944cd30c1a56aada# as my IA-64 implementation. On Opteron this resulted in modest 5%
55553f719b521a0bb4deab6efc944cd30c1a56aada# improvement [I had to test it], while final Intel P4 performance
55553f719b521a0bb4deab6efc944cd30c1a56aada# achieves respectful 432MBps on 2.8GHz processor now. For reference.
55553f719b521a0bb4deab6efc944cd30c1a56aada# If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than
55553f719b521a0bb4deab6efc944cd30c1a56aada# RC4_INT code-path. While if executed on Opteron, it's only 25%
55553f719b521a0bb4deab6efc944cd30c1a56aada# slower than the RC4_INT one [meaning that if CPU �-arch detection
55553f719b521a0bb4deab6efc944cd30c1a56aada# is not implemented, then this final RC4_CHAR code-path should be
55553f719b521a0bb4deab6efc944cd30c1a56aada# preferred, as it provides better *all-round* performance].
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# Intel Core2 was observed to perform poorly on both code paths:-( It
55553f719b521a0bb4deab6efc944cd30c1a56aada# apparently suffers from some kind of partial register stall, which
55553f719b521a0bb4deab6efc944cd30c1a56aada# occurs in 64-bit mode only [as virtually identical 32-bit loop was
55553f719b521a0bb4deab6efc944cd30c1a56aada# observed to outperform 64-bit one by almost 50%]. Adding two movzb to
55553f719b521a0bb4deab6efc944cd30c1a56aada# cloop1 boosts its performance by 80%! This loop appears to be optimal
55553f719b521a0bb4deab6efc944cd30c1a56aada# fit for Core2 and therefore the code was modified to skip cloop8 on
55553f719b521a0bb4deab6efc944cd30c1a56aada# this CPU.
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# OpenSolaris OS modifications
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# Sun elects to use this software under the BSD license.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# This source originates from OpenSSL file rc4-x86_64.pl at
55553f719b521a0bb4deab6efc944cd30c1a56aada# ftp://ftp.openssl.org/snapshot/openssl-0.9.8-stable-SNAP-20080131.tar.gz
55553f719b521a0bb4deab6efc944cd30c1a56aada# (presumably for future OpenSSL release 0.9.8h), with these changes:
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# 1. Added some comments, "use strict", and declared all variables.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# 2. Added OpenSolaris ENTRY_NP/SET_SIZE macros from
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# /usr/include/sys/asm_linkage.h.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# 3. Changed function name from RC4() to arcfour_crypt_asm() and RC4_set_key()
55553f719b521a0bb4deab6efc944cd30c1a56aada# to arcfour_key_init(), and changed the parameter order for both to that
55553f719b521a0bb4deab6efc944cd30c1a56aada# used by OpenSolaris.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# 4. The current method of using cpuid feature bits 20 (NX) or 28 (HTT) from
55553f719b521a0bb4deab6efc944cd30c1a56aada# function OPENSSL_ia32_cpuid() to distinguish Intel/AMD does not work for
55553f719b521a0bb4deab6efc944cd30c1a56aada# some newer AMD64 processors, as these bits are set on both Intel EM64T
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# processors and newer AMD64 processors. I replaced this with C code
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# (function arcfour_crypt_on_intel()) to call cpuid_getvendor()
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# when executing in the kernel and getisax() when executing in userland.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# 5. Set a new field in the key structure, key->flag to 0 for AMD AMD64
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# and 1 for Intel EM64T. This is to select the most-efficient arcfour_crypt()
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# function to use.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# 6. Removed x86_64-xlate.pl script (not needed for as(1) or gas(1) assemblers).
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson#
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# 7. Removed unused RC4_CHAR, Lcloop1, and Lcloop8 code.
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson#
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# 8. Added C function definitions for use by lint(1B).
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aadause strict;
55553f719b521a0bb4deab6efc944cd30c1a56aadamy ($code, $dat, $inp, $out, $len, $idx, $ido, $i, @XX, @TX, $YY, $TY);
55553f719b521a0bb4deab6efc944cd30c1a56aadamy $output = shift;
55553f719b521a0bb4deab6efc944cd30c1a56aadaopen STDOUT,">$output";
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# Parameters
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# OpenSSL:
55553f719b521a0bb4deab6efc944cd30c1a56aada# void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
55553f719b521a0bb4deab6efc944cd30c1a56aada# unsigned char *outdata);
55553f719b521a0bb4deab6efc944cd30c1a56aada#$dat="%rdi"; # arg1
55553f719b521a0bb4deab6efc944cd30c1a56aada#$len="%rsi"; # arg2
55553f719b521a0bb4deab6efc944cd30c1a56aada#$inp="%rdx"; # arg3
55553f719b521a0bb4deab6efc944cd30c1a56aada#$out="%rcx"; # arg4
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# OpenSolaris:
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# void arcfour_crypt_asm(ARCFour_key *key, uchar_t *in, uchar_t *out,
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson# size_t len);
55553f719b521a0bb4deab6efc944cd30c1a56aada$dat="%rdi"; # arg1
55553f719b521a0bb4deab6efc944cd30c1a56aada$inp="%rsi"; # arg2
55553f719b521a0bb4deab6efc944cd30c1a56aada$out="%rdx"; # arg3
55553f719b521a0bb4deab6efc944cd30c1a56aada$len="%rcx"; # arg4
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# Register variables
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# $XX[0] is key->i (aka key->x), $XX[1] is a temporary.
55553f719b521a0bb4deab6efc944cd30c1a56aada# $TX[0] and $TX[1] are temporaries.
55553f719b521a0bb4deab6efc944cd30c1a56aada# $YY is key->j (aka key->y).
55553f719b521a0bb4deab6efc944cd30c1a56aada# $TY is a temporary.
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada@XX=("%r8","%r10");
55553f719b521a0bb4deab6efc944cd30c1a56aada@TX=("%r9","%r11");
55553f719b521a0bb4deab6efc944cd30c1a56aada$YY="%r12";
55553f719b521a0bb4deab6efc944cd30c1a56aada$TY="%r13";
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada$code=<<___;
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson#if defined(lint) || defined(__lint)
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson#include "arcfour.h"
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson/* ARGSUSED */
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Andersonvoid
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Andersonarcfour_crypt_asm(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len)
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson{}
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson/* ARGSUSED */
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Andersonvoid
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Andersonarcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson{}
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson#else
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson#include <sys/asm_linkage.h>
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris AndersonENTRY_NP(arcfour_crypt_asm)
55553f719b521a0bb4deab6efc944cd30c1a56aada or $len,$len # If (len == 0) return
55553f719b521a0bb4deab6efc944cd30c1a56aada jne .Lentry
55553f719b521a0bb4deab6efc944cd30c1a56aada ret
55553f719b521a0bb4deab6efc944cd30c1a56aada.Lentry:
55553f719b521a0bb4deab6efc944cd30c1a56aada push %r12
55553f719b521a0bb4deab6efc944cd30c1a56aada push %r13
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada / Set $dat to beginning of array, key->arr[0]
55553f719b521a0bb4deab6efc944cd30c1a56aada add \$8,$dat
55553f719b521a0bb4deab6efc944cd30c1a56aada / Get key->j
55553f719b521a0bb4deab6efc944cd30c1a56aada movl -8($dat),$XX[0]#d
55553f719b521a0bb4deab6efc944cd30c1a56aada / Get key->i
55553f719b521a0bb4deab6efc944cd30c1a56aada movl -4($dat),$YY#d
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada /
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson / Use a 4-byte key schedule element array
55553f719b521a0bb4deab6efc944cd30c1a56aada /
55553f719b521a0bb4deab6efc944cd30c1a56aada inc $XX[0]#b
55553f719b521a0bb4deab6efc944cd30c1a56aada movl ($dat,$XX[0],4),$TX[0]#d
55553f719b521a0bb4deab6efc944cd30c1a56aada test \$-8,$len
55553f719b521a0bb4deab6efc944cd30c1a56aada jz .Lloop1
55553f719b521a0bb4deab6efc944cd30c1a56aada jmp .Lloop8
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada.align 16
55553f719b521a0bb4deab6efc944cd30c1a56aada.Lloop8:
55553f719b521a0bb4deab6efc944cd30c1a56aada___
55553f719b521a0bb4deab6efc944cd30c1a56aadafor ($i=0;$i<8;$i++) {
55553f719b521a0bb4deab6efc944cd30c1a56aada$code.=<<___;
55553f719b521a0bb4deab6efc944cd30c1a56aada add $TX[0]#b,$YY#b
55553f719b521a0bb4deab6efc944cd30c1a56aada mov $XX[0],$XX[1]
55553f719b521a0bb4deab6efc944cd30c1a56aada movl ($dat,$YY,4),$TY#d
55553f719b521a0bb4deab6efc944cd30c1a56aada ror \$8,%rax # ror is redundant when $i=0
55553f719b521a0bb4deab6efc944cd30c1a56aada inc $XX[1]#b
55553f719b521a0bb4deab6efc944cd30c1a56aada movl ($dat,$XX[1],4),$TX[1]#d
55553f719b521a0bb4deab6efc944cd30c1a56aada cmp $XX[1],$YY
55553f719b521a0bb4deab6efc944cd30c1a56aada movl $TX[0]#d,($dat,$YY,4)
55553f719b521a0bb4deab6efc944cd30c1a56aada cmove $TX[0],$TX[1]
55553f719b521a0bb4deab6efc944cd30c1a56aada movl $TY#d,($dat,$XX[0],4)
55553f719b521a0bb4deab6efc944cd30c1a56aada add $TX[0]#b,$TY#b
55553f719b521a0bb4deab6efc944cd30c1a56aada movb ($dat,$TY,4),%al
55553f719b521a0bb4deab6efc944cd30c1a56aada___
55553f719b521a0bb4deab6efc944cd30c1a56aadapush(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers
55553f719b521a0bb4deab6efc944cd30c1a56aada}
55553f719b521a0bb4deab6efc944cd30c1a56aada$code.=<<___;
55553f719b521a0bb4deab6efc944cd30c1a56aada ror \$8,%rax
55553f719b521a0bb4deab6efc944cd30c1a56aada sub \$8,$len
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada xor ($inp),%rax
55553f719b521a0bb4deab6efc944cd30c1a56aada add \$8,$inp
55553f719b521a0bb4deab6efc944cd30c1a56aada mov %rax,($out)
55553f719b521a0bb4deab6efc944cd30c1a56aada add \$8,$out
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada test \$-8,$len
55553f719b521a0bb4deab6efc944cd30c1a56aada jnz .Lloop8
55553f719b521a0bb4deab6efc944cd30c1a56aada cmp \$0,$len
55553f719b521a0bb4deab6efc944cd30c1a56aada jne .Lloop1
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson
55553f719b521a0bb4deab6efc944cd30c1a56aada.Lexit:
55553f719b521a0bb4deab6efc944cd30c1a56aada /
55553f719b521a0bb4deab6efc944cd30c1a56aada / Cleanup and exit code
55553f719b521a0bb4deab6efc944cd30c1a56aada /
55553f719b521a0bb4deab6efc944cd30c1a56aada / --i to undo ++i done at entry
55553f719b521a0bb4deab6efc944cd30c1a56aada sub \$1,$XX[0]#b
55553f719b521a0bb4deab6efc944cd30c1a56aada / set key->i
55553f719b521a0bb4deab6efc944cd30c1a56aada movl $XX[0]#d,-8($dat)
55553f719b521a0bb4deab6efc944cd30c1a56aada / set key->j
55553f719b521a0bb4deab6efc944cd30c1a56aada movl $YY#d,-4($dat)
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada pop %r13
55553f719b521a0bb4deab6efc944cd30c1a56aada pop %r12
55553f719b521a0bb4deab6efc944cd30c1a56aada ret
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson
55553f719b521a0bb4deab6efc944cd30c1a56aada.align 16
55553f719b521a0bb4deab6efc944cd30c1a56aada.Lloop1:
55553f719b521a0bb4deab6efc944cd30c1a56aada add $TX[0]#b,$YY#b
55553f719b521a0bb4deab6efc944cd30c1a56aada movl ($dat,$YY,4),$TY#d
55553f719b521a0bb4deab6efc944cd30c1a56aada movl $TX[0]#d,($dat,$YY,4)
55553f719b521a0bb4deab6efc944cd30c1a56aada movl $TY#d,($dat,$XX[0],4)
55553f719b521a0bb4deab6efc944cd30c1a56aada add $TY#b,$TX[0]#b
55553f719b521a0bb4deab6efc944cd30c1a56aada inc $XX[0]#b
55553f719b521a0bb4deab6efc944cd30c1a56aada movl ($dat,$TX[0],4),$TY#d
55553f719b521a0bb4deab6efc944cd30c1a56aada movl ($dat,$XX[0],4),$TX[0]#d
55553f719b521a0bb4deab6efc944cd30c1a56aada xorb ($inp),$TY#b
55553f719b521a0bb4deab6efc944cd30c1a56aada inc $inp
55553f719b521a0bb4deab6efc944cd30c1a56aada movb $TY#b,($out)
55553f719b521a0bb4deab6efc944cd30c1a56aada inc $out
55553f719b521a0bb4deab6efc944cd30c1a56aada dec $len
55553f719b521a0bb4deab6efc944cd30c1a56aada jnz .Lloop1
55553f719b521a0bb4deab6efc944cd30c1a56aada jmp .Lexit
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada ret
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris AndersonSET_SIZE(arcfour_crypt_asm)
55553f719b521a0bb4deab6efc944cd30c1a56aada___
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada# Parameters
55553f719b521a0bb4deab6efc944cd30c1a56aada#
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# OpenSSL:
55553f719b521a0bb4deab6efc944cd30c1a56aada# void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
55553f719b521a0bb4deab6efc944cd30c1a56aada#$dat="%rdi"; # arg1
55553f719b521a0bb4deab6efc944cd30c1a56aada#$len="%rsi"; # arg2
55553f719b521a0bb4deab6efc944cd30c1a56aada#$inp="%rdx"; # arg3
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# OpenSolaris:
55553f719b521a0bb4deab6efc944cd30c1a56aada# void arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen);
55553f719b521a0bb4deab6efc944cd30c1a56aada$dat="%rdi"; # arg1
55553f719b521a0bb4deab6efc944cd30c1a56aada$inp="%rsi"; # arg2
55553f719b521a0bb4deab6efc944cd30c1a56aada$len="%rdx"; # arg3
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada# Temporaries
55553f719b521a0bb4deab6efc944cd30c1a56aada$idx="%r8";
55553f719b521a0bb4deab6efc944cd30c1a56aada$ido="%r9";
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada$code.=<<___;
55553f719b521a0bb4deab6efc944cd30c1a56aada / int arcfour_crypt_on_intel(void);
55553f719b521a0bb4deab6efc944cd30c1a56aada.extern arcfour_crypt_on_intel
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aadaENTRY_NP(arcfour_key_init)
55553f719b521a0bb4deab6efc944cd30c1a56aada / Find out if we're running on Intel or something else (e.g., AMD64).
55553f719b521a0bb4deab6efc944cd30c1a56aada / This sets %eax to 1 for Intel, otherwise 0.
55553f719b521a0bb4deab6efc944cd30c1a56aada push %rdi / Save arg1
55553f719b521a0bb4deab6efc944cd30c1a56aada push %rsi / Save arg2
55553f719b521a0bb4deab6efc944cd30c1a56aada push %rdx / Save arg3
55553f719b521a0bb4deab6efc944cd30c1a56aada call arcfour_crypt_on_intel
55553f719b521a0bb4deab6efc944cd30c1a56aada pop %rdx / Restore arg3
55553f719b521a0bb4deab6efc944cd30c1a56aada pop %rsi / Restore arg2
55553f719b521a0bb4deab6efc944cd30c1a56aada pop %rdi / Restore arg1
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson / Save return value in key->flag (1=Intel, 0=AMD)
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson movl %eax,1032($dat)
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada / Set $dat to beginning of array, key->arr[0]
55553f719b521a0bb4deab6efc944cd30c1a56aada lea 8($dat),$dat
55553f719b521a0bb4deab6efc944cd30c1a56aada lea ($inp,$len),$inp
55553f719b521a0bb4deab6efc944cd30c1a56aada neg $len
55553f719b521a0bb4deab6efc944cd30c1a56aada mov $len,%rcx
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson xor %eax,%eax
55553f719b521a0bb4deab6efc944cd30c1a56aada xor $ido,$ido
55553f719b521a0bb4deab6efc944cd30c1a56aada xor %r10,%r10
55553f719b521a0bb4deab6efc944cd30c1a56aada xor %r11,%r11
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson / Use a 4-byte data array
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson jmp .Lw1stloop
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada.align 16
55553f719b521a0bb4deab6efc944cd30c1a56aada.Lw1stloop:
55553f719b521a0bb4deab6efc944cd30c1a56aada / AMD64 (4-byte array)
55553f719b521a0bb4deab6efc944cd30c1a56aada mov %eax,($dat,%rax,4)
55553f719b521a0bb4deab6efc944cd30c1a56aada add \$1,%al
55553f719b521a0bb4deab6efc944cd30c1a56aada jnc .Lw1stloop
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada xor $ido,$ido
55553f719b521a0bb4deab6efc944cd30c1a56aada xor $idx,$idx
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson
55553f719b521a0bb4deab6efc944cd30c1a56aada.align 16
55553f719b521a0bb4deab6efc944cd30c1a56aada.Lw2ndloop:
55553f719b521a0bb4deab6efc944cd30c1a56aada mov ($dat,$ido,4),%r10d
55553f719b521a0bb4deab6efc944cd30c1a56aada add ($inp,$len,1),$idx#b
55553f719b521a0bb4deab6efc944cd30c1a56aada add %r10b,$idx#b
55553f719b521a0bb4deab6efc944cd30c1a56aada add \$1,$len
55553f719b521a0bb4deab6efc944cd30c1a56aada mov ($dat,$idx,4),%r11d
55553f719b521a0bb4deab6efc944cd30c1a56aada cmovz %rcx,$len
55553f719b521a0bb4deab6efc944cd30c1a56aada mov %r10d,($dat,$idx,4)
55553f719b521a0bb4deab6efc944cd30c1a56aada mov %r11d,($dat,$ido,4)
55553f719b521a0bb4deab6efc944cd30c1a56aada add \$1,$ido#b
55553f719b521a0bb4deab6efc944cd30c1a56aada jnc .Lw2ndloop
55553f719b521a0bb4deab6efc944cd30c1a56aada
92a8e44d7a50507b89a65e1e3226edb5b90fd363Dan OpenSolaris Anderson / Exit code
55553f719b521a0bb4deab6efc944cd30c1a56aada xor %eax,%eax
55553f719b521a0bb4deab6efc944cd30c1a56aada mov %eax,-8($dat)
55553f719b521a0bb4deab6efc944cd30c1a56aada mov %eax,-4($dat)
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada ret
55553f719b521a0bb4deab6efc944cd30c1a56aadaSET_SIZE(arcfour_key_init)
55553f719b521a0bb4deab6efc944cd30c1a56aada.asciz "RC4 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
55553f719b521a0bb4deab6efc944cd30c1a56aada#endif /* !lint && !__lint */
55553f719b521a0bb4deab6efc944cd30c1a56aada___
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aada$code =~ s/#([bwd])/$1/gm;
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aadaprint $code;
55553f719b521a0bb4deab6efc944cd30c1a56aada
55553f719b521a0bb4deab6efc944cd30c1a56aadaclose STDOUT;