ab_riscv_interpreter/rv64/zk/zkn/zkne/
rv64_zkne_helpers.rs1cfg_select! {
4 all(
5 not(miri),
6 target_arch = "riscv64",
7 target_feature = "zkne"
8 ) => {
9 }
11 all(target_arch = "x86_64", target_feature = "aes", target_feature = "sse4.1") => {
12 #[expect(
14 clippy::inline_modules,
15 reason = "Small internal API, it is more readable this way"
16 )]
17 mod x86_64 {
18 use core::arch::x86_64::{
19 _mm_aesenclast_si128, _mm_aesenc_si128, _mm_extract_epi64,
20 _mm_set_epi64x, _mm_setzero_si128,
21 };
22
23 #[inline]
26 #[target_feature(enable = "aes,sse4.1")]
27 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
28 pub(super) fn aes64es(rs1: u64, rs2: u64) -> u64 {
29 let state = _mm_set_epi64x(rs2.cast_signed(), rs1.cast_signed());
30 let zero = _mm_setzero_si128();
31 let result = _mm_aesenclast_si128(state, zero);
32 _mm_extract_epi64::<0>(result).cast_unsigned()
33 }
34
35 #[inline]
38 #[target_feature(enable = "aes,sse4.1")]
39 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
40 pub(super) fn aes64esm(rs1: u64, rs2: u64) -> u64 {
41 let state = _mm_set_epi64x(rs2.cast_signed(), rs1.cast_signed());
42 let zero = _mm_setzero_si128();
43 let result = _mm_aesenc_si128(state, zero);
44 _mm_extract_epi64::<0>(result).cast_unsigned()
45 }
46 }
47 }
48 all(target_arch = "aarch64", target_feature = "aes") => {
49 #[expect(
55 clippy::inline_modules,
56 reason = "Small internal API, it is more readable this way"
57 )]
58 mod aarch64 {
59 use core::arch::aarch64::{
60 vaeseq_u8, vaesmcq_u8, vcombine_u64, vcreate_u64, vdupq_n_u8, vgetq_lane_u64,
61 vreinterpretq_u8_u64, vreinterpretq_u64_u8,
62 };
63
64 #[inline]
65 #[target_feature(enable = "aes")]
66 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
67 pub(super) fn aes64es(rs1: u64, rs2: u64) -> u64 {
68 let state = vreinterpretq_u8_u64(vcombine_u64(vcreate_u64(rs1), vcreate_u64(rs2)));
69 let zero = vdupq_n_u8(0);
70 let result = vaeseq_u8(state, zero);
71 vgetq_lane_u64::<0>(vreinterpretq_u64_u8(result))
72 }
73
74 #[inline]
76 #[target_feature(enable = "aes")]
77 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
78 pub(super) fn aes64esm(rs1: u64, rs2: u64) -> u64 {
79 let state = vreinterpretq_u8_u64(vcombine_u64(vcreate_u64(rs1), vcreate_u64(rs2)));
80 let zero = vdupq_n_u8(0);
81 let after_sub_shift = vaeseq_u8(state, zero);
82 let result = vaesmcq_u8(after_sub_shift);
83 vgetq_lane_u64::<0>(vreinterpretq_u64_u8(result))
84 }
85 }
86 }
87 _ => {
88 #[expect(
90 clippy::inline_modules,
91 reason = "Small internal API, it is more readable this way"
92 )]
93 mod soft {
94 use crate::rv32::zk::zkn::zknd::rv32_zknd_helpers::{SBOX, gmul};
95
96 #[inline(always)]
97 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
98 fn mix_col(col: u32) -> u32 {
99 let s0 = col as u8;
100 let s1 = (col >> 8) as u8;
101 let s2 = (col >> 16) as u8;
102 let s3 = (col >> 24) as u8;
103 let r0 = gmul(s0, 0x02) ^ gmul(s1, 0x03) ^ s2 ^ s3;
104 let r1 = s0 ^ gmul(s1, 0x02) ^ gmul(s2, 0x03) ^ s3;
105 let r2 = s0 ^ s1 ^ gmul(s2, 0x02) ^ gmul(s3, 0x03);
106 let r3 = gmul(s0, 0x03) ^ s1 ^ s2 ^ gmul(s3, 0x02);
107 u32::from(r0) | (u32::from(r1) << 8) | (u32::from(r2) << 16) | (u32::from(r3) << 24)
108 }
109
110 #[inline(always)]
117 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
118 pub(super) fn aes64es(rs1: u64, rs2: u64) -> u64 {
119 let state_byte = |col: usize, row: usize| -> u8 {
120 let word = if col < 2 { rs1 } else { rs2 };
121 (word >> ((col % 2) * 32 + row * 8)) as u8
122 };
123
124 let mut out = 0;
125 for c in 0..2usize {
126 for r in 0..4usize {
127 let src_col = (c + r) & 3;
128 let b = SBOX[state_byte(src_col, r) as usize];
129 out |= u64::from(b) << (c * 32 + r * 8);
130 }
131 }
132 out
133 }
134
135 #[inline(always)]
136 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
137 pub(super) fn aes64esm(rs1: u64, rs2: u64) -> u64 {
138 let lo = aes64es(rs1, rs2);
139 let col0 = mix_col(lo as u32);
140 let col1 = mix_col((lo >> 32) as u32);
141 u64::from(col0) | (u64::from(col1) << 32)
142 }
143 }
144 }
145}
146
147#[inline(always)]
148#[doc(hidden)]
149#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
150pub fn aes64es(rs1: u64, rs2: u64) -> u64 {
151 cfg_select! {
153 all(
154 not(miri),
155 target_arch = "riscv64",
156 target_feature = "zkne"
157 ) => {
158 unsafe {
160 core::arch::riscv64::aes64es(rs1, rs2)
161 }
162 }
163 all(target_arch = "x86_64", target_feature = "aes", target_feature = "sse4.1") => {
164 unsafe {
166 x86_64::aes64es(rs1, rs2)
167 }
168 }
169 all(target_arch = "aarch64", target_feature = "aes") => {
170 unsafe {
172 aarch64::aes64es(rs1, rs2)
173 }
174 }
175 _ => { soft::aes64es(rs1, rs2) }
176 }
177}
178
179#[inline(always)]
180#[doc(hidden)]
181#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
182pub fn aes64esm(rs1: u64, rs2: u64) -> u64 {
183 cfg_select! {
185 all(
186 not(miri),
187 target_arch = "riscv64",
188 target_feature = "zkne"
189 ) => {
190 unsafe {
192 core::arch::riscv64::aes64esm(rs1, rs2)
193 }
194 }
195 all(target_arch = "x86_64", target_feature = "aes", target_feature = "sse4.1") => {
196 unsafe {
198 x86_64::aes64esm(rs1, rs2)
199 }
200 }
201 all(target_arch = "aarch64", target_feature = "aes") => {
202 unsafe {
204 aarch64::aes64esm(rs1, rs2)
205 }
206 }
207 _ => { soft::aes64esm(rs1, rs2) }
208 }
209}