diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 1f427b467f..90f330bd54 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -1,3 +1,4 @@ +use crate::mips::registers::{REGISTER_CURRENT_IP, REGISTER_NEXT_IP}; use log::debug; use strum_macros::{EnumCount, EnumIter}; @@ -397,13 +398,65 @@ pub trait InterpreterEnv { // TODO } - fn set_instruction_pointer(&mut self, ip: Self::Variable); + fn set_instruction_pointer(&mut self, ip: Self::Variable) { + let idx = Self::constant(REGISTER_CURRENT_IP as u32); + let new_accessed = self.instruction_counter() + Self::constant(1); + unsafe { + self.push_register_access(&idx, new_accessed.clone()); + } + unsafe { + self.push_register(&idx, ip.clone()); + } + self.add_lookup(Lookup { + numerator: -1, + table_id: LookupTable::RegisterLookup, + value: vec![idx, new_accessed, ip], + }); + } - fn get_instruction_pointer(&self) -> Self::Variable; + fn get_instruction_pointer(&mut self) -> Self::Variable { + let idx = Self::constant(REGISTER_CURRENT_IP as u32); + let ip = { + let value_location = self.alloc_scratch(); + unsafe { self.fetch_register(&idx, value_location) } + }; + self.add_lookup(Lookup { + numerator: 1, + table_id: LookupTable::RegisterLookup, + value: vec![idx, self.instruction_counter(), ip.clone()], + }); + ip + } - fn set_next_instruction_pointer(&mut self, ip: Self::Variable); + fn set_next_instruction_pointer(&mut self, ip: Self::Variable) { + let idx = Self::constant(REGISTER_NEXT_IP as u32); + let new_accessed = self.instruction_counter() + Self::constant(1); + unsafe { + self.push_register_access(&idx, new_accessed.clone()); + } + unsafe { + self.push_register(&idx, ip.clone()); + } + self.add_lookup(Lookup { + numerator: -1, + table_id: LookupTable::RegisterLookup, + value: vec![idx, new_accessed, ip], + }); + } - fn get_next_instruction_pointer(&self) -> Self::Variable; + fn get_next_instruction_pointer(&mut self) -> Self::Variable { + let idx = Self::constant(REGISTER_NEXT_IP as u32); + let ip = { + let value_location = self.alloc_scratch(); + unsafe { self.fetch_register(&idx, value_location) } + }; + self.add_lookup(Lookup { + numerator: 1, + table_id: LookupTable::RegisterLookup, + value: vec![idx, self.instruction_counter(), ip.clone()], + }); + ip + } fn constant(x: u32) -> Self::Variable; diff --git a/optimism/src/mips/registers.rs b/optimism/src/mips/registers.rs index 89a1ee23b8..bb737fe1e3 100644 --- a/optimism/src/mips/registers.rs +++ b/optimism/src/mips/registers.rs @@ -1,18 +1,30 @@ use serde::{Deserialize, Serialize}; use std::ops::{Index, IndexMut}; -pub const NUM_REGISTERS: usize = 34; +pub const REGISTER_HI: usize = 32; +pub const REGISTER_LO: usize = 33; +pub const REGISTER_CURRENT_IP: usize = 34; +pub const REGISTER_NEXT_IP: usize = 35; + +pub const NUM_REGISTERS: usize = 36; #[derive(Clone, Default, Debug, Serialize, Deserialize)] pub struct Registers { pub general_purpose: [T; 32], pub hi: T, pub lo: T, + pub current_instruction_pointer: T, + pub next_instruction_pointer: T, } impl Registers { pub fn iter(&self) -> impl Iterator { - self.general_purpose.iter().chain([&self.hi, &self.lo]) + self.general_purpose.iter().chain([ + &self.hi, + &self.lo, + &self.current_instruction_pointer, + &self.next_instruction_pointer, + ]) } } @@ -22,10 +34,14 @@ impl Index for Registers { fn index(&self, index: usize) -> &Self::Output { if index < 32 { &self.general_purpose[index] - } else if index == 32 { + } else if index == REGISTER_HI { &self.hi - } else if index == 33 { + } else if index == REGISTER_LO { &self.lo + } else if index == REGISTER_CURRENT_IP { + &self.current_instruction_pointer + } else if index == REGISTER_NEXT_IP { + &self.next_instruction_pointer } else { panic!("Index out of bounds"); } @@ -36,10 +52,14 @@ impl IndexMut for Registers { fn index_mut(&mut self, index: usize) -> &mut Self::Output { if index < 32 { &mut self.general_purpose[index] - } else if index == 32 { + } else if index == REGISTER_HI { &mut self.hi - } else if index == 33 { + } else if index == REGISTER_LO { &mut self.lo + } else if index == REGISTER_CURRENT_IP { + &mut self.current_instruction_pointer + } else if index == REGISTER_NEXT_IP { + &mut self.next_instruction_pointer } else { panic!("Index out of bounds"); } diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index 1893466367..eb9e4b58da 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -22,7 +22,7 @@ pub const NUM_DECODING_LOOKUP_TERMS: usize = 2; pub const NUM_INSTRUCTION_LOOKUP_TERMS: usize = 5; pub const NUM_LOOKUP_TERMS: usize = NUM_GLOBAL_LOOKUP_TERMS + NUM_DECODING_LOOKUP_TERMS + NUM_INSTRUCTION_LOOKUP_TERMS; -pub const SCRATCH_SIZE: usize = 29; +pub const SCRATCH_SIZE: usize = 31; #[derive(Clone, Default)] pub struct SyscallEnv { @@ -49,8 +49,6 @@ pub struct Env { pub memory_write_index: Vec<(u32, Vec)>, // TODO: u32 will not be big enough.. pub registers: Registers, pub registers_write_index: Registers, // TODO: u32 will not be big enough.. - pub instruction_pointer: u32, - pub next_instruction_pointer: u32, pub scratch_state_idx: usize, pub scratch_state: [Fp; SCRATCH_SIZE], pub halt: bool, @@ -202,22 +200,6 @@ impl InterpreterEnv for Env { panic!("Could not write to address") } - fn set_instruction_pointer(&mut self, ip: Self::Variable) { - self.instruction_pointer = ip; - } - - fn get_instruction_pointer(&self) -> Self::Variable { - self.instruction_pointer - } - - fn set_next_instruction_pointer(&mut self, ip: Self::Variable) { - self.next_instruction_pointer = ip; - } - - fn get_next_instruction_pointer(&self) -> Self::Variable { - self.next_instruction_pointer - } - fn constant(x: u32) -> Self::Variable { x } @@ -284,6 +266,8 @@ impl Env { lo: state.lo, hi: state.hi, general_purpose: state.registers, + current_instruction_pointer: initial_instruction_pointer, + next_instruction_pointer, }; Env { @@ -295,8 +279,6 @@ impl Env { .collect(), registers: initial_registers.clone(), registers_write_index: Registers::default(), - instruction_pointer: initial_instruction_pointer, - next_instruction_pointer, scratch_state_idx: 0, scratch_state: fresh_scratch_state(), halt: state.exited, @@ -328,10 +310,13 @@ impl Env { } pub fn decode_instruction(&self) -> (Instruction, u32) { - let instruction = ((self.get_memory_direct(self.instruction_pointer) as u32) << 24) - | ((self.get_memory_direct(self.instruction_pointer + 1) as u32) << 16) - | ((self.get_memory_direct(self.instruction_pointer + 2) as u32) << 8) - | (self.get_memory_direct(self.instruction_pointer + 3) as u32); + let instruction = + ((self.get_memory_direct(self.registers.current_instruction_pointer) as u32) << 24) + | ((self.get_memory_direct(self.registers.current_instruction_pointer + 1) as u32) + << 16) + | ((self.get_memory_direct(self.registers.current_instruction_pointer + 2) as u32) + << 8) + | (self.get_memory_direct(self.registers.current_instruction_pointer + 3) as u32); let opcode = { match instruction >> 26 { 0x00 => match instruction & 0x3F { @@ -490,7 +475,7 @@ impl Env { } fn page_address(&self) -> (u32, usize) { - let address = self.instruction_pointer; + let address = self.registers.current_instruction_pointer; let page = address >> PAGE_ADDRESS_SIZE; let page_address = (address & PAGE_ADDRESS_MASK) as usize; (page, page_address) @@ -513,7 +498,7 @@ impl Env { if self.should_trigger_at(at) { let elapsed = start.time.elapsed(); let step = self.instruction_counter; - let pc = self.instruction_pointer; + let pc = self.registers.current_instruction_pointer; // Get the 32-bits opcode let insn = self.get_opcode().unwrap();