ab_riscv_interpreter/rv32/zk/zkn/zknh/rv32_zknh_helpers.rs
1//! Opaque helpers for RV32 Zknh extension
2
3#[inline(always)]
4#[doc(hidden)]
5pub fn sha256sig0(x: u32) -> u32 {
6 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
7 cfg_select! {
8 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
9 // SAFETY: Compile-time checked for supported feature
10 unsafe { core::arch::riscv32::sha256sig0(x) }
11 }
12 _ => {
13 x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3)
14 }
15 }
16}
17
18#[inline(always)]
19#[doc(hidden)]
20pub fn sha256sig1(x: u32) -> u32 {
21 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
22 cfg_select! {
23 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
24 // SAFETY: Compile-time checked for supported feature
25 unsafe { core::arch::riscv32::sha256sig1(x) }
26 }
27 _ => {
28 x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10)
29 }
30 }
31}
32
33#[inline(always)]
34#[doc(hidden)]
35pub fn sha256sum0(x: u32) -> u32 {
36 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
37 cfg_select! {
38 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
39 // SAFETY: Compile-time checked for supported feature
40 unsafe { core::arch::riscv32::sha256sum0(x) }
41 }
42 _ => {
43 x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22)
44 }
45 }
46}
47
48#[inline(always)]
49#[doc(hidden)]
50pub fn sha256sum1(x: u32) -> u32 {
51 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
52 cfg_select! {
53 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
54 // SAFETY: Compile-time checked for supported feature
55 unsafe { core::arch::riscv32::sha256sum1(x) }
56 }
57 _ => {
58 x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25)
59 }
60 }
61}
62
63// SHA-512 sigma0: ROR64(x,1) ^ ROR64(x,8) ^ SHR64(x,7)
64
65/// High 32 bits of SHA-512 sigma0. rs1 = HIGH word, rs2 = LOW word.
66///
67/// ```text
68/// ROR64(x,1).hi = (rs1>>1) ^ (rs2<<31)
69/// ROR64(x,8).hi = (rs1>>8) ^ (rs2<<24)
70/// SHR64(x,7).hi = rs1>>7 <- shift: no rs2 contribution
71/// ```
72#[inline(always)]
73#[doc(hidden)]
74pub fn sha512sig0h(rs1: u32, rs2: u32) -> u32 {
75 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
76 cfg_select! {
77 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
78 // SAFETY: Compile-time checked for supported feature
79 unsafe { core::arch::riscv32::sha512sig0h(rs1, rs2) }
80 }
81 _ => {
82 (rs1 >> 1) ^ (rs2 << 31) ^ (rs1 >> 8) ^ (rs2 << 24) ^ (rs1 >> 7)
83 }
84 }
85}
86
87/// Low 32 bits of SHA-512 sigma0. rs1 = LOW word, rs2 = HIGH word.
88///
89/// ```text
90/// ROR64(x,1).lo = (rs1>>1) ^ (rs2<<31)
91/// ROR64(x,8).lo = (rs1>>8) ^ (rs2<<24)
92/// SHR64(x,7).lo = (rs1>>7) ^ (rs2<<25) <- cross-boundary bits from hi
93/// ```
94#[inline(always)]
95#[doc(hidden)]
96pub fn sha512sig0l(rs1: u32, rs2: u32) -> u32 {
97 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
98 cfg_select! {
99 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
100 // SAFETY: Compile-time checked for supported feature
101 unsafe { core::arch::riscv32::sha512sig0l(rs1, rs2) }
102 }
103 _ => {
104 (rs1 >> 1) ^ (rs2 << 31) ^ (rs1 >> 8) ^ (rs2 << 24) ^ (rs1 >> 7) ^ (rs2 << 25)
105 }
106 }
107}
108
109// SHA-512 sigma1: ROR64(x,19) ^ ROR64(x,61) ^ SHR64(x,6)
110
111/// High 32 bits of SHA-512 sigma1. rs1 = HIGH word, rs2 = LOW word.
112///
113/// ```text
114/// ROR64(x,19).hi = (rs1>>19) ^ (rs2<<13)
115/// ROR64(x,61).hi = ROR64(x,32+29).hi = (rs2>>29) ^ (rs1<<3)
116/// SHR64(x,6).hi = rs1>>6 <- shift: no rs2 contribution
117/// ```
118#[inline(always)]
119#[doc(hidden)]
120pub fn sha512sig1h(rs1: u32, rs2: u32) -> u32 {
121 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
122 cfg_select! {
123 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
124 // SAFETY: Compile-time checked for supported feature
125 unsafe { core::arch::riscv32::sha512sig1h(rs1, rs2) }
126 }
127 _ => {
128 (rs1 >> 19) ^ (rs2 << 13) ^ (rs2 >> 29) ^ (rs1 << 3) ^ (rs1 >> 6)
129 }
130 }
131}
132
133/// Low 32 bits of SHA-512 sigma1. rs1 = LOW word, rs2 = HIGH word.
134///
135/// ```text
136/// ROR64(x,19).lo = (rs1>>19) ^ (rs2<<13)
137/// ROR64(x,61).lo = ROR64(x,32+29).lo = (rs2>>29) ^ (rs1<<3)
138/// SHR64(x,6).lo = (rs1>>6) ^ (rs2<<26) <- cross-boundary bits from hi
139/// ```
140#[inline(always)]
141#[doc(hidden)]
142pub fn sha512sig1l(rs1: u32, rs2: u32) -> u32 {
143 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
144 cfg_select! {
145 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
146 // SAFETY: Compile-time checked for supported feature
147 unsafe { core::arch::riscv32::sha512sig1l(rs1, rs2) }
148 }
149 _ => {
150 (rs1 >> 19) ^ (rs2 << 13) ^ (rs2 >> 29) ^ (rs1 << 3) ^ (rs1 >> 6) ^ (rs2 << 26)
151 }
152 }
153}
154
155// SHA-512 Sum0: ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39)
156//
157// Sail: let x = X(rs2) @ X(rs1) => x[63:32] = rs2 (HIGH), x[31:0] = rs1 (LOW)
158// sum0r produces the LOW half of the result.
159//
160// ROR64({hi=rs2, lo=rs1}, 28).lo = (rs1>>28) ^ (rs2<<4) [n=28 < 32]
161// ROR64({hi=rs2, lo=rs1}, 34).lo = (rs2>>2) ^ (rs1<<30) [n=34 = 32+2]
162// ROR64({hi=rs2, lo=rs1}, 39).lo = (rs2>>7) ^ (rs1<<25) [n=39 = 32+7]
163
164/// Low 32 bits of SHA-512 Sum0. rs1 = LOW word, rs2 = HIGH word.
165///
166/// All three terms are rotations, so no asymmetric shift contribution.
167///
168/// ```text
169/// ROR64(x,28).lo = (rs1>>28) ^ (rs2<<4)
170/// ROR64(x,34).lo = ROR64(x,32+2).lo = (rs2>>2) ^ (rs1<<30)
171/// ROR64(x,39).lo = ROR64(x,32+7).lo = (rs2>>7) ^ (rs1<<25)
172/// ```
173#[inline(always)]
174#[doc(hidden)]
175pub fn sha512sum0r(rs1: u32, rs2: u32) -> u32 {
176 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
177 cfg_select! {
178 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
179 // SAFETY: Compile-time checked for supported feature
180 unsafe { core::arch::riscv32::sha512sum0r(rs1, rs2) }
181 }
182 _ => {
183 (rs1 >> 28) ^ (rs2 << 4) ^ (rs2 >> 2) ^ (rs1 << 30) ^ (rs2 >> 7) ^ (rs1 << 25)
184 }
185 }
186}
187
188// SHA-512 Sum1: ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41)
189//
190// Sail: let x = X(rs2) @ X(rs1) => x[63:32] = rs2 (HIGH), x[31:0] = rs1 (LOW)
191// sum1r produces the LOW half of the result.
192//
193// ROR64({hi=rs2, lo=rs1}, 14).lo = (rs1>>14) ^ (rs2<<18) [n=14 < 32]
194// ROR64({hi=rs2, lo=rs1}, 18).lo = (rs1>>18) ^ (rs2<<14) [n=18 < 32]
195// ROR64({hi=rs2, lo=rs1}, 41).lo = (rs2>>9) ^ (rs1<<23) [n=41 = 32+9]
196
197/// Low 32 bits of SHA-512 Sum1. rs1 = LOW word, rs2 = HIGH word.
198///
199/// All three terms are rotations.
200///
201/// ```text
202/// ROR64(x,14).lo = (rs1>>14) ^ (rs2<<18)
203/// ROR64(x,18).lo = (rs1>>18) ^ (rs2<<14)
204/// ROR64(x,41).lo = ROR64(x,32+9).lo = (rs2>>9) ^ (rs1<<23)
205/// ```
206#[inline(always)]
207#[doc(hidden)]
208pub fn sha512sum1r(rs1: u32, rs2: u32) -> u32 {
209 // TODO: Miri is excluded because corresponding intrinsic is not implemented there
210 cfg_select! {
211 all(not(miri), target_arch = "riscv32", target_feature = "zknh") => {
212 // SAFETY: Compile-time checked for supported feature
213 unsafe { core::arch::riscv32::sha512sum1r(rs1, rs2) }
214 }
215 _ => {
216 (rs1 >> 14) ^ (rs2 << 18) ^ (rs1 >> 18) ^ (rs2 << 14) ^ (rs2 >> 9) ^ (rs1 << 23)
217 }
218 }
219}