1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Four-byte packed bitsliced SM4 S-box (issue #163 serial-`tau` repair).
//!
//! Public entry point: [`sbox_x4`]. Operates on 4 independent S-box
//! inputs packed as `[u8; 4]`, returning `[u8; 4]`. The intended
//! consumer is `gmcrypto_core::sm4::cipher::tau` under
//! `sm4-bitsliced-simd`: one call replaces four one-byte-to-x8
//! broadcasts.
//!
//! # Dispatch
//!
//! - **aarch64:** stage the four bytes in the first four lanes of a
//! fixed x16 buffer (remaining lanes public zeros), invoke the
//! existing NEON x16 gate circuit once, return the first four
//! outputs. NEON is compile-time baseline; no runtime detect.
//! Must not go through [`super::sbox_x16::sbox_x16`] on any other
//! target (that dispatcher is 16 scalar calls off-aarch64).
//! - **`x86_64`:** exactly four scalar gate-circuit calls. AVX2 is
//! not the production branch: the 10% improvement rule could not
//! be measured on the `AArch64` implementation host. The AVX2
//! candidate remains [`sbox_x4_avx2`] for tests. Must not call
//! [`super::sbox_x8::sbox_x8`] (its non-AVX2 fallback is eight
//! scalar calls).
//! - **other targets:** [`sbox_x4_scalar`].
//!
//! [`sbox_x8`](super::sbox_x8) is kept as an internal AVX2 candidate
//! and test surface (v0.6 Q6.9). Removing the core one-byte adapter
//! does not delete that module.
use sbox_byte;
/// Scalar fallback: exactly four calls into
/// `super::scalar::sbox_byte`. Always available.
///
/// Takes `&[u8; 4]` to match [`super::sbox_x8::sbox_x8`] / x16 / x32
/// (lane-oriented array refs). Clippy's 8-byte pass-by-value
/// threshold would otherwise rewrite only this width.
/// Four-byte packed bitsliced SM4 S-box dispatch.
///
/// On `aarch64`, one NEON x16 invocation with public-zero filler
/// lanes. Elsewhere, exactly four scalar gate-circuit calls.
/// Stage four S-box bytes into the first four lanes of an x16
/// buffer. Remaining lanes are public zeros.
/// NEON four-byte S-box: one x16 gate-circuit invocation.
///
/// # Safety
///
/// Caller must be running on `aarch64` (NEON is baseline).
pub unsafe
// ============================================================
// x86_64 AVX2 candidate (not the production sbox_x4 branch)
// ============================================================
//
// AVX2-vs-scalar decision (issue #163 / design 10% rule):
// - Date: 2026-08-22
// - CPU: not measured (implementation host is aarch64-apple-darwin)
// - rustc: not measured on an AVX2 host
// - Key-construction medians: n/a
// - Pre-keyed single-block medians: n/a
// - Rule: select AVX2 only if repeated median is ≥10% faster for
// BOTH key construction and pre-keyed single-block encryption
// - Selection: four scalar calls. Either condition "cannot be
// measured" ⇒ production uses `sbox_x4_scalar`. Existing x32
// batch AVX2 is unchanged.
//
// The candidate below exists so x86 tests can exercise one direct
// x8 AVX2 invocation on four real lanes. Production `sbox_x4` does
// not call it.
/// AVX2 four-byte S-box candidate: one x8 gate-circuit invocation
/// with four public-zero filler lanes.
///
/// # Safety
///
/// Caller must guarantee the host CPU supports AVX2.
pub unsafe