base/asm-common.h, symm/rijndael-x86ish-aesni.S: Better section switching.
[catacomb] / symm / rijndael-x86ish-aesni.S
index 4196181..3cca50f 100644 (file)
        .globl  F(rijndael_rcon)
 
 ///--------------------------------------------------------------------------
-/// Local utilities.
-
-// Magic constants for shuffling.
-#define ROTL 0x93
-#define ROT2 0x4e
-#define ROTR 0x39
-
-///--------------------------------------------------------------------------
 /// Main code.
 
        .arch   .aes
@@ -88,6 +80,7 @@ FUNC(rijndael_setup_x86ish_aesni)
 #  define RCON ecx                     // round constants table
 #  define LIM edx                      // limit pointer
 #  define LIMn edx                     // ... as integer offset from base
+#  define CYIX edi                     // index in shift-register cycle
 
 #  define NR ecx                       // number of rounds
 #  define LRK eax                      // distance to last key
@@ -123,6 +116,7 @@ FUNC(rijndael_setup_x86ish_aesni)
 #  define RCON rdi                     // round constants table
 #  define LIMn ecx                     // limit pointer
 #  define LIM rcx                      // ... as integer offset from base
+#  define CYIX r11d                    // index in shift-register cycle
 
 #  define NR ecx                       // number of rounds
 #  define LRK eax                      // distance to last key
@@ -152,6 +146,7 @@ FUNC(rijndael_setup_x86ish_aesni)
 #  define RCON rdi                     // round constants table
 #  define LIMn ecx                     // limit pointer
 #  define LIM rcx                      // ... as integer offset from base
+#  define CYIX r11d                    // index in shift-register cycle
 
 #  define NR ecx                       // number of rounds
 #  define LRK eax                      // distance to last key
@@ -162,7 +157,10 @@ FUNC(rijndael_setup_x86ish_aesni)
        // We'll need the index registers, which belong to the caller in this
        // ABI.
        push    rsi
+         .seh_pushreg rsi
        push    rdi
+         .seh_pushreg rdi
+  .seh_endprologue
 
        // Move arguments to more useful places.
        mov     SI, r8                  // key material
@@ -200,6 +198,7 @@ FUNC(rijndael_setup_x86ish_aesni)
        lea     SI, [CTX + w]
        mov     eax, [SI + 4*KSZo - 4]  // most recent key word
        lea     LIM, [SI + 4*LIM]       // limit, offset by one key expansion
+       xor     CYIX, CYIX              // start of new cycle
 
        // Main key expansion loop.  The first word of each key-length chunk
        // needs special treatment.
@@ -215,84 +214,41 @@ FUNC(rijndael_setup_x86ish_aesni)
        // as an immediate, so it's kind of annoying if you're not
        // open-coding the whole thing.  It's much easier to leave that as
        // zero and XOR in the round constant by hand.
-0:     movd    xmm0, eax
-       pshufd  xmm0, xmm0, ROTR
+0:     cmp     CYIX, 0                 // first word of the cycle?
+       je      1f
+       cmp     CYIX, 4                 // fourth word of the cycle?
+       jne     2f
+       cmp     KSZ, 7                  // and a large key?
+       jb      2f
+
+       // Fourth word of the cycle, and seven or eight words of key.  Do a
+       // byte substitution.
+       movd    xmm0, eax
+       pshufd  xmm0, xmm0, SHUF(2, 1, 0, 3)
        aeskeygenassist xmm1, xmm0, 0
-       pshufd  xmm1, xmm1, ROTL
        movd    eax, xmm1
-       xor     eax, [SI]
-       xor     al, [RCON]
-       inc     RCON
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
-
-       // The next three words are simple...
-       xor     eax, [SI]
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
-
-       // (Word 2...)
-       xor     eax, [SI]
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
-
-       // (Word 3...)
-       xor     eax, [SI]
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
+       jmp     2f
 
-       // Word 4.  If the key is /more/ than 6 words long, then we must
-       // apply a substitution here.
-       cmp     KSZ, 5
-       jb      0b
-       cmp     KSZ, 7
-       jb      1f
-       movd    xmm0, eax
-       pshufd  xmm0, xmm0, ROTL
+       // First word of the cycle.  This is the complicated piece.
+1:     movd    xmm0, eax
+       pshufd  xmm0, xmm0, SHUF(0, 3, 2, 1)
        aeskeygenassist xmm1, xmm0, 0
+       pshufd  xmm1, xmm1, SHUF(2, 1, 0, 3)
        movd    eax, xmm1
-1:     xor     eax, [SI]
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
-
-       // (Word 5...)
-       cmp     KSZ, 6
-       jb      0b
-       xor     eax, [SI]
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
+       xor     al, [RCON]
+       inc     RCON
 
-       // (Word 6...)
-       cmp     KSZ, 7
-       jb      0b
-       xor     eax, [SI]
+       // Common tail.  Mix in the corresponding word from the previous
+       // cycle and prepare for the next loop.
+2:     xor     eax, [SI]
        mov     [SI + 4*KSZo], eax
        add     SI, 4
+       inc     CYIX
        cmp     SI, LIM
        jae     9f
-
-       // (Word 7...)
-       cmp     KSZ, 8
+       cmp     CYIX, KSZ
        jb      0b
-       xor     eax, [SI]
-       mov     [SI + 4*KSZo], eax
-       add     SI, 4
-       cmp     SI, LIM
-       jae     9f
-
-       // Must be done by now.
+       xor     CYIX, CYIX
        jmp     0b
 
        // Next job is to construct the decryption keys.  The keys for the
@@ -430,18 +386,14 @@ ENDFUNC
 .macro encdec  op, aes, koff
   FUNC(rijndael_\op\()_x86ish_aesni)
 
-       // Find the magic endianness-swapping table.
-       ldgot   ecx
-       movdqa  xmm5, [INTADDR(endswap_tab, ecx)]
-
 #if CPUFAM_X86
        // Arguments come in on the stack, and need to be collected.  We
        // don't have a shortage of registers.
 
-#  define K ecx
+#  define K eax
 #  define SRC edx
 #  define DST edx
-#  define NR eax
+#  define NR ecx
 
        mov     K, [esp + 4]
        mov     SRC, [esp + 8]
@@ -463,8 +415,13 @@ ENDFUNC
 #  define SRC rdx
 #  define DST r8
 #  define NR eax
+  .seh_endprologue
 #endif
 
+       // Find the magic endianness-swapping table.
+       ldgot   ecx
+       movdqa  xmm5, [INTADDR(endswap_tab, ecx)]
+
        // Initial setup.
        movdqu  xmm0, [SRC]
        pshufb  xmm0, xmm5
@@ -475,6 +432,9 @@ ENDFUNC
        movdqu  xmm1, [K]
        add     K, 16
        pxor    xmm0, xmm1
+#if CPUFAM_X86
+       mov     DST, [esp + 12]
+#endif
 
        // Dispatch to the correct code.
        cmp     NR, 10
@@ -552,9 +512,6 @@ ENDFUNC
 
        // Unpermute the ciphertext block and store it.
        pshufb  xmm0, xmm5
-#if CPUFAM_X86
-       mov     DST, [esp + 12]
-#endif
        movdqu  [DST], xmm0
 
        // And we're done.
@@ -585,11 +542,11 @@ bogus:    callext F(abort)
 0:     hlt
        jmp     0b
 
-       gotaux  ecx
-
 ///--------------------------------------------------------------------------
 /// Data tables.
 
+       RODATA
+
        .align  16
 endswap_tab:
        .byte    3,  2,  1,  0