Skip to main content

javm_guest_tests/tests/
bitwise.rs

1//! Bitwise and shift test vectors.
2//!
3//! Shift/rotate input: u64 value (8 bytes) + u32 shift amount (4 bytes).
4//! Binary ops input: two u64 values (16 bytes).
5//! Unary ops input: one u64 value (8 bytes).
6//! Output: one u64 result (8 bytes).
7//!
8//! Each operation comes with a baked-corpus `_suite() -> u64` that
9//! XOR-folds the per-case u64 results into a single fingerprint —
10//! consumed by the three-way conformance harness.
11
12use crate::tests::arithmetic::{run_binary_u64, BINARY_U64_CASES};
13use crate::{read_u32, read_u64, write_u64};
14
15/// `(value, shift_amount)` pairs covering low, mid, boundary, and
16/// >=64 (wrapping_shl/shr is defined for these on RISC-V via mask).
17const SHIFT_CASES: &[(u64, u32)] = &[
18    (0, 0),
19    (1, 1),
20    (0xFFFF_FFFF_FFFF_FFFF, 0),
21    (0xFFFF_FFFF_FFFF_FFFF, 63),
22    (0xDEAD_BEEF_DEAD_BEEF, 7),
23    (0x8000_0000_0000_0000, 1),
24    (0x1, 63),
25];
26
27const UNARY_U64_CASES: &[u64] = &[
28    0,
29    1,
30    0xFFFF_FFFF_FFFF_FFFF,
31    0x8000_0000_0000_0000,
32    0x0000_0000_0000_0001,
33    0xDEAD_BEEF_DEAD_BEEF,
34];
35
36fn run_shift(op: fn(&[u8], &mut [u8]) -> usize) -> u64 {
37    let mut acc = 0u64;
38    let mut input = [0u8; 12];
39    let mut output = [0u8; 8];
40    for (val, amt) in SHIFT_CASES {
41        input[0..8].copy_from_slice(&val.to_le_bytes());
42        input[8..12].copy_from_slice(&amt.to_le_bytes());
43        let len = op(&input, &mut output);
44        debug_assert!(len == 8);
45        acc ^= u64::from_le_bytes(output);
46    }
47    acc
48}
49
50fn run_unary(op: fn(&[u8], &mut [u8]) -> usize) -> u64 {
51    let mut acc = 0u64;
52    let mut input = [0u8; 8];
53    let mut output = [0u8; 8];
54    for val in UNARY_U64_CASES {
55        input.copy_from_slice(&val.to_le_bytes());
56        let len = op(&input, &mut output);
57        debug_assert!(len == 8);
58        acc ^= u64::from_le_bytes(output);
59    }
60    acc
61}
62
63// -- Byte-level helpers --------------------------------------------------------
64
65pub fn shift_left(input: &[u8], output: &mut [u8]) -> usize {
66    let (mut off, mut out) = (0, 0);
67    let val = read_u64(input, &mut off);
68    let amt = read_u32(input, &mut off);
69    write_u64(output, &mut out, val.wrapping_shl(amt));
70    out
71}
72
73pub fn shift_right_logical(input: &[u8], output: &mut [u8]) -> usize {
74    let (mut off, mut out) = (0, 0);
75    let val = read_u64(input, &mut off);
76    let amt = read_u32(input, &mut off);
77    write_u64(output, &mut out, val.wrapping_shr(amt));
78    out
79}
80
81pub fn shift_right_arithmetic(input: &[u8], output: &mut [u8]) -> usize {
82    let (mut off, mut out) = (0, 0);
83    let val = read_u64(input, &mut off) as i64;
84    let amt = read_u32(input, &mut off);
85    write_u64(output, &mut out, val.wrapping_shr(amt) as u64);
86    out
87}
88
89pub fn rotate_right(input: &[u8], output: &mut [u8]) -> usize {
90    let (mut off, mut out) = (0, 0);
91    let val = read_u64(input, &mut off);
92    let amt = read_u32(input, &mut off);
93    write_u64(output, &mut out, val.rotate_right(amt));
94    out
95}
96
97pub fn and(input: &[u8], output: &mut [u8]) -> usize {
98    let (mut off, mut out) = (0, 0);
99    let a = read_u64(input, &mut off);
100    let b = read_u64(input, &mut off);
101    write_u64(output, &mut out, a & b);
102    out
103}
104
105pub fn or(input: &[u8], output: &mut [u8]) -> usize {
106    let (mut off, mut out) = (0, 0);
107    let a = read_u64(input, &mut off);
108    let b = read_u64(input, &mut off);
109    write_u64(output, &mut out, a | b);
110    out
111}
112
113pub fn xor(input: &[u8], output: &mut [u8]) -> usize {
114    let (mut off, mut out) = (0, 0);
115    let a = read_u64(input, &mut off);
116    let b = read_u64(input, &mut off);
117    write_u64(output, &mut out, a ^ b);
118    out
119}
120
121pub fn clz(input: &[u8], output: &mut [u8]) -> usize {
122    let (mut off, mut out) = (0, 0);
123    let val = read_u64(input, &mut off);
124    write_u64(output, &mut out, val.leading_zeros() as u64);
125    out
126}
127
128pub fn ctz(input: &[u8], output: &mut [u8]) -> usize {
129    let (mut off, mut out) = (0, 0);
130    let val = read_u64(input, &mut off);
131    write_u64(output, &mut out, val.trailing_zeros() as u64);
132    out
133}
134
135pub fn set_lt_u(input: &[u8], output: &mut [u8]) -> usize {
136    let (mut off, mut out) = (0, 0);
137    let a = read_u64(input, &mut off);
138    let b = read_u64(input, &mut off);
139    write_u64(output, &mut out, if a < b { 1 } else { 0 });
140    out
141}
142
143pub fn set_lt_s(input: &[u8], output: &mut [u8]) -> usize {
144    let (mut off, mut out) = (0, 0);
145    let a = read_u64(input, &mut off) as i64;
146    let b = read_u64(input, &mut off) as i64;
147    write_u64(output, &mut out, if a < b { 1 } else { 0 });
148    out
149}
150
151// -- Suites --------------------------------------------------------------------
152
153pub fn shift_left_suite() -> u64 {
154    run_shift(shift_left)
155}
156pub fn shift_right_logical_suite() -> u64 {
157    run_shift(shift_right_logical)
158}
159pub fn shift_right_arithmetic_suite() -> u64 {
160    run_shift(shift_right_arithmetic)
161}
162pub fn rotate_right_suite() -> u64 {
163    run_shift(rotate_right)
164}
165pub fn and_suite() -> u64 {
166    run_binary_u64(BINARY_U64_CASES, and)
167}
168pub fn or_suite() -> u64 {
169    run_binary_u64(BINARY_U64_CASES, or)
170}
171pub fn xor_suite() -> u64 {
172    run_binary_u64(BINARY_U64_CASES, xor)
173}
174pub fn clz_suite() -> u64 {
175    run_unary(clz)
176}
177pub fn ctz_suite() -> u64 {
178    run_unary(ctz)
179}
180pub fn set_lt_u_suite() -> u64 {
181    run_binary_u64(BINARY_U64_CASES, set_lt_u)
182}
183pub fn set_lt_s_suite() -> u64 {
184    run_binary_u64(BINARY_U64_CASES, set_lt_s)
185}