symm/des-base.h: Improve the IP permutation network.
[catacomb] / symm / des-base.h
index 7e55e04..325af53 100644 (file)
@@ -122,27 +122,39 @@ extern const uint32 des_sp[8][64];
  *
  * We can implement this efficiently using our permutation machinery.
  * Writing ~k for index bit @k@ inverted, this permutation reflects the index
- * transformation given by ~0, 2, 1, ~5, ~4, ~3.  The following sequence of
- * operations is traditional.  Essentially this is an antitranspose -- a
- * reflection about the antidiagonal -- followed by a couple of fixup stages.
+ * transformation given by ~0, 2, 1, ~5, ~4, ~3.  There's a traditional
+ * swizzle sequence for this, which we used to use, namely:
+ *
+ *                                     //  5,  4,  3,  2,  1,  0
+ *     TWIZZLE_XCPL (x, y, 2);         // ~2,  4,  3, ~5,  1,  0
+ *     SWIZZLE_XCPL2(x, y, 1, 4);      // ~2, ~1,  3, ~5, ~4,  0
+ *     SWIZZLE_XCPL2(x, y, 0, 3);      // ~2, ~1, ~0, ~5, ~4, ~3
+ *     SWIZZLE_XCPL2(x, y, 3, 4);      // ~2,  0,  1, ~5, ~4, ~3
+ *     TWIZZLE_XCPL (x, y, 4);         // ~0,  2,  1, ~5, ~4, ~3
+ *
+ * Essentially this is an antitranspose -- a reflection about the
+ * antidiagonal -- followed by a couple of fixup stages.  But the non-twizzle
+ * steps require more operations, and it's easy to find a sequence which
+ * always acts on the (current) index bit 5, moving it to where it's wanted,
+ * and inverting it if necessary, so we only need twizzles.
  */
 
-#define DES_IP(x, y) do {              /*  5,  4,  3,  2,  1,  0 */    \
-  TWIZZLE_XCPL (x, y, 2);              /* ~2,  4,  3, ~5,  1,  0 */    \
-  SWIZZLE_XCPL2(x, y, 1, 4);           /* ~2, ~1,  3, ~5, ~4,  0 */    \
-  SWIZZLE_XCPL2(x, y, 0, 3);           /* ~2, ~1, ~0, ~5, ~4, ~3 */    \
-  SWIZZLE_XCPL2(x, y, 3, 4);           /* ~2,  0,  1, ~5, ~4, ~3 */    \
-  TWIZZLE_XCPL (x, y, 4);              /* ~0,  2,  1, ~5, ~4, ~3 */    \
+#define DES_IP(x, y) do {                                              \
+  TWIZZLE_XCPL(x, y, 2);               /* ~2,  4,  3, ~5,  1,  0 */    \
+  TWIZZLE_XCPL(x, y, 4);               /* ~4,  2,  3, ~5,  1,  0 */    \
+  TWIZZLE_EXCH(x, y, 1);               /*  1,  2,  3, ~5, ~4,  0 */    \
+  TWIZZLE_EXCH(x, y, 3);               /*  3,  2,  1, ~5, ~4,  0 */    \
+  TWIZZLE_XCPL(x, y, 0);               /* ~0,  2,  1, ~5, ~4, ~3 */    \
   x = ROL32(x, 1); y = ROL32(y, 1);                                    \
 } while (0)
 
 #define DES_IPINV(x, y) do {                                           \
   x = ROR32(x, 1); y = ROR32(y, 1);    /* ~0,  2,  1, ~5, ~4, ~3 */    \
-  TWIZZLE_XCPL (x, y, 4);              /* ~2,  0,  1, ~5, ~4, ~3 */    \
-  SWIZZLE_XCPL2(x, y, 3, 4);           /* ~2, ~1, ~0, ~5, ~4, ~3 */    \
-  SWIZZLE_XCPL2(x, y, 0, 3);           /* ~2, ~1,  3, ~5, ~4,  0 */    \
-  SWIZZLE_XCPL2(x, y, 1, 4);           /* ~2,  4,  3, ~5,  1,  0 */    \
-  TWIZZLE_XCPL (x, y, 2);              /*  5,  4,  3,  2,  1,  0 */    \
+  TWIZZLE_XCPL(x, y, 0);               /*  3,  2,  1, ~5, ~4,  0 */    \
+  TWIZZLE_EXCH(x, y, 3);               /*  1,  2,  3, ~5, ~4,  0 */    \
+  TWIZZLE_EXCH(x, y, 1);               /* ~4,  2,  3, ~5,  1,  0 */    \
+  TWIZZLE_XCPL(x, y, 4);               /*  3,  2,  1, ~5, ~4,  0 */    \
+  TWIZZLE_XCPL(x, y, 2);               /*  5,  4,  3,  2,  1,  0 */    \
 } while (0)
 
 /* --- @DES_EBLK@, @DES_DBLK@ --- *