From 232832e34dccf6d2781307244cf6e620a766fd39 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 6 Apr 2023 16:46:10 -0400 Subject: [PATCH] Implement smod in interpreter --- evm/src/cpu/kernel/interpreter.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 49ff2222..ede6aece 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -308,7 +308,7 @@ impl<'a> Interpreter<'a> { 0x04 => self.run_div(), // "DIV", 0x05 => self.run_sdiv(), // "SDIV", 0x06 => self.run_mod(), // "MOD", - 0x07 => todo!(), // "SMOD", + 0x07 => self.run_smod(), // "SMOD", 0x08 => self.run_addmod(), // "ADDMOD", 0x09 => self.run_mulmod(), // "MULMOD", 0x0a => self.run_exp(), // "EXP", @@ -509,6 +509,34 @@ impl<'a> Interpreter<'a> { self.push(if y.is_zero() { U256::zero() } else { x % y }); } + fn run_smod(&mut self) { + let mut x = self.pop(); + let mut y = self.pop(); + + if y.is_zero() { + self.push(U256::zero()); + } else { + let x_is_pos = x.eq(&(x & SIGN_MASK)); + let y_is_pos = y.eq(&(y & SIGN_MASK)); + + // We compute the absolute remainder first, + // then adapt its sign based on the operands. + if !x_is_pos { + x = two_complement(x); + } + if !y_is_pos { + y = two_complement(y); + } + let rem = x % y; + if rem.eq(&U256::zero()) { + self.push(U256::zero()); + } + + // Remainder always has the same sign as the dividend. + self.push(if x_is_pos { rem } else { two_complement(rem) }); + } + } + fn run_addmod(&mut self) { let x = U512::from(self.pop()); let y = U512::from(self.pop());