diff --git a/.gitignore b/.gitignore index 67a6dff458..c6f644327e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,5 @@ meta.json state.json # Directory for the RISC-V 32bits toolchain -_riscv32-gnu-toolchain \ No newline at end of file +_riscv32-gnu-toolchain +o1vm/resources/programs/riscv32im/bin/*.o \ No newline at end of file diff --git a/o1vm/resources/programs/riscv32im/bin/sll b/o1vm/resources/programs/riscv32im/bin/sll index f5a7fc75b1..14d0b82f86 100755 Binary files a/o1vm/resources/programs/riscv32im/bin/sll and b/o1vm/resources/programs/riscv32im/bin/sll differ diff --git a/o1vm/resources/programs/riscv32im/src/sll.S b/o1vm/resources/programs/riscv32im/src/sll.S index 0f8cedd065..e343543e81 100644 --- a/o1vm/resources/programs/riscv32im/src/sll.S +++ b/o1vm/resources/programs/riscv32im/src/sll.S @@ -1,6 +1,10 @@ .global _start -exit_success: +_start: + # Load 2^12 in the register t0 + lui t0, 0b1 + # Multiply by 4 + sll t0, t0, 2 li a0, 0 li a1, 0 li a2, 0 @@ -10,8 +14,3 @@ exit_success: li a6, 0 li a7, 42 ecall - -_start: - lui t0, 0x42 - sll t0, t0, 2 - jal exit_success diff --git a/o1vm/src/interpreters/riscv32im/interpreter.rs b/o1vm/src/interpreters/riscv32im/interpreter.rs index f27d89ec4e..e960a93fb4 100644 --- a/o1vm/src/interpreters/riscv32im/interpreter.rs +++ b/o1vm/src/interpreters/riscv32im/interpreter.rs @@ -1388,12 +1388,19 @@ pub trait InterpreterEnv { /// Given a variable `x`, this function extends it to a signed integer of /// `bitlength` bits. fn sign_extend(&mut self, x: &Self::Variable, bitlength: u32) -> Self::Variable { + assert!(bitlength <= 32); // FIXME: Constrain `high_bit` let high_bit = { let pos = self.alloc_scratch(); unsafe { self.bitmask(x, bitlength, bitlength - 1, pos) } }; - high_bit * Self::constant(((1 << (32 - bitlength)) - 1) << bitlength) + x.clone() + // Casting in u64 for special case of bitlength = 0 to avoid overflow. + // No condition for constant time execution. + // Decomposing the steps for readability. + let v: u64 = (1u64 << (32 - bitlength)) - 1; + let v: u64 = v << bitlength; + let v: u32 = v as u32; + high_bit * Self::constant(v) + x.clone() } fn report_exit(&mut self, exit_code: &Self::Variable); diff --git a/o1vm/src/interpreters/riscv32im/witness.rs b/o1vm/src/interpreters/riscv32im/witness.rs index c02b240bb4..011185339b 100644 --- a/o1vm/src/interpreters/riscv32im/witness.rs +++ b/o1vm/src/interpreters/riscv32im/witness.rs @@ -214,6 +214,14 @@ impl InterpreterEnv for Env { lowest_bit: u32, position: Self::Position, ) -> Self::Variable { + assert!( + lowest_bit < highest_bit, + "The lowest bit must be strictly lower than the highest bit" + ); + assert!( + highest_bit <= 32, + "The interpreter is for a 32bits architecture" + ); let x: u32 = (*x).try_into().unwrap(); let res = (x >> lowest_bit) & ((1 << (highest_bit - lowest_bit)) - 1); let res = res as u64; diff --git a/o1vm/tests/test_riscv_elf.rs b/o1vm/tests/test_riscv_elf.rs index 8aba68fd3f..c2925b7b10 100644 --- a/o1vm/tests/test_riscv_elf.rs +++ b/o1vm/tests/test_riscv_elf.rs @@ -15,8 +15,8 @@ fn test_registers_indexed_by_alias() { let state = o1vm::elf_loader::parse_riscv32(&path).unwrap(); let witness = Env::::create(PAGE_SIZE.try_into().unwrap(), state); - assert_eq!(witness.registers[Ip], 65688); - assert_eq!(witness.registers[NextIp], 65692); + assert_eq!(witness.registers[Ip], 65652); + assert_eq!(witness.registers[NextIp], 65656); } #[test] @@ -88,10 +88,7 @@ fn test_fibonacci_7() { } } -// FIXME: stop ignore when all the instructions necessary for running this -// program are implemented. #[test] -#[ignore] fn test_sll() { let curr_dir = std::env::current_dir().unwrap(); let path = curr_dir.join(std::path::PathBuf::from( @@ -104,5 +101,6 @@ fn test_sll() { witness.step(); } - // FIXME: check the state of the registers after the program has run. + // Expected output of the program + assert_eq!(witness.registers.general_purpose[5], 1 << 14) }