diff options
Diffstat (limited to 'tests/tst-bswap.c')
| -rw-r--r-- | tests/tst-bswap.c | 105 |
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 ); +} |
