diff --git a/vm/src/types/instruction.rs b/vm/src/types/instruction.rs index 133c691302..698f6e0500 100644 --- a/vm/src/types/instruction.rs +++ b/vm/src/types/instruction.rs @@ -27,6 +27,7 @@ pub struct Instruction { pub ap_update: ApUpdate, pub fp_update: FpUpdate, pub opcode: Opcode, + pub opcode_extension: OpcodeExtension, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -76,6 +77,11 @@ pub enum Opcode { Ret, } +#[derive(Clone, Debug, Copy, PartialEq, Eq)] +pub enum OpcodeExtension { + Stone, +} + impl Instruction { pub fn size(&self) -> usize { match self.op1_addr { diff --git a/vm/src/vm/context/run_context.rs b/vm/src/vm/context/run_context.rs index d5de5d41f5..e2fdb9e633 100644 --- a/vm/src/vm/context/run_context.rs +++ b/vm/src/vm/context/run_context.rs @@ -106,7 +106,7 @@ mod tests { use super::*; use crate::relocatable; use crate::stdlib::string::ToString; - use crate::types::instruction::{ApUpdate, FpUpdate, Opcode, PcUpdate, Res}; + use crate::types::instruction::{ApUpdate, FpUpdate, Opcode, OpcodeExtension, PcUpdate, Res}; use crate::utils::test_utils::mayberelocatable; use crate::vm::errors::memory_errors::MemoryError; use crate::Felt252; @@ -130,6 +130,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -158,6 +159,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -187,6 +189,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -215,6 +218,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -243,6 +247,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -271,6 +276,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -299,6 +305,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -327,6 +334,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -358,6 +366,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -388,6 +397,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { @@ -420,6 +430,7 @@ mod tests { ap_update: ApUpdate::Regular, fp_update: FpUpdate::Regular, opcode: Opcode::NOp, + opcode_extension: OpcodeExtension::Stone, }; let run_context = RunContext { diff --git a/vm/src/vm/decoding/decoder.rs b/vm/src/vm/decoding/decoder.rs index 8a018980f4..0124f75566 100644 --- a/vm/src/vm/decoding/decoder.rs +++ b/vm/src/vm/decoding/decoder.rs @@ -1,16 +1,15 @@ use crate::{ types::instruction::{ - ApUpdate, FpUpdate, Instruction, Op1Addr, Opcode, PcUpdate, Register, Res, + ApUpdate, FpUpdate, Instruction, Op1Addr, Opcode, OpcodeExtension, PcUpdate, Register, Res, }, vm::errors::vm_errors::VirtualMachineError, }; -// 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg -// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0 +// opcode_extension| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg +// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0 -/// Decodes an instruction. The encoding is little endian, so flags go from bit 63 to 48. +/// Decodes an instruction. The encoding is little endian, so flags go from bit 64 to 48. pub fn decode_instruction(encoded_instr: u64) -> Result { - const HIGH_BIT: u64 = 1u64 << 63; const DST_REG_MASK: u64 = 0x0001; const DST_REG_OFF: u64 = 0; const OP0_REG_MASK: u64 = 0x0002; @@ -25,25 +24,23 @@ pub fn decode_instruction(encoded_instr: u64) -> Result> OFF0_OFF & OFFX_MASK); let off1 = decode_offset(encoded_instr >> OFF1_OFF & OFFX_MASK); let off2 = decode_offset(encoded_instr >> OFF2_OFF & OFFX_MASK); // Grab flags - let flags = encoded_instr >> FLAGS_OFFSET; + let flags = (encoded_instr >> FLAGS_OFFSET) & FLAGS_MASK; // Grab individual flags let dst_reg_num = (flags & DST_REG_MASK) >> DST_REG_OFF; let op0_reg_num = (flags & OP0_REG_MASK) >> OP0_REG_OFF; @@ -53,6 +50,9 @@ pub fn decode_instruction(encoded_instr: u64) -> Result> AP_UPDATE_OFF; let opcode_num = (flags & OPCODE_MASK) >> OPCODE_OFF; + // Grab opcode_extension + let opcode_extension_num = encoded_instr >> OPCODE_EXTENSION_OFF; + // Match each flag to its corresponding enum value let dst_register = if dst_reg_num == 1 { Register::FP @@ -98,6 +98,15 @@ pub fn decode_instruction(encoded_instr: u64) -> Result return Err(VirtualMachineError::InvalidOpcode(opcode_num)), }; + let opcode_extension = match opcode_extension_num { + 0 => OpcodeExtension::Stone, + _ => { + return Err(VirtualMachineError::InvalidOpcodeExtension( + opcode_extension_num, + )) + } + }; + let ap_update = match (ap_update_num, opcode == Opcode::Call) { (0, true) => ApUpdate::Add2, (0, false) => ApUpdate::Regular, @@ -145,6 +154,7 @@ pub fn decode_instruction(encoded_instr: u64) -> Result