From: Julian Seward Date: Fri, 12 May 2006 19:50:44 +0000 (+0000) Subject: Comprehensive tests for bt{s,r,c,}{w,l,q} on amd64. X-Git-Tag: svn/VALGRIND_3_2_0~67 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4950ba18061b1f7d95cf68509a087daebdd9670b;p=thirdparty%2Fvalgrind.git Comprehensive tests for bt{s,r,c,}{w,l,q} on amd64. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5892 --- diff --git a/memcheck/tests/amd64/Makefile.am b/memcheck/tests/amd64/Makefile.am index a62b428ab8..716c9d6981 100644 --- a/memcheck/tests/amd64/Makefile.am +++ b/memcheck/tests/amd64/Makefile.am @@ -8,10 +8,12 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ $(addsuffix .stderr.exp,$(INSN_TESTS)) \ $(addsuffix .stdout.exp,$(INSN_TESTS)) \ $(addsuffix .vgtest,$(INSN_TESTS)) \ + bt_everything.stderr.exp bt_everything.stdout.exp \ + bt_everything.vgtest \ more_x87_fp.stderr.exp more_x87_fp.stdout.exp more_x87_fp.vgtest \ sse_memory.stderr.exp sse_memory.stdout.exp sse_memory.vgtest -check_PROGRAMS = more_x87_fp sse_memory +check_PROGRAMS = bt_everything more_x87_fp sse_memory AM_CPPFLAGS = -I$(top_srcdir)/include AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -g -I$(top_srcdir)/include diff --git a/memcheck/tests/amd64/bt_everything.c b/memcheck/tests/amd64/bt_everything.c new file mode 100644 index 0000000000..3c50181817 --- /dev/null +++ b/memcheck/tests/amd64/bt_everything.c @@ -0,0 +1,498 @@ + +#include +#include +#include + +typedef unsigned long long int ULong; +typedef unsigned int UInt; +typedef unsigned short UShort; +typedef unsigned char UChar; + +typedef signed int Int; +typedef signed short Short; + +typedef signed long int Word; + +/* ------------ MEM, Q ------------ */ + +ULong btsq_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btsq\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" (bitno)); + /* Pretty meaningless to dereference base here, but that's what you + have to do to get a btsl insn which refers to memory starting at + base. */ + return res; +} + +ULong btrq_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btrq\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" (bitno)); + return res; +} + +ULong btcq_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btcq\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" (bitno)); + return res; +} + +ULong btq_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btq\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" (bitno) + : "cc", "memory"); + return res; +} + + +/* ------------ MEM, L ------------ */ + +ULong btsl_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btsl\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Int)bitno)); + /* Pretty meaningless to dereference base here, but that's what you + have to do to get a btsl insn which refers to memory starting at + base. */ + return res; +} + +ULong btrl_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btrl\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Int)bitno)); + return res; +} + +ULong btcl_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btcl\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Int)bitno)); + return res; +} + +ULong btl_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btl\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Int)bitno) + : "cc", "memory"); + return res; +} + + + +/* ------------ MEM, W ------------ */ + +ULong btsw_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btsw\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Short)bitno)); + /* Pretty meaningless to dereference base here, but that's what you + have to do to get a btsl insn which refers to memory starting at + base. */ + return res; +} + +ULong btrw_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btrw\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Short)bitno)); + return res; +} + +ULong btcw_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btcw\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Short)bitno)); + return res; +} + +ULong btw_mem ( char* base, Word bitno ) +{ + UChar res; + __asm__ + __volatile__("btw\t%2, %0\n\t" + "setc\t%1" + : "=m" (*base), "=q" (res) + : "r" ((Short)bitno) + : "cc", "memory"); + return res; +} + + + +/* ------------ REG, Q ------------ */ + +ULong btsq_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btsq\t%2, %%rax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" (bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btrq_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btrq\t%2, %%rax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" (bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btcq_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btcq\t%2, %%rax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" (bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btq_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btq\t%2, %%rax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" (bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + + +/* ------------ REG, L ------------ */ + +ULong btsl_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btsl\t%2, %%eax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Int)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btrl_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btrl\t%2, %%eax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Int)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btcl_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btcl\t%2, %%eax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Int)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btl_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btl\t%2, %%eax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Int)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + + +/* ------------ REG, W ------------ */ + +ULong btsw_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btsw\t%2, %%ax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Short)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btrw_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btrw\t%2, %%ax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Short)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btcw_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btcw\t%2, %%ax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Short)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + +ULong btw_reg ( ULong reg_in, Word bitno, + ULong* reg_out_p ) +{ + UChar res; + ULong reg_out; + __asm__ + __volatile__("movq\t%3, %%rax\n\t" + "btw\t%2, %%ax\n\t" + "movq\t%%rax, %1\n\t" + "setc\t%0" + : "=q" (res), "=r" (reg_out) + : "r" ((Short)bitno), "r" (reg_in) + : "cc", "eax"); + *reg_out_p = reg_out; + return res; +} + + + + + + + +ULong rol1 ( ULong x ) +{ + return (x << 1) | (x >> 63); +} + +int main ( void ) +{ + UInt n, op; + ULong carrydep, c, res; + UChar* block; + ULong reg; + Word bitoff; + + /*------------------------ MEM-L -----------------------*/ + + carrydep = 0; + block = calloc(200,1); + block += 100; + /* Valid bit offsets are -800 .. 799 inclusive. */ + + for (n = 0; n < 10000; n++) { + bitoff = (random() % 1600) - 800; + op = random() % 12; + c = 2; + switch (op) { + case 0: c = btsl_mem(block, bitoff); break; + case 1: c = btrl_mem(block, bitoff); break; + case 2: c = btcl_mem(block, bitoff); break; + case 3: c = btl_mem(block, bitoff); break; + case 4: c = btsq_mem(block, bitoff); break; + case 5: c = btrq_mem(block, bitoff); break; + case 6: c = btcq_mem(block, bitoff); break; + case 7: c = btq_mem(block, bitoff); break; + case 8: c = btsw_mem(block, bitoff); break; + case 9: c = btrw_mem(block, bitoff); break; + case 10: c = btcw_mem(block, bitoff); break; + case 11: c = btw_mem(block, bitoff); break; + default: assert(0); + } + assert(c == 0 || c == 1); + carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep; + } + + /* Compute final result */ + block -= 100; + res = 0; + for (n = 0; n < 200; n++) { + UChar ch = block[n]; + /* printf("%d ", (int)block[n]); */ + res = rol1(res) ^ (UInt)ch; + } + + printf("MEM-L: final res 0x%llx, carrydep 0x%llx\n", res, carrydep); + + /*------------------------ REG-L -----------------------*/ + + carrydep = 0; + reg = 0; + + for (n = 0; n < 1000; n++) { + bitoff = (random() % 100) - 50; + op = random() % 12; + c = 2; + switch (op) { + case 0: c = btsl_reg(reg, bitoff, ®); break; + case 1: c = btrl_reg(reg, bitoff, ®); break; + case 2: c = btcl_reg(reg, bitoff, ®); break; + case 3: c = btl_reg(reg, bitoff, ®); break; + case 4: c = btsq_reg(reg, bitoff, ®); break; + case 5: c = btrq_reg(reg, bitoff, ®); break; + case 6: c = btcq_reg(reg, bitoff, ®); break; + case 7: c = btq_reg(reg, bitoff, ®); break; + case 8: c = btsw_reg(reg, bitoff, ®); break; + case 9: c = btrw_reg(reg, bitoff, ®); break; + case 10: c = btcw_reg(reg, bitoff, ®); break; + case 11: c = btw_reg(reg, bitoff, ®); break; + default: assert(0); + } + assert(c == 0 || c == 1); + carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep; + } + + printf("REG-L: final res 0x%llx, carrydep 0x%llx\n", reg, carrydep); + + block += 100; + + /* Just try one of these at once; more than one can cause a + confusing merging of error messages. */ + //btsl_mem(block, -800); /* should not complain */ + //btsl_mem(block, -801); /* should complain */ + //btsl_mem(block, 799); /* should not complain */ + //btsl_mem(block, 800); /* should complain */ + + block -= 100; + free(block); + + return 0; +} + diff --git a/memcheck/tests/amd64/bt_everything.stderr.exp b/memcheck/tests/amd64/bt_everything.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/amd64/bt_everything.stdout.exp b/memcheck/tests/amd64/bt_everything.stdout.exp new file mode 100644 index 0000000000..f22a0a77cf --- /dev/null +++ b/memcheck/tests/amd64/bt_everything.stdout.exp @@ -0,0 +1,2 @@ +MEM-L: final res 0xbb05dc8f69ba36dc, carrydep 0x818f336625f01277 +REG-L: final res 0xa15f293e, carrydep 0x6082b5e5befc6a40 diff --git a/memcheck/tests/amd64/bt_everything.vgtest b/memcheck/tests/amd64/bt_everything.vgtest new file mode 100644 index 0000000000..844c404bc2 --- /dev/null +++ b/memcheck/tests/amd64/bt_everything.vgtest @@ -0,0 +1,2 @@ +prog: bt_everything +vgopts: -q