+CPU_DISPATCH(EMPTY, EMPTY, void, gcm_mktable,
+ (const gcm_params *p, uint32 *ktab, const uint32 *k),
+ (p, ktab, k),
+ pick_mktable, simple_mktable)
+
+static gcm_mktable__functype *pick_mktable(void)
+{
+ DISPATCH_PICK_FALLBACK(gcm_mktable, simple_mktable);
+}
+
+/* --- @recover_k@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *k@ = block-sized vector in which to store %$k$%
+ * @const uint32 *ktab@ = the table encoding %$k$%
+ *
+ * Returns: ---
+ *
+ * Use: Recovers %$k$%, the secret from which @ktab@ was by
+ * @gcm_mktable@, from the table, and stores it in internal
+ * (big-endian) form in @k@.
+ */
+
+static void simple_recover_k(const gcm_params *p,
+ uint32 *k, const uint32 *ktab)
+{
+ unsigned i;
+
+ /* If the blockcipher is big-endian, then the key is simply in the first
+ * table element, in the right format. If the blockcipher is little-endian
+ * then it's in element 24, and the bytes need swapping.
+ */
+
+ if (!(p->f&GCMF_SWAP)) for (i = 0; i < p->n; i++) k[i] = ktab[i];
+ else for (i = 0; i < p->n; i++) k[i] = ENDSWAP32(ktab[24*p->n + i]);
+}
+
+CPU_DISPATCH(static, EMPTY, void, recover_k,
+ (const gcm_params *p, uint32 *k, const uint32 *ktab),
+ (p, k, ktab),
+ pick_recover_k, simple_recover_k)
+
+static recover_k__functype *pick_recover_k(void)
+ { DISPATCH_PICK_FALLBACK(recover_k, simple_recover_k); }
+
+/* --- @gcm_mulk_N{b,l}@ --- *