zkevm_assembly/assembly/instruction/
add.rs1use super::*;
6use crate::assembly::operand::{FullOperand, RegisterOperand};
7use crate::error::InstructionReadError;
8use std::collections::HashMap;
9use std::convert::TryFrom;
10
11#[derive(Debug, Clone, PartialEq)]
15pub struct Add {
16 pub condition: ConditionCase,
18 pub set_flags_option: SetFlags,
20 pub source_1: FullOperand,
22 pub source_2: RegisterOperand,
24 pub destination: FullOperand,
26}
27
28impl Add {
29 pub const NUM_ARGUMENTS: usize = 3;
31
32 #[track_caller]
33 pub fn build_from_parts(
34 mut modifiers: HashSet<&str>,
35 operands: Vec<&str>,
36 ) -> Result<Self, InstructionReadError> {
37 let operands = if let Ok(operands) = parse_canonical_operands_sequence(
38 operands.clone(),
39 &[marker_full_operand(), marker_register_operand()],
40 &[marker_full_operand()],
41 ) {
42 operands
43 } else {
44 parse_canonical_operands_sequence(
46 operands,
47 &[OperandType::Label, marker_register_operand()],
48 &[marker_full_operand()],
49 )?
50 };
51
52 let src0 = operands[0].clone();
53 let src1 = operands[1].clone();
54 let dst0 = operands[2].clone();
55
56 let condition = pick_condition(&mut modifiers)?;
57 let set_flags_option = pick_setting_flags(&mut modifiers)?;
58
59 if !modifiers.is_empty() {
60 return Err(InstructionReadError::UnknownArgument(format!(
61 "Add instruction contains unknown modifiers: {:?}",
62 modifiers
63 )));
64 }
65
66 let new = Self {
67 condition,
68 source_1: src0,
69 source_2: src1.as_register_operand(1)?,
70 destination: dst0,
71 set_flags_option,
72 };
73
74 Ok(new)
75 }
76
77 #[track_caller]
78 pub(crate) fn link<const N: usize, E: VmEncodingMode<N>>(
79 &mut self,
80 function_labels_to_pc: &HashMap<String, usize>,
81 constant_labels_to_offset: &HashMap<String, usize>,
82 globals_to_offsets: &HashMap<String, usize>,
83 ) -> Result<(), AssemblyParseError> {
84 link_operand::<N, E>(
85 &mut self.source_1,
86 function_labels_to_pc,
87 constant_labels_to_offset,
88 globals_to_offsets,
89 )?;
90
91 link_operand::<N, E>(
92 &mut self.destination,
93 function_labels_to_pc,
94 constant_labels_to_offset,
95 globals_to_offsets,
96 )?;
97
98 Ok(())
99 }
100}
101
102impl<const N: usize, E: VmEncodingMode<N>> TryFrom<Add> for DecodedOpcode<N, E> {
103 type Error = InstructionReadError;
104
105 fn try_from(value: Add) -> Result<Self, Self::Error> {
106 let mut new = DecodedOpcode::default();
107 new.variant = OpcodeVariant {
108 opcode: Opcode::Add(AddOpcode::Add),
109 ..OpcodeVariant::default()
110 };
111 set_src0_or_dst0_full_operand(&value.source_1.as_generic_operand(0)?, &mut new, false);
112 set_register_operand(&value.source_2, &mut new, false);
113 set_src0_or_dst0_full_operand(&value.destination.as_generic_operand(2)?, &mut new, true);
114 new.condition = value.condition.0;
115 new.variant.flags[SET_FLAGS_FLAG_IDX] = value.set_flags_option.0;
116
117 Ok(new)
118 }
119}