summaryrefslogtreecommitdiff
path: root/tests/tst-bswap.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-bswap.c
parentd130fe27fa753be02ed76fd9b277aa3c3d928eb9 (diff)
downloadlibmcpu-0.4.0.tar.xz
Version 0.4.00.4.0
Diffstat (limited to 'tests/tst-bswap.c')
-rw-r--r--tests/tst-bswap.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/tests/tst-bswap.c b/tests/tst-bswap.c
new file mode 100644
index 0000000..aff9cbd
--- /dev/null
+++ b/tests/tst-bswap.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <string.h>
+#include <libmcpu.h>
+#include "../utils/mcpu-asm.h"
+
+#define CHECK(c,m) do{if(!(c)){fprintf(stderr,"FAIL: %s\n",m);return 1;}}while(0)
+
+static void
+regop( cpu_operand *o, unsigned bits, unsigned address )
+{
+ memset( o, 0, sizeof( *o ) );
+ o->type = CPU_OPERAND_REGISTER;
+ o->value.reg.bits = bits;
+ o->value.reg.address = address;
+}
+
+static int
+do_bswap( unsigned bits, unsigned d, unsigned s )
+{
+ cpu_instruction i;
+ memset( &i, 0, sizeof( i ) );
+ i.opcode = CPU_OP_BSWAP;
+ regop( &i.operand[0], bits, d );
+ regop( &i.operand[1], bits, s );
+ return( __cpu_exec( &i ) );
+}
+
+int
+main( void )
+{
+ cpu_asm_image im;
+ char err[256];
+ __mpu_UNIT_t *src, *dst;
+ unsigned i;
+ __mpu_uint32_t psw;
+ const char *asrc=
+ ".text\n"
+ "LDI r64@0x00000, 42\n"
+ "BSWAP r64@0x00008, r64@0x00000\n"
+ "BSWAP r64@0x00010, r64@0x00008\n"
+ "HALT\n";
+
+ __cpu_init();
+ CHECK( cpu_assemble_text( asrc, &im, err, sizeof( err ) ) == 0, err );
+ CHECK( im.code_size == 31, "BSWAP machine size is OPCODE16 + 2*REG24" );
+ CHECK( __cpu_code_get_u16( im.code + 13 ) == CPU_OP_BSWAP, "first BSWAP opcode encoded" );
+ CHECK( __cpu_program_set( im.code, im.code_size ) == 0, "set BSWAP program" );
+ CHECK( __cpu_run() == CPU_EXEC_SUCCESS, "run BSWAP program" );
+ CHECK( __cpu_data_get_u64( __cpu_reg_ptr( 64, 0x10 ) ) == 42, "double BSWAP round trip" );
+ cpu_asm_image_free( &im );
+
+ /* r8 is a defined identity operation. */
+ src = __cpu_reg_ptr( 8, 0x100 );
+ dst = __cpu_reg_ptr( 8, 0x101 );
+ *src = 0xa5;
+ *dst = 0;
+ CHECK( do_bswap( 8, 0x101, 0x100 ) == CPU_EXEC_SUCCESS, "BSWAP r8" );
+ CHECK( *dst == 0xa5, "BSWAP r8 identity" );
+
+ /* Arbitrary wide physical registers are reversed byte for byte. */
+ src = __cpu_reg_ptr( 256, 0x200 );
+ dst = __cpu_reg_ptr( 256, 0x220 );
+ for( i = 0; i < 32; i++ ) src[i] = (__mpu_UNIT_t)i;
+ memset( dst, 0, 32 );
+ psw = PSW_CF_MASK | PSW_IF_MASK | PSW_TF_MASK;
+ __cpu_set_psw( psw );
+ CHECK( do_bswap( 256, 0x220, 0x200 ) == CPU_EXEC_SUCCESS, "BSWAP r256" );
+ for( i = 0; i < 32; i++ ) CHECK( dst[i] == (__mpu_UNIT_t)( 31 - i ), "BSWAP r256 byte reversal" );
+ CHECK( __cpu_get_psw() == psw, "BSWAP preserves PSW" );
+
+ /* In-place BSWAP uses source-snapshot semantics. */
+ src = __cpu_reg_ptr( 64, 0x300 );
+ for( i = 0; i < 8; i++ ) src[i] = (__mpu_UNIT_t)( 0x10 + i );
+ CHECK( do_bswap( 64, 0x300, 0x300 ) == CPU_EXEC_SUCCESS, "in-place BSWAP" );
+ for( i = 0; i < 8; i++ ) CHECK( src[i] == (__mpu_UNIT_t)( 0x17 - i ), "in-place BSWAP snapshot result" );
+
+ /* Maximum physical width is supported. */
+ src = __cpu_reg_ptr( 65536, 0x0000 );
+ dst = __cpu_reg_ptr( 65536, 0x2000 );
+ for( i = 0; i < 8192; i++ ) src[i] = (__mpu_UNIT_t)( i & 0xffU );
+ CHECK( do_bswap( 65536, 0x2000, 0x0000 ) == CPU_EXEC_SUCCESS, "BSWAP r65536" );
+ CHECK( dst[0] == src[8191] && dst[8191] == src[0], "BSWAP r65536 endpoints" );
+
+ /* Width mismatch is rejected before modifying destination. */
+ {
+ cpu_instruction x;
+ __mpu_UNIT_t before[8];
+ memset( x.operand, 0, sizeof( x.operand ) );
+ x.opcode = CPU_OP_BSWAP;
+ regop( &x.operand[0], 64, 0x400 );
+ regop( &x.operand[1], 32, 0x408 );
+ memset( __cpu_reg_ptr( 64, 0x400 ), 0x5a, 8 );
+ memcpy( before, __cpu_reg_ptr( 64, 0x400 ), 8 );
+ CHECK( __cpu_exec( &x ) == CPU_EXEC_WIDTH_FAULT, "BSWAP width mismatch" );
+ CHECK( memcmp( before, __cpu_reg_ptr( 64, 0x400 ), 8 ) == 0, "BSWAP width fault atomic" );
+ }
+
+ /* Assembler syntax intentionally uses raw r<bits> views, not c<bits>. */
+ CHECK( cpu_assemble_text( ".text\nBSWAP c64@0x0, c64@0x8\nHALT\n", &im, err, sizeof( err ) ) != 0,
+ "assembler rejects complex spelling for raw BSWAP");
+
+ __cpu_free_context();
+ puts( "libcpu BSWAP regression: PASS" );
+ return( 0 );
+}