@@ -731,3 +731,231 @@ fn store_u8() {
731731 _ => panic ! ( "Unexpected test result: {res:?}" ) ,
732732 }
733733}
734+
735+ #[ test]
736+ fn store_unaligned_u32 ( ) {
737+ // Use the start of the 17th page (1 page after the 16 pages reserved for the Rust stack)
738+ let write_to = 17 * 2u32 . pow ( 16 ) ;
739+ let write_val = 0xddccbbaa_u32 ; // Little-endian bytes will be [AA BB CC DD].
740+
741+ // Generate a `test` module with `main` function that stores to a u32 offset.
742+ let signature = Signature :: new (
743+ [ AbiParam :: new ( Type :: U32 ) ] ,
744+ [ AbiParam :: new ( Type :: U32 ) ] , // Return u32 to satisfy test infrastructure
745+ ) ;
746+
747+ // Compile once outside the test loop
748+ let ( package, context) = compile_test_module ( signature, |builder| {
749+ let block = builder. current_block ( ) ;
750+ let idx_val = block. borrow ( ) . arguments ( ) [ 0 ] as ValueRef ;
751+
752+ // Set base pointer, add argument offset to it.
753+ let base_addr = builder. u32 ( write_to, SourceSpan :: default ( ) ) ;
754+ let write_addr = builder. add ( base_addr, idx_val, SourceSpan :: default ( ) ) . unwrap ( ) ;
755+ let ptr = builder
756+ . inttoptr ( write_addr, Type :: from ( PointerType :: new ( Type :: U32 ) ) , SourceSpan :: default ( ) )
757+ . unwrap ( ) ;
758+
759+ // Store test value to pointer.
760+ let write_val = builder. u32 ( write_val, SourceSpan :: default ( ) ) ;
761+ builder. store ( ptr, write_val, SourceSpan :: default ( ) ) . unwrap ( ) ;
762+
763+ // Return a constant to satisfy test infrastructure
764+ let result = builder. u32 ( 1 , SourceSpan :: default ( ) ) ;
765+ builder. ret ( Some ( result) , SourceSpan :: default ( ) ) . unwrap ( ) ;
766+ } ) ;
767+
768+ let run_test = |offs : u32 , expected0 : u32 , expected1 : u32 | {
769+ // Initialise memory with some known bytes.
770+ let initializers = [ Initializer :: MemoryBytes {
771+ addr : write_to,
772+ bytes : & [ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 ] ,
773+ } ] ;
774+
775+ let output = eval_package :: < u32 , _ , _ > (
776+ & package,
777+ initializers,
778+ & [ Felt :: new ( offs as u64 ) ] ,
779+ context. session ( ) ,
780+ |trace| {
781+ // Get the overwritten words.
782+ let word0 = trace. read_from_rust_memory :: < u32 > ( write_to) . unwrap ( ) ;
783+ let word1 = trace. read_from_rust_memory :: < u32 > ( write_to + 4 ) . unwrap ( ) ;
784+
785+ eprintln ! ( "word0: 0x{word0:0>8x}" ) ;
786+ eprintln ! ( "word1: 0x{word1:0>8x}" ) ;
787+
788+ assert_eq ! (
789+ word0, expected0,
790+ "expected 1st overwritten word to be {expected0}, got {word0}, with offset \
791+ {offs}"
792+ ) ;
793+
794+ assert_eq ! (
795+ word1, expected1,
796+ "expected 2nd overwritten word to be {expected1}, got {word1}, with offset \
797+ {offs}"
798+ ) ;
799+
800+ Ok ( ( ) )
801+ } ,
802+ )
803+ . unwrap ( ) ;
804+
805+ assert_eq ! ( output, 1 ) ;
806+ } ;
807+
808+ // Overwrite 11 22 33 44 55 66 77 88 with bytes aa bb cc dd at offset 1:
809+ // Expect 11 aa bb cc | dd 66 77 88
810+ // or 0xccbbaa11 and 0x887766dd.
811+ run_test ( 1 , 0xccbbaa11 , 0x887766dd ) ;
812+
813+ // Overwrite 11 22 33 44 55 66 77 88 with bytes aa bb cc dd at offset 2:
814+ // Expect 11 22 aa bb | cc dd 77 88
815+ // or 0xbbaa2211 and 0x8877ddcc.
816+ run_test ( 2 , 0xbbaa2211 , 0x8877ddcc ) ;
817+
818+ // Overwrite 11 22 33 44 55 66 77 88 with bytes aa bb cc dd at offset 3:
819+ // Expect 11 22 33 aa | bb cc dd 88
820+ // or 0xaa332211 and 0x88ddccbb.
821+ run_test ( 3 , 0xaa332211 , 0x88ddccbb ) ;
822+ }
823+
824+ #[ test]
825+ fn store_unaligned_u64 ( ) {
826+ // Use the start of the 17th page (1 page after the 16 pages reserved for the Rust stack)
827+ let write_to = 17 * 2u32 . pow ( 16 ) ;
828+
829+ // STORE_DW writes the high 32bit word to address and low 32bit word to address+1.
830+ // So a .store() of 0xddccbbaa_cdabffee writes 0xddccbbaa to addr and 0xcdabffee to addr+1.
831+ // Which in turn will be little-endian bytes [ AA BB CC DD EE FF AB CD ] at addr.
832+ let write_val = 0xddccbbaa_cdabffee_u64 ;
833+
834+ // Generate a `test` module with `main` function that stores to a u32 offset.
835+ let signature = Signature :: new (
836+ [ AbiParam :: new ( Type :: U32 ) ] ,
837+ [ AbiParam :: new ( Type :: U32 ) ] , // Return u32 to satisfy test infrastructure
838+ ) ;
839+
840+ // Compile once outside the test loop
841+ let ( package, context) = compile_test_module ( signature, |builder| {
842+ let block = builder. current_block ( ) ;
843+ let idx_val = block. borrow ( ) . arguments ( ) [ 0 ] as ValueRef ;
844+
845+ // Set base pointer, add argument offset to it.
846+ let base_addr = builder. u32 ( write_to, SourceSpan :: default ( ) ) ;
847+ let write_addr = builder. add ( base_addr, idx_val, SourceSpan :: default ( ) ) . unwrap ( ) ;
848+ let ptr = builder
849+ . inttoptr ( write_addr, Type :: from ( PointerType :: new ( Type :: U64 ) ) , SourceSpan :: default ( ) )
850+ . unwrap ( ) ;
851+
852+ // Store test value to pointer.
853+ let write_val = builder. u64 ( write_val, SourceSpan :: default ( ) ) ;
854+ builder. store ( ptr, write_val, SourceSpan :: default ( ) ) . unwrap ( ) ;
855+
856+ // Return a constant to satisfy test infrastructure
857+ let result = builder. u32 ( 1 , SourceSpan :: default ( ) ) ;
858+ builder. ret ( Some ( result) , SourceSpan :: default ( ) ) . unwrap ( ) ;
859+ } ) ;
860+
861+ let run_test = |offs : u32 , expected0 : u32 , expected1 : u32 , expected2 : u32 , expected3 : u32 | {
862+ // Initialise memory with some known bytes.
863+ let initializers = [ Initializer :: MemoryBytes {
864+ addr : write_to,
865+ bytes : & [
866+ 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 ,
867+ 0x17 , 0x18 ,
868+ ] ,
869+ } ] ;
870+
871+ let output = eval_package :: < u32 , _ , _ > (
872+ & package,
873+ initializers,
874+ & [ Felt :: new ( offs as u64 ) ] ,
875+ context. session ( ) ,
876+ |trace| {
877+ // Get the overwritten words.
878+ let word0 = trace. read_from_rust_memory :: < u32 > ( write_to) . unwrap ( ) ;
879+ let word1 = trace. read_from_rust_memory :: < u32 > ( write_to + 4 ) . unwrap ( ) ;
880+ let word2 = trace. read_from_rust_memory :: < u32 > ( write_to + 8 ) . unwrap ( ) ;
881+ let word3 = trace. read_from_rust_memory :: < u32 > ( write_to + 12 ) . unwrap ( ) ;
882+
883+ eprintln ! ( "word0: 0x{word0:0>8x}" ) ;
884+ eprintln ! ( "word1: 0x{word1:0>8x}" ) ;
885+ eprintln ! ( "word2: 0x{word2:0>8x}" ) ;
886+ eprintln ! ( "word3: 0x{word3:0>8x}" ) ;
887+
888+ assert_eq ! (
889+ word0, expected0,
890+ "expected 1st overwritten word to be {expected0}, got {word0}, with offset \
891+ {offs}"
892+ ) ;
893+
894+ assert_eq ! (
895+ word1, expected1,
896+ "expected 2nd overwritten word to be {expected1}, got {word1}, with offset \
897+ {offs}"
898+ ) ;
899+
900+ assert_eq ! (
901+ word2, expected2,
902+ "expected 3rd overwritten word to be {expected2}, got {word2}, with offset \
903+ {offs}"
904+ ) ;
905+
906+ assert_eq ! (
907+ word3, expected3,
908+ "expected 4th overwritten word to be {expected3}, got {word3}, with offset \
909+ {offs}"
910+ ) ;
911+
912+ Ok ( ( ) )
913+ } ,
914+ )
915+ . unwrap ( ) ;
916+
917+ assert_eq ! ( output, 1 ) ;
918+ } ;
919+
920+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
921+ // with bytes aa bb cc dd ee ff ab cd at offset 1:
922+ // Expect 01 aa bb cc dd ee ff ab cd 12 13 14 15 16 17 18
923+ // or 0xccbbaa01, 0xabffeedd, 0x141312cd, 0x18171615
924+ run_test ( 1 , 0xccbbaa01 , 0xabffeedd , 0x141312cd , 0x18171615 ) ;
925+
926+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
927+ // with bytes aa bb cc dd ee ff ab cd at offset 2:
928+ // Expect 01 02 aa bb cc dd ee ff ab cd 13 14 15 16 17 18
929+ // or 0xbbaa0201, 0xffeeddcc, 0x1413cdab, 0x18171615
930+ run_test ( 2 , 0xbbaa0201 , 0xffeeddcc , 0x1413cdab , 0x18171615 ) ;
931+
932+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
933+ // with bytes aa bb cc dd ee ff ab cd at offset 3:
934+ // Expect 01 02 03 aa bb cc dd ee ff ab cd 14 15 16 17 18
935+ // or 0xaa030201, 0xeeddccbb, 0x14cdabff, 0x18171615
936+ run_test ( 3 , 0xaa030201 , 0xeeddccbb , 0x14cdabff , 0x18171615 ) ;
937+
938+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
939+ // with bytes aa bb cc dd ee ff ab cd at offset 4:
940+ // Expect 01 02 03 04 aa bb cc dd ee ff ab cd 15 16 17 18
941+ // or 0x04030201, 0xddccbbaa, 0xcdabffee, 0x18171615
942+ run_test ( 4 , 0x04030201 , 0xddccbbaa , 0xcdabffee , 0x18171615 ) ;
943+
944+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
945+ // with bytes aa bb cc dd ee ff ab cd at offset 5:
946+ // Expect 01 02 03 04 05 aa bb cc dd ee ff ab cd 16 17 18
947+ // or 0x04030201, 0xccbbaa05, 0xabffeedd, 0x181716cd
948+ run_test ( 5 , 0x04030201 , 0xccbbaa05 , 0xabffeedd , 0x181716cd ) ;
949+
950+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
951+ // with bytes aa bb cc dd ee ff ab cd at offset 6:
952+ // Expect 01 02 03 04 05 06 aa bb cc dd ee ff ab cd 17 18
953+ // or 0x04030201, 0xbbaa0605, 0xffeeddcc, 0x1817cdab
954+ run_test ( 6 , 0x04030201 , 0xbbaa0605 , 0xffeeddcc , 0x1817cdab ) ;
955+
956+ // Overwrite 01 02 03 04 05 06 07 08-11 12 13 14 15 16 17 18
957+ // with bytes aa bb cc dd ee ff ab cd at offset 7:
958+ // Expect 01 02 03 04 05 06 07 aa bb cc dd ee ff ab cd 18
959+ // or 0x04030201, 0xaa070605, 0xeeddccbb, 0x18cdabff
960+ run_test ( 7 , 0x04030201 , 0xaa070605 , 0xeeddccbb , 0x18cdabff ) ;
961+ }
0 commit comments