Update perl asm scripts include paths for perlasm.
[openssl.git] / crypto / bf / bf_locl.h
index 7936e6c56a232db66e9af10ea263453c4d3b6f1d..cc7c3ec9922161636846abfe5ed20aecc16844af 100644 (file)
@@ -56,8 +56,8 @@
  * [including the GNU Public Licence.]
  */
 
-#ifndef _HEADER_BF_LOCL_H
-#define _HEADER_BF_LOCL_H
+#ifndef HEADER_BF_LOCL_H
+#define HEADER_BF_LOCL_H
 #include <openssl/opensslconf.h> /* BF_PTR, BF_PTR2 */
 
 #undef c2l
                          *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
                          *((c)++)=(unsigned char)(((l)     )&0xff))
 
-/* This is actually a big endian algorithm, the most significate byte
+/* This is actually a big endian algorithm, the most significant byte
  * is used to lookup array 0 */
 
-#define BF_M   0x3fc
-#define BF_0   22L
-#define BF_1   14L
-#define BF_2    6L
-#define BF_3    2L /* left shift */
-
 #if defined(BF_PTR2)
 
-/* This is basically a special pentium verson */
-#define BF_ENC(LL,R,S,P) \
-       { \
-       BF_LONG t,u,v; \
-       u=R>>BF_0; \
-       v=R>>BF_1; \
-       u&=BF_M; \
-       v&=BF_M; \
-       t=  *(BF_LONG *)((unsigned char *)&(S[  0])+u); \
-       u=R>>BF_2; \
-       t+= *(BF_LONG *)((unsigned char *)&(S[256])+v); \
-       v=R<<BF_3; \
-       u&=BF_M; \
-       v&=BF_M; \
-       t^= *(BF_LONG *)((unsigned char *)&(S[512])+u); \
-       LL^=P; \
-       t+= *(BF_LONG *)((unsigned char *)&(S[768])+v); \
-       LL^=t; \
-       }
+/*
+ * This is basically a special Intel version. Point is that Intel
+ * doesn't have many registers, but offers a reach choice of addressing
+ * modes. So we spare some registers by directly traversing BF_KEY
+ * structure and hiring the most decorated addressing mode. The code
+ * generated by EGCS is *perfectly* competitive with assembler
+ * implementation!
+ */
+#define BF_ENC(LL,R,KEY,Pi) (\
+       LL^=KEY[Pi], \
+       t=  KEY[BF_ROUNDS+2 +   0 + ((R>>24)&0xFF)], \
+       t+= KEY[BF_ROUNDS+2 + 256 + ((R>>16)&0xFF)], \
+       t^= KEY[BF_ROUNDS+2 + 512 + ((R>>8 )&0xFF)], \
+       t+= KEY[BF_ROUNDS+2 + 768 + ((R    )&0xFF)], \
+       LL^=t \
+       )
 
 #elif defined(BF_PTR)
 
-/* This is normally very good */
+#ifndef BF_LONG_LOG2
+#define BF_LONG_LOG2  2       /* default to BF_LONG being 32 bits */
+#endif
+#define BF_M  (0xFF<<BF_LONG_LOG2)
+#define BF_0  (24-BF_LONG_LOG2)
+#define BF_1  (16-BF_LONG_LOG2)
+#define BF_2  ( 8-BF_LONG_LOG2)
+#define BF_3  BF_LONG_LOG2 /* left shift */
+
+/*
+ * This is normally very good on RISC platforms where normally you
+ * have to explicitly "multiply" array index by sizeof(BF_LONG)
+ * in order to calculate the effective address. This implementation
+ * excuses CPU from this extra work. Power[PC] uses should have most
+ * fun as (R>>BF_i)&BF_M gets folded into a single instruction, namely
+ * rlwinm. So let'em double-check if their compiler does it.
+ */
 
-#define BF_ENC(LL,R,S,P) \
-       LL^=P; \
+#define BF_ENC(LL,R,S,P) \
+       LL^=P, \
        LL^= (((*(BF_LONG *)((unsigned char *)&(S[  0])+((R>>BF_0)&BF_M))+ \
                *(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \
                *(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \
-               *(BF_LONG *)((unsigned char *)&(S[768])+((R<<BF_3)&BF_M)));
+               *(BF_LONG *)((unsigned char *)&(S[768])+((R<<BF_3)&BF_M))) \
+       )
 #else
 
-/* This will always work, even on 64 bit machines and strangly enough,
- * on the Alpha it is faster than the pointer versions (both 32 and 64
- * versions of BF_LONG) */
+/*
+ * This is a *generic* version. Seem to perform best on platforms that
+ * offer explicit support for extraction of 8-bit nibbles preferably
+ * complemented with "multiplying" of array index by sizeof(BF_LONG).
+ * For the moment of this writing the list comprises Alpha CPU featuring
+ * extbl and s[48]addq instructions.
+ */
 
-#define BF_ENC(LL,R,S,P) \
-       LL^=P; \
-       LL^=((( S[        (int)(R>>24L)      ] + \
-               S[0x0100+((int)(R>>16L)&0xff)])^ \
-               S[0x0200+((int)(R>> 8L)&0xff)])+ \
-               S[0x0300+((int)(R     )&0xff)])&0xffffffffL;
+#define BF_ENC(LL,R,S,P) ( \
+       LL^=P, \
+       LL^=((( S[       ((int)(R>>24)&0xff)] + \
+               S[0x0100+((int)(R>>16)&0xff)])^ \
+               S[0x0200+((int)(R>> 8)&0xff)])+ \
+               S[0x0300+((int)(R    )&0xff)])&0xffffffffL \
+       )
 #endif
 
 #endif