use super::{DOUBLE_WORD_SIZE, WORD_SIZE_FELT};
use crate::{
Felt,
errors::IoError,
processor::{
AdviceProviderInterface, MemoryInterface, Processor, StackInterface, SystemInterface,
},
tracer::{OperationHelperRegisters, Tracer},
};
#[cfg(test)]
mod tests;
#[inline(always)]
pub(super) fn op_advpop<P, T>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError>
where
P: Processor,
T: Tracer<Processor = P>,
{
let value = processor.advice_provider_mut().pop_stack()?;
tracer.record_advice_pop_stack(value);
processor.stack_mut().increment_size()?;
processor.stack_mut().set(0, value);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_advpopw<P, T>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError>
where
P: Processor,
T: Tracer<Processor = P>,
{
let word = processor.advice_provider_mut().pop_stack_word()?;
tracer.record_advice_pop_stack_word(word);
processor.stack_mut().set_word(0, &word);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_mloadw<P, T>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError>
where
P: Processor,
T: Tracer<Processor = P>,
{
let addr = processor.stack().get(0);
let ctx = processor.system().ctx();
let clk = processor.system().clock();
processor.stack_mut().decrement_size()?;
let word = processor.memory_mut().read_word(ctx, addr, clk)?;
tracer.record_memory_read_word(
word,
addr,
processor.system().ctx(),
processor.system().clock(),
);
processor.stack_mut().set_word(0, &word);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_mstorew<P, T>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError>
where
P: Processor,
T: Tracer<Processor = P>,
{
let addr = processor.stack().get(0);
let word = [
processor.stack().get(1),
processor.stack().get(2),
processor.stack().get(3),
processor.stack().get(4),
]
.into();
let ctx = processor.system().ctx();
let clk = processor.system().clock();
processor.stack_mut().decrement_size()?;
processor.memory_mut().write_word(ctx, addr, clk, word)?;
tracer.record_memory_write_word(
word,
addr,
processor.system().ctx(),
processor.system().clock(),
);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_mload<P: Processor, T: Tracer>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError> {
let ctx = processor.system().ctx();
let addr = processor.stack().get(0);
let element = processor.memory_mut().read_element(ctx, addr)?;
tracer.record_memory_read_element(
element,
addr,
processor.system().ctx(),
processor.system().clock(),
);
processor.stack_mut().set(0, element);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_mstore<P, T>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError>
where
P: Processor,
T: Tracer<Processor = P>,
{
let addr = processor.stack().get(0);
let value = processor.stack().get(1);
let ctx = processor.system().ctx();
processor.stack_mut().decrement_size()?;
processor.memory_mut().write_element(ctx, addr, value)?;
tracer.record_memory_write_element(
value,
addr,
processor.system().ctx(),
processor.system().clock(),
);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_mstream<P: Processor, T: Tracer>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError> {
const MEM_ADDR_STACK_IDX: usize = 12;
let ctx = processor.system().ctx();
let clk = processor.system().clock();
let addr_first_word = processor.stack().get(MEM_ADDR_STACK_IDX);
let words = {
let addr_second_word = addr_first_word + WORD_SIZE_FELT;
let first_word = processor.memory_mut().read_word(ctx, addr_first_word, clk)?;
let second_word = processor.memory_mut().read_word(ctx, addr_second_word, clk)?;
tracer.record_memory_read_dword([first_word, second_word], addr_first_word, ctx, clk);
[first_word, second_word]
};
processor.stack_mut().set_word(0, &words[0]);
processor.stack_mut().set_word(4, &words[1]);
processor
.stack_mut()
.set(MEM_ADDR_STACK_IDX, addr_first_word + DOUBLE_WORD_SIZE);
Ok(OperationHelperRegisters::Empty)
}
#[inline(always)]
pub(super) fn op_pipe<P: Processor, T: Tracer>(
processor: &mut P,
tracer: &mut T,
) -> Result<OperationHelperRegisters, IoError> {
const WORD_SIZE_FELT: Felt = Felt::new(4);
const DOUBLE_WORD_SIZE: Felt = Felt::new(8);
const MEM_ADDR_STACK_IDX: usize = 12;
let clk = processor.system().clock();
let ctx = processor.system().ctx();
let addr_first_word = processor.stack().get(MEM_ADDR_STACK_IDX);
let addr_second_word = addr_first_word + WORD_SIZE_FELT;
let words = processor.advice_provider_mut().pop_stack_dword()?;
processor.memory_mut().write_word(ctx, addr_first_word, clk, words[0])?;
processor.memory_mut().write_word(ctx, addr_second_word, clk, words[1])?;
tracer.record_pipe(words, addr_first_word, ctx, clk);
processor.stack_mut().set_word(0, &words[0]);
processor.stack_mut().set_word(4, &words[1]);
processor
.stack_mut()
.set(MEM_ADDR_STACK_IDX, addr_first_word + DOUBLE_WORD_SIZE);
Ok(OperationHelperRegisters::Empty)
}