sp1_core_machine/operations/
xor.rs1use 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#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
12#[repr(C)]
13pub struct XorOperation<T> {
14 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}