@@ -170,14 +170,14 @@ impl Bytecode {
170170 & self . data
171171 }
172172
173- /// Maximum register index used by the tape
173+ /// Number of registers (0-indexed) used by the tape
174174 ///
175175 /// This does not include the virtual register `0xFF` used for immediates
176176 pub fn reg_count ( & self ) -> u8 {
177177 self . reg_count
178178 }
179179
180- /// Maximum memory slot used for `Load` / `Store` operations
180+ /// Number of memory slots (0-indexed) used for `Load` / `Store` operations
181181 pub fn mem_count ( & self ) -> u32 {
182182 self . mem_count
183183 }
@@ -197,14 +197,15 @@ impl Bytecode {
197197 let mut data = vec ! [ u32 :: MAX , 0u32 ] ;
198198 let mut reg_count = 0u8 ;
199199 let mut mem_count = 0u32 ;
200+ let mem_offset = u32:: try_from ( N ) . unwrap ( ) ;
200201 for op in t. iter_asm ( ) {
201202 let mut word = [ 0xFF ; 4 ] ;
202203 let mut imm = None ;
203204 let mut store_reg = |i, r| {
204205 if r == u8:: MAX {
205206 Err ( ReservedRegister )
206207 } else {
207- reg_count = reg_count. max ( r) ; // update the max reg
208+ reg_count = reg_count. max ( r + 1 ) ;
208209 word[ i] = r;
209210 Ok ( ( ) )
210211 }
@@ -217,15 +218,15 @@ impl Bytecode {
217218
218219 RegOp :: Load ( reg, slot) => {
219220 store_reg ( 1 , reg) ?;
220- store_reg ( 2 , u8:: MAX ) ? ;
221- mem_count = mem_count. max ( slot) ;
222- imm = Some ( slot) ;
221+ word [ 2 ] = u8:: MAX ;
222+ mem_count = mem_count. max ( slot + 1 - mem_offset ) ;
223+ imm = Some ( slot - mem_offset ) ;
223224 }
224225 RegOp :: Store ( reg, slot) => {
225- store_reg ( 1 , u8:: MAX ) ?;
226226 store_reg ( 2 , reg) ?;
227- mem_count = mem_count. max ( slot) ;
228- imm = Some ( slot) ;
227+ word[ 1 ] = u8:: MAX ;
228+ mem_count = mem_count. max ( slot + 1 - mem_offset) ;
229+ imm = Some ( slot - mem_offset) ;
229230 }
230231
231232 RegOp :: CopyImm ( out, imm_f32) => {
@@ -361,6 +362,7 @@ mod test {
361362
362363 #[ test]
363364 fn load_store ( ) {
365+ // Build a bytecode tape with only 2 registers to test load and store
364366 let mut ctx = fidget_core:: Context :: new ( ) ;
365367 let x = ctx. x ( ) ;
366368 let y = ctx. y ( ) ;
@@ -369,13 +371,65 @@ mod test {
369371 let out = ctx. max ( xy, z) . unwrap ( ) ;
370372 let data = VmData :: < 2 > :: new ( & ctx, & [ out] ) . unwrap ( ) ;
371373 let bc = Bytecode :: new ( & data) . unwrap ( ) ;
374+ assert_eq ! ( bc. reg_count( ) , 2 ) ;
375+ assert_eq ! ( bc. mem_count( ) , 1 ) ;
372376 let mut iter = bc. data . iter ( ) ;
373377 let mut next = || * iter. next ( ) . unwrap ( ) ;
374378 assert_eq ! ( next( ) , 0xFFFFFFFF ) ; // start marker
375379 assert_eq ! ( next( ) , 0 ) ;
380+
381+ // Input(1, Z)
382+ assert_eq ! (
383+ next( ) . to_le_bytes( ) ,
384+ [ BytecodeOp :: Input as u8 , 1 , 0xFF , 0xFF ]
385+ ) ;
386+ assert_eq ! ( next( ) , 2 ) ; // Z
387+
388+ // Copy from reg[1] -> mem[0]
389+ assert_eq ! (
390+ next( ) . to_le_bytes( ) ,
391+ [ BytecodeOp :: Mem as u8 , 0xFF , 1 , 0xFF ]
392+ ) ;
393+ assert_eq ! ( next( ) , 0 ) ;
394+
395+ // Input(1, Y)
376396 assert_eq ! (
377397 next( ) . to_le_bytes( ) ,
378- [ BytecodeOp :: Copy as u8 , 0 , 0xFF , 0xFF ]
398+ [ BytecodeOp :: Input as u8 , 1 , 0xFF , 0xFF ]
399+ ) ;
400+ assert_eq ! ( next( ) , 1 ) ; // Y
401+
402+ // Input(0, X)
403+ assert_eq ! (
404+ next( ) . to_le_bytes( ) ,
405+ [ BytecodeOp :: Input as u8 , 0 , 0xFF , 0xFF ]
379406 ) ;
407+ assert_eq ! ( next( ) , 0 ) ; // X
408+
409+ // r1 = max(1, 0)
410+ assert_eq ! ( next( ) . to_le_bytes( ) , [ BytecodeOp :: Max as u8 , 1 , 1 , 0 ] ) ;
411+ assert_eq ! ( next( ) , 0xFF000000 ) ;
412+
413+ // Copy from mem[0] -> reg[0]
414+ assert_eq ! (
415+ next( ) . to_le_bytes( ) ,
416+ [ BytecodeOp :: Mem as u8 , 0 , 0xFF , 0xFF ]
417+ ) ;
418+ assert_eq ! ( next( ) , 0 ) ;
419+
420+ // r0 = max(0, 1)
421+ assert_eq ! ( next( ) . to_le_bytes( ) , [ BytecodeOp :: Max as u8 , 0 , 0 , 1 ] ) ;
422+ assert_eq ! ( next( ) , 0xFF000000 ) ;
423+
424+ // output(0) = r0
425+ assert_eq ! (
426+ next( ) . to_le_bytes( ) ,
427+ [ BytecodeOp :: Output as u8 , 0 , 0xFF , 0xFF ]
428+ ) ;
429+ assert_eq ! ( next( ) , 0 ) ;
430+
431+ assert_eq ! ( next( ) , 0xFFFFFFFF ) ; // end marker
432+ assert_eq ! ( next( ) , 0xFFFFFFFF ) ;
433+ assert ! ( iter. next( ) . is_none( ) ) ;
380434 }
381435}
0 commit comments