Skip to main content

ab_riscv_interpreter/rv32/zk/zkn/zknh/
rv32_zknh_helpers.rs

1//! Opaque helpers for RV32 Zknh extension
2
3use const_fn_specialization::const_fn_specialization;
4
5#[const_fn_specialization]
6#[inline(always)]
7#[doc(hidden)]
8#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
9pub fn sha256sig0(x: u32) -> u32 {
10    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
11    cfg_select! {
12        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
13            // SAFETY: Compile-time checked for supported feature
14            unsafe { core::arch::riscv32::sha256sig0(x) }
15        }
16        _ => x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3),
17    }
18}
19
20#[const_fn_specialization]
21#[inline(always)]
22#[doc(hidden)]
23#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
24pub const fn sha256sig0(x: u32) -> u32 {
25    x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3)
26}
27
28#[const_fn_specialization]
29#[inline(always)]
30#[doc(hidden)]
31#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
32pub fn sha256sig1(x: u32) -> u32 {
33    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
34    cfg_select! {
35        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
36            // SAFETY: Compile-time checked for supported feature
37            unsafe { core::arch::riscv32::sha256sig1(x) }
38        }
39        _ => x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10),
40    }
41}
42
43#[const_fn_specialization]
44#[inline(always)]
45#[doc(hidden)]
46#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
47pub const fn sha256sig1(x: u32) -> u32 {
48    x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10)
49}
50
51#[const_fn_specialization]
52#[inline(always)]
53#[doc(hidden)]
54#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
55pub fn sha256sum0(x: u32) -> u32 {
56    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
57    cfg_select! {
58        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
59            // SAFETY: Compile-time checked for supported feature
60            unsafe { core::arch::riscv32::sha256sum0(x) }
61        }
62        _ => x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22),
63    }
64}
65
66#[const_fn_specialization]
67#[inline(always)]
68#[doc(hidden)]
69#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
70pub const fn sha256sum0(x: u32) -> u32 {
71    x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22)
72}
73
74#[const_fn_specialization]
75#[inline(always)]
76#[doc(hidden)]
77#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
78pub fn sha256sum1(x: u32) -> u32 {
79    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
80    cfg_select! {
81        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
82            // SAFETY: Compile-time checked for supported feature
83            unsafe { core::arch::riscv32::sha256sum1(x) }
84        }
85        _ => x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25),
86    }
87}
88
89#[const_fn_specialization]
90#[inline(always)]
91#[doc(hidden)]
92#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
93pub const fn sha256sum1(x: u32) -> u32 {
94    x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25)
95}
96
97// SHA-512 sigma0: ROR64(x,1) ^ ROR64(x,8) ^ SHR64(x,7)
98
99/// High 32 bits of SHA-512 sigma0. rs1 = HIGH word, rs2 = LOW word.
100///
101/// ```text
102/// ROR64(x,1).hi  = (rs1>>1)  ^ (rs2<<31)
103/// ROR64(x,8).hi  = (rs1>>8)  ^ (rs2<<24)
104/// SHR64(x,7).hi  =  rs1>>7              <- shift: no rs2 contribution
105/// ```
106#[const_fn_specialization]
107#[inline(always)]
108#[doc(hidden)]
109#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
110pub fn sha512sig0h(rs1: u32, rs2: u32) -> u32 {
111    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
112    cfg_select! {
113        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
114            // SAFETY: Compile-time checked for supported feature
115            unsafe { core::arch::riscv32::sha512sig0h(rs1, rs2) }
116        }
117        _ => (rs1 >> 1) ^ (rs2 << 31) ^ (rs1 >> 8) ^ (rs2 << 24) ^ (rs1 >> 7),
118    }
119}
120
121#[const_fn_specialization]
122#[inline(always)]
123#[doc(hidden)]
124#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
125pub const fn sha512sig0h(rs1: u32, rs2: u32) -> u32 {
126    (rs1 >> 1) ^ (rs2 << 31) ^ (rs1 >> 8) ^ (rs2 << 24) ^ (rs1 >> 7)
127}
128
129/// Low 32 bits of SHA-512 sigma0. rs1 = LOW word, rs2 = HIGH word.
130///
131/// ```text
132/// ROR64(x,1).lo  = (rs1>>1)  ^ (rs2<<31)
133/// ROR64(x,8).lo  = (rs1>>8)  ^ (rs2<<24)
134/// SHR64(x,7).lo  = (rs1>>7)  ^ (rs2<<25)  <- cross-boundary bits from hi
135/// ```
136#[const_fn_specialization]
137#[inline(always)]
138#[doc(hidden)]
139#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
140pub fn sha512sig0l(rs1: u32, rs2: u32) -> u32 {
141    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
142    cfg_select! {
143        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
144            // SAFETY: Compile-time checked for supported feature
145            unsafe { core::arch::riscv32::sha512sig0l(rs1, rs2) }
146        }
147        _ => (rs1 >> 1) ^ (rs2 << 31) ^ (rs1 >> 8) ^ (rs2 << 24) ^ (rs1 >> 7) ^ (rs2 << 25),
148    }
149}
150
151#[const_fn_specialization]
152#[inline(always)]
153#[doc(hidden)]
154#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
155pub const fn sha512sig0l(rs1: u32, rs2: u32) -> u32 {
156    (rs1 >> 1) ^ (rs2 << 31) ^ (rs1 >> 8) ^ (rs2 << 24) ^ (rs1 >> 7) ^ (rs2 << 25)
157}
158
159// SHA-512 sigma1: ROR64(x,19) ^ ROR64(x,61) ^ SHR64(x,6)
160
161/// High 32 bits of SHA-512 sigma1. rs1 = HIGH word, rs2 = LOW word.
162///
163/// ```text
164/// ROR64(x,19).hi = (rs1>>19) ^ (rs2<<13)
165/// ROR64(x,61).hi = ROR64(x,32+29).hi = (rs2>>29) ^ (rs1<<3)
166/// SHR64(x,6).hi  =  rs1>>6              <- shift: no rs2 contribution
167/// ```
168#[const_fn_specialization]
169#[inline(always)]
170#[doc(hidden)]
171#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
172pub fn sha512sig1h(rs1: u32, rs2: u32) -> u32 {
173    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
174    cfg_select! {
175        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
176            // SAFETY: Compile-time checked for supported feature
177            unsafe { core::arch::riscv32::sha512sig1h(rs1, rs2) }
178        }
179        _ => (rs1 >> 19) ^ (rs2 << 13) ^ (rs2 >> 29) ^ (rs1 << 3) ^ (rs1 >> 6),
180    }
181}
182
183#[const_fn_specialization]
184#[inline(always)]
185#[doc(hidden)]
186#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
187pub const fn sha512sig1h(rs1: u32, rs2: u32) -> u32 {
188    (rs1 >> 19) ^ (rs2 << 13) ^ (rs2 >> 29) ^ (rs1 << 3) ^ (rs1 >> 6)
189}
190
191/// Low 32 bits of SHA-512 sigma1. rs1 = LOW word, rs2 = HIGH word.
192///
193/// ```text
194/// ROR64(x,19).lo = (rs1>>19) ^ (rs2<<13)
195/// ROR64(x,61).lo = ROR64(x,32+29).lo = (rs2>>29) ^ (rs1<<3)
196/// SHR64(x,6).lo  = (rs1>>6)  ^ (rs2<<26)  <- cross-boundary bits from hi
197/// ```
198#[const_fn_specialization]
199#[inline(always)]
200#[doc(hidden)]
201#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
202pub fn sha512sig1l(rs1: u32, rs2: u32) -> u32 {
203    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
204    cfg_select! {
205        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
206            // SAFETY: Compile-time checked for supported feature
207            unsafe { core::arch::riscv32::sha512sig1l(rs1, rs2) }
208        }
209        _ => (rs1 >> 19) ^ (rs2 << 13) ^ (rs2 >> 29) ^ (rs1 << 3) ^ (rs1 >> 6) ^ (rs2 << 26),
210    }
211}
212
213#[const_fn_specialization]
214#[inline(always)]
215#[doc(hidden)]
216#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
217pub const fn sha512sig1l(rs1: u32, rs2: u32) -> u32 {
218    (rs1 >> 19) ^ (rs2 << 13) ^ (rs2 >> 29) ^ (rs1 << 3) ^ (rs1 >> 6) ^ (rs2 << 26)
219}
220
221// SHA-512 Sum0: ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39)
222//
223// Sail: let x = X(rs2) @ X(rs1)  =>  x[63:32] = rs2 (HIGH), x[31:0] = rs1 (LOW)
224// sum0r produces the LOW half of the result.
225//
226// ROR64({hi=rs2, lo=rs1}, 28).lo  = (rs1>>28) ^ (rs2<<4)   [n=28 < 32]
227// ROR64({hi=rs2, lo=rs1}, 34).lo  = (rs2>>2)  ^ (rs1<<30)  [n=34 = 32+2]
228// ROR64({hi=rs2, lo=rs1}, 39).lo  = (rs2>>7)  ^ (rs1<<25)  [n=39 = 32+7]
229
230/// Low 32 bits of SHA-512 Sum0. rs1 = LOW word, rs2 = HIGH word.
231///
232/// All three terms are rotations, so no asymmetric shift contribution.
233///
234/// ```text
235/// ROR64(x,28).lo = (rs1>>28) ^ (rs2<<4)
236/// ROR64(x,34).lo = ROR64(x,32+2).lo  = (rs2>>2)  ^ (rs1<<30)
237/// ROR64(x,39).lo = ROR64(x,32+7).lo  = (rs2>>7)  ^ (rs1<<25)
238/// ```
239#[const_fn_specialization]
240#[inline(always)]
241#[doc(hidden)]
242#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
243pub fn sha512sum0r(rs1: u32, rs2: u32) -> u32 {
244    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
245    cfg_select! {
246        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
247            // SAFETY: Compile-time checked for supported feature
248            unsafe { core::arch::riscv32::sha512sum0r(rs1, rs2) }
249        }
250        _ => (rs1 >> 28) ^ (rs2 << 4) ^ (rs2 >> 2) ^ (rs1 << 30) ^ (rs2 >> 7) ^ (rs1 << 25),
251    }
252}
253
254#[const_fn_specialization]
255#[inline(always)]
256#[doc(hidden)]
257#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
258pub const fn sha512sum0r(rs1: u32, rs2: u32) -> u32 {
259    (rs1 >> 28) ^ (rs2 << 4) ^ (rs2 >> 2) ^ (rs1 << 30) ^ (rs2 >> 7) ^ (rs1 << 25)
260}
261
262// SHA-512 Sum1: ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41)
263//
264// Sail: let x = X(rs2) @ X(rs1)  =>  x[63:32] = rs2 (HIGH), x[31:0] = rs1 (LOW)
265// sum1r produces the LOW half of the result.
266//
267// ROR64({hi=rs2, lo=rs1}, 14).lo  = (rs1>>14) ^ (rs2<<18)  [n=14 < 32]
268// ROR64({hi=rs2, lo=rs1}, 18).lo  = (rs1>>18) ^ (rs2<<14)  [n=18 < 32]
269// ROR64({hi=rs2, lo=rs1}, 41).lo  = (rs2>>9)  ^ (rs1<<23)  [n=41 = 32+9]
270
271/// Low 32 bits of SHA-512 Sum1. rs1 = LOW word, rs2 = HIGH word.
272///
273/// All three terms are rotations.
274///
275/// ```text
276/// ROR64(x,14).lo = (rs1>>14) ^ (rs2<<18)
277/// ROR64(x,18).lo = (rs1>>18) ^ (rs2<<14)
278/// ROR64(x,41).lo = ROR64(x,32+9).lo = (rs2>>9)  ^ (rs1<<23)
279/// ```
280#[const_fn_specialization]
281#[inline(always)]
282#[doc(hidden)]
283#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
284pub fn sha512sum1r(rs1: u32, rs2: u32) -> u32 {
285    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
286    cfg_select! {
287        all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
288            // SAFETY: Compile-time checked for supported feature
289            unsafe { core::arch::riscv32::sha512sum1r(rs1, rs2) }
290        }
291        _ => (rs1 >> 14) ^ (rs2 << 18) ^ (rs1 >> 18) ^ (rs2 << 14) ^ (rs2 >> 9) ^ (rs1 << 23),
292    }
293}
294
295#[const_fn_specialization]
296#[inline(always)]
297#[doc(hidden)]
298#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
299pub const fn sha512sum1r(rs1: u32, rs2: u32) -> u32 {
300    (rs1 >> 14) ^ (rs2 << 18) ^ (rs1 >> 18) ^ (rs2 << 14) ^ (rs2 >> 9) ^ (rs1 << 23)
301}