summaryrefslogtreecommitdiff
path: root/tests/tst-overlap.c
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-10-09 18:00:15 +0300
committerkx <kx@radix-linux.su>2026-10-09 18:00:15 +0300
commit065da3509019b15dd0e678072e6be629e5330bef (patch)
tree69c934c9e786ac048b4fbe8f4c4c5571661521f4 /tests/tst-overlap.c
parentd130fe27fa753be02ed76fd9b277aa3c3d928eb9 (diff)
downloadlibmcpu-0.4.0.tar.xz
Version 0.4.00.4.0
Diffstat (limited to 'tests/tst-overlap.c')
-rw-r--r--tests/tst-overlap.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/tests/tst-overlap.c b/tests/tst-overlap.c
new file mode 100644
index 0000000..9de9286
--- /dev/null
+++ b/tests/tst-overlap.c
@@ -0,0 +1,104 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <libmcpu.h>
+
+
+static int failures = 0;
+
+#define CHECK(cond,msg) \
+ do { \
+ if( !(cond) ) \
+ { \
+ fprintf( stderr, "FAIL: %s\n", (msg) ); \
+ ++failures; \
+ } \
+ } while( 0 )
+
+
+int
+main( void )
+{
+ __mpu_UNIT_t *r64;
+ __mpu_UNIT_t *r32_0;
+ __mpu_UNIT_t *r32_4;
+ __mpu_UNIT_t *r16_2;
+ __mpu_UNIT_t *r8_3;
+ unsigned int i;
+
+ __cpu_init();
+
+ r64 = __cpu_reg_ptr( 64, 0 );
+ r32_0 = __cpu_reg_ptr( 32, 0 );
+ r32_4 = __cpu_reg_ptr( 32, 4 );
+ r16_2 = __cpu_reg_ptr( 16, 2 );
+ r8_3 = __cpu_reg_ptr( 8, 3 );
+
+ CHECK( r64 != 0, "r64@0 pointer" );
+ CHECK( r32_0 != 0, "r32@0 pointer" );
+ CHECK( r32_4 != 0, "r32@4 pointer" );
+ CHECK( r16_2 != 0, "r16@2 pointer" );
+ CHECK( r8_3 != 0, "r8@3 pointer" );
+
+ CHECK( r64 == r32_0, "r64@0 and r32@0 start at same byte" );
+ CHECK( r32_4 == r64 + 4, "r32@4 overlaps upper four bytes of r64@0" );
+ CHECK( r16_2 == r64 + 2, "r16@2 overlaps bytes 2..3 of r64@0" );
+ CHECK( r8_3 == r64 + 3, "r8@3 overlaps byte 3 of r64@0" );
+
+ for( i = 0; i < 8; ++i ) r64[i] = (__mpu_UNIT_t)( 0x10 + i );
+
+ CHECK( r32_0[0] == 0x10 && r32_0[1] == 0x11 &&
+ r32_0[2] == 0x12 && r32_0[3] == 0x13,
+ "r32@0 sees bytes written through r64@0" );
+
+ CHECK( r32_4[0] == 0x14 && r32_4[1] == 0x15 &&
+ r32_4[2] == 0x16 && r32_4[3] == 0x17,
+ "r32@4 sees bytes written through r64@0" );
+
+ CHECK( r16_2[0] == 0x12 && r16_2[1] == 0x13,
+ "r16@2 sees bytes written through r64@0" );
+
+ *r8_3 = 0xa5;
+ CHECK( r64[3] == 0xa5,
+ "write through r8@3 changes r64@0 storage" );
+ CHECK( r32_0[3] == 0xa5,
+ "write through r8@3 changes r32@0 storage" );
+ CHECK( r16_2[1] == 0xa5,
+ "write through r8@3 changes r16@2 storage" );
+
+ /* Check the same property at a non-zero naturally aligned address. */
+ {
+ __mpu_UNIT_t *r128 = __cpu_reg_ptr( 128, 0x00100 );
+ __mpu_UNIT_t *r32 = __cpu_reg_ptr( 32, 0x0010c );
+ __mpu_UNIT_t *r8 = __cpu_reg_ptr( 8, 0x0010f );
+
+ CHECK( r128 != 0 && r32 != 0 && r8 != 0,
+ "overlap pointers at 0x00100" );
+ CHECK( r32 == r128 + 12,
+ "r32@0x0010c inside r128@0x00100" );
+ CHECK( r8 == r128 + 15,
+ "r8@0x0010f inside r128@0x00100" );
+
+ r128[15] = 0x5a;
+ CHECK( *r8 == 0x5a,
+ "r8 view sees r128 storage" );
+
+ r32[3] = 0xc3;
+ CHECK( r128[15] == 0xc3,
+ "r32 view changes r128 storage" );
+ }
+
+ if( failures != 0 )
+ {
+ fprintf( stderr, "libcpu overlap regression: %d failure(s)\n", failures );
+ return( 1 );
+ }
+
+ printf( "libcpu 0.0.3 overlapping register views regression: PASS\n" );
+ printf( "overlap is byte-storage aliasing and is endian independent\n" );
+
+ return( 0 );
+}