sp1_core_machine/operations/
xor.rs

1use p3_field::{AbstractField, Field};
2use sp1_core_executor::{
3    events::{ByteLookupEvent, ByteRecord},
4    ByteOpcode,
5};
6use sp1_derive::AlignedBorrow;
7use sp1_primitives::consts::WORD_SIZE;
8use sp1_stark::{air::SP1AirBuilder, Word};
9
10/// A set of columns needed to compute the xor of two words.
11#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
12#[repr(C)]
13pub struct XorOperation<T> {
14    /// The result of `x ^ y`.
15    pub value: Word<T>,
16}
17
18impl<F: Field> XorOperation<F> {
19    pub fn populate(&mut self, record: &mut impl ByteRecord, x: u32, y: u32) -> u32 {
20        let expected = x ^ y;
21        let x_bytes = x.to_le_bytes();
22        let y_bytes = y.to_le_bytes();
23        for i in 0..WORD_SIZE {
24            let xor = x_bytes[i] ^ y_bytes[i];
25            self.value[i] = F::from_canonical_u8(xor);
26
27            let byte_event = ByteLookupEvent {
28                opcode: ByteOpcode::XOR,
29                a1: xor as u16,
30                a2: 0,
31                b: x_bytes[i],
32                c: y_bytes[i],
33            };
34            record.add_byte_lookup_event(byte_event);
35        }
36        expected
37    }
38
39    #[allow(unused_variables)]
40    pub fn eval<AB: SP1AirBuilder>(
41        builder: &mut AB,
42        a: Word<AB::Var>,
43        b: Word<AB::Var>,
44        cols: XorOperation<AB::Var>,
45        is_real: AB::Var,
46    ) {
47        for i in 0..WORD_SIZE {
48            builder.send_byte(
49                AB::F::from_canonical_u32(ByteOpcode::XOR as u32),
50                cols.value[i],
51                a[i],
52                b[i],
53                is_real,
54            );
55        }
56    }
57}