@@ -30,31 +30,41 @@ std::optional<std::ranges::range_value_t<Range>> get_nth_filtered(Range&& range,
3030 return *std::ranges::next (filtered.begin (), static_cast <long >(index % static_cast <size_t >(count)));
3131}
3232
33- uint32_t get_max_variable_address (AddressingMode mode, uint32_t literal_max_value )
33+ uint32_t get_max_variable_address (AddressingMode mode, uint32_t base_offset, uint32_t max_operand_address )
3434{
35- if (mode == AddressingMode::Direct) {
36- return literal_max_value;
35+ switch (mode) {
36+ case AddressingMode::Direct:
37+ return max_operand_address;
38+ case AddressingMode::Relative:
39+ return base_offset + max_operand_address;
40+ case AddressingMode::Indirect:
41+ case AddressingMode::IndirectRelative:
42+ return AVM_HIGHEST_MEM_ADDRESS;
3743 }
38- // In relative addressing, and indirect addressing, we can reach any variable address.
39- return AVM_HIGHEST_MEM_ADDRESS;
4044}
4145
42- uint32_t trimmed_pointer_address ( uint32_t pointer_address_seed , uint32_t max_operand_address )
46+ uint32_t get_min_variable_address (AddressingMode mode , uint32_t base_offset )
4347{
44- return pointer_address_seed % (max_operand_address + 1 );
48+ switch (mode) {
49+ case AddressingMode::Relative:
50+ return base_offset;
51+ case AddressingMode::Direct:
52+ case AddressingMode::Indirect:
53+ case AddressingMode::IndirectRelative:
54+ return 0 ;
55+ }
4556}
4657
47- uint32_t trimmed_relative_operand_address (uint32_t base_offset_seed,
48- uint32_t relative_target,
49- uint32_t max_operand_address)
58+ uint32_t trimmed_pointer_address (uint32_t pointer_address_seed, uint32_t max_operand_address)
5059{
51- uint32_t max_operand = std::min (relative_target, max_operand_address);
52- return (base_offset_seed % (max_operand + 1 ));
60+ return pointer_address_seed % (max_operand_address + 1 );
5361}
5462
55- uint32_t trimmed_base_pointer (uint32_t base_offset_seed, uint32_t relative_target, uint32_t max_operand_address)
63+ uint32_t trimmed_relative_pointer_address (uint32_t pointer_address_seed,
64+ uint32_t base_offset,
65+ uint32_t max_operand_address)
5666{
57- return relative_target - trimmed_relative_operand_address (base_offset_seed, relative_target, max_operand_address);
67+ return base_offset + (pointer_address_seed % ( max_operand_address + 1 ) );
5868}
5969
6070} // namespace
@@ -107,19 +117,19 @@ ResolvedAddress MemoryManager::resolve_address(VariableRef variable,
107117 break ;
108118 }
109119 case AddressingMode::Relative:
110- resolved_address.base_pointer =
111- trimmed_base_pointer (variable.base_offset_seed , absolute_address, max_operand_address);
112- resolved_address.operand_address =
113- trimmed_relative_operand_address (variable.base_offset_seed , absolute_address, max_operand_address);
120+ BB_ASSERT_LTE (absolute_address, base_offset + max_operand_address);
121+ resolved_address.operand_address = absolute_address - base_offset;
122+ resolved_address.via_relative = true ;
114123 break ;
115- case AddressingMode::IndirectRelative:
116- resolved_address.pointer_address = variable.pointer_address_seed ;
124+ case AddressingMode::IndirectRelative: {
125+ uint32_t trimmed_pointer_address_value =
126+ trimmed_relative_pointer_address (variable.pointer_address_seed , base_offset, max_operand_address);
127+ resolved_address.pointer_address = trimmed_pointer_address_value;
117128 // Relative addressing target is the pointer
118- resolved_address.base_pointer =
119- trimmed_base_pointer (variable.base_offset_seed , variable.pointer_address_seed , max_operand_address);
120- resolved_address.operand_address = trimmed_relative_operand_address (
121- variable.base_offset_seed , variable.pointer_address_seed , max_operand_address);
129+ resolved_address.operand_address = trimmed_pointer_address_value - base_offset;
130+ resolved_address.via_relative = true ;
122131 break ;
132+ }
123133 case AddressingMode::Direct:
124134 // We can't change the absolute address, or it won't find anything useful there.
125135 resolved_address.operand_address = absolute_address;
@@ -136,30 +146,31 @@ ResolvedAddress MemoryManager::resolve_address(AddressRef address, uint32_t max_
136146 };
137147 switch (address.mode ) {
138148 case AddressingMode::Indirect: {
139- // Trim the pointer to 16 bits for it to be writable by SET_32
149+ // Trim the pointer to max_operand_address bits for it to be reachable by the instruction
140150 uint32_t trimmed_pointer_address_value =
141151 trimmed_pointer_address (address.pointer_address_seed , max_operand_address);
142152 resolved_address.pointer_address = trimmed_pointer_address_value;
143153 resolved_address.operand_address = trimmed_pointer_address_value;
144154 break ;
145155 }
146156 case AddressingMode::Relative:
147- resolved_address.base_pointer =
148- trimmed_base_pointer (address.base_offset_seed , resolved_address.absolute_address , max_operand_address);
149- resolved_address.operand_address = trimmed_relative_operand_address (
150- address.base_offset_seed , resolved_address.absolute_address , max_operand_address);
157+ BB_ASSERT_LTE (address.address , base_offset + max_operand_address);
158+ resolved_address.operand_address = address.address - base_offset;
159+ resolved_address.via_relative = true ;
151160 break ;
152- case AddressingMode::IndirectRelative:
153- resolved_address.pointer_address = address.pointer_address_seed ;
161+ case AddressingMode::IndirectRelative: {
154162 // Relative addressing target is the pointer
155- resolved_address.base_pointer =
156- trimmed_base_pointer (address.base_offset_seed , address.pointer_address_seed , max_operand_address);
157- resolved_address.operand_address = trimmed_relative_operand_address (
158- address.base_offset_seed , address.pointer_address_seed , max_operand_address);
163+ uint32_t trimmed_pointer_address_value =
164+ trimmed_relative_pointer_address (address.pointer_address_seed , base_offset, max_operand_address);
165+ resolved_address.pointer_address = trimmed_pointer_address_value;
166+
167+ resolved_address.operand_address = trimmed_pointer_address_value - base_offset;
168+ resolved_address.via_relative = true ;
159169 break ;
170+ }
160171 case AddressingMode::Direct:
161172 // Do not delete this assert, if it fails, it means that some address was generated / mutated incorrectly in
162- // instruction .cpp. Check all the `max_operand` parameters that you're passing to generate_address_ref.
173+ // instruction_block .cpp. Check all the `max_operand` parameters that you're passing to generate_address_ref.
163174 BB_ASSERT_LTE (address.address , max_operand_address);
164175 resolved_address.operand_address = resolved_address.absolute_address ;
165176 break ;
@@ -197,7 +208,10 @@ std::optional<std::pair<ResolvedAddress, bb::avm2::testing::OperandBuilder>> Mem
197208std::optional<std::pair<ResolvedAddress, bb::avm2::testing::OperandBuilder>> MemoryManager::
198209 get_resolved_address_and_operand_8 (VariableRef address)
199210{
200- auto actual_address = get_variable_address (address.tag , address.index , get_max_variable_address (address.mode , 255 ));
211+ auto actual_address = get_variable_address (address.tag ,
212+ address.index ,
213+ get_min_variable_address (address.mode , base_offset),
214+ get_max_variable_address (address.mode , base_offset, 255 ));
201215 if (!actual_address.has_value ()) {
202216 return std::nullopt ;
203217 }
@@ -214,6 +228,9 @@ std::optional<std::pair<ResolvedAddress, bb::avm2::testing::OperandBuilder>> Mem
214228 get_resolved_address_and_operand_8 (AddressRef address)
215229{
216230 auto resolved_address = resolve_address (address, 255 );
231+
232+ BB_ASSERT_LTE (resolved_address.operand_address , uint32_t { 255 });
233+
217234 auto operand = OperandBuilder::from<uint8_t >(static_cast <uint8_t >(resolved_address.operand_address ));
218235 return std::make_pair (resolved_address, get_memory_address_operand (operand, address.mode ));
219236}
@@ -229,8 +246,10 @@ std::optional<std::pair<ResolvedAddress, bb::avm2::testing::OperandBuilder>> Mem
229246std::optional<std::pair<ResolvedAddress, bb::avm2::testing::OperandBuilder>> MemoryManager::
230247 get_resolved_address_and_operand_16 (VariableRef address)
231248{
232- auto actual_address =
233- get_variable_address (address.tag , address.index , get_max_variable_address (address.mode , 65535 ));
249+ auto actual_address = get_variable_address (address.tag ,
250+ address.index ,
251+ get_min_variable_address (address.mode , base_offset),
252+ get_max_variable_address (address.mode , base_offset, 65535 ));
234253 if (!actual_address.has_value ()) {
235254 return std::nullopt ;
236255 }
@@ -246,18 +265,26 @@ std::optional<std::pair<ResolvedAddress, bb::avm2::testing::OperandBuilder>> Mem
246265 get_resolved_address_and_operand_16 (AddressRef address)
247266{
248267 auto resolved_address = resolve_address (address, 65535 );
268+ BB_ASSERT_LTE (resolved_address.operand_address , uint32_t { 65535 });
269+
249270 auto operand = OperandBuilder::from<uint16_t >(static_cast <uint16_t >(resolved_address.operand_address ));
250271 return std::make_pair (resolved_address, get_memory_address_operand (operand, address.mode ));
251272}
252273
253- std::optional<uint32_t > MemoryManager::get_variable_address (bb::avm2::MemoryTag tag, uint32_t index, uint32_t max_value)
274+ std::optional<uint32_t > MemoryManager::get_variable_address (bb::avm2::MemoryTag tag,
275+ uint32_t index,
276+ uint32_t min_value,
277+ uint32_t max_value)
254278{
255- return get_nth_filtered (this ->stored_variables [tag], [max_value](uint32_t val) { return val <= max_value; }, index);
279+ return get_nth_filtered (
280+ this ->stored_variables [tag],
281+ [min_value, max_value](uint32_t val) { return val >= min_value && val <= max_value; },
282+ index);
256283}
257284
258285std::optional<uint8_t > MemoryManager::get_memory_offset_8 (bb::avm2::MemoryTag tag, uint32_t index)
259286{
260- auto value = get_variable_address (tag, index, 255 );
287+ auto value = get_variable_address (tag, index, 0 , 255 );
261288 if (!value.has_value ()) {
262289 return std::nullopt ;
263290 }
@@ -267,7 +294,7 @@ std::optional<uint8_t> MemoryManager::get_memory_offset_8(bb::avm2::MemoryTag ta
267294
268295std::optional<uint16_t > MemoryManager::get_memory_offset_16 (bb::avm2::MemoryTag tag, uint32_t index)
269296{
270- auto value = get_variable_address (tag, index, 65535 );
297+ auto value = get_variable_address (tag, index, 0 , 65535 );
271298 if (!value.has_value ()) {
272299 return std::nullopt ;
273300 }
@@ -308,3 +335,8 @@ std::optional<uint16_t> MemoryManager::get_leaf_index(uint16_t note_hash_index)
308335 }
309336 return note_hash_index % emitted_note_hashes.size ();
310337}
338+
339+ void MemoryManager::set_base_offset (uint32_t base_offset)
340+ {
341+ this ->base_offset = base_offset;
342+ }
0 commit comments