mirror of
https://github.com/ioacademy-jikim/debugging
synced 2026-08-31 09:49:38 +00:00
first commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
vbit_test-binary.o: binary.c /usr/include/stdc-predef.h \
|
||||
/usr/include/assert.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h /usr/include/string.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/string.h \
|
||||
/usr/include/i386-linux-gnu/bits/string2.h /usr/include/endian.h \
|
||||
/usr/include/i386-linux-gnu/bits/endian.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h \
|
||||
/usr/include/i386-linux-gnu/bits/string3.h vtest.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
|
||||
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
|
||||
vbits.h /usr/include/stdio.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
/usr/include/string.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/string.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/string2.h:
|
||||
|
||||
/usr/include/endian.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/endian.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/string3.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
@@ -0,0 +1,87 @@
|
||||
vbit_test-irops.o: irops.c /usr/include/stdc-predef.h \
|
||||
/usr/include/stdio.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/stdlib.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-float.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib.h \
|
||||
../../../include/pub_tool_basics.h ../../../VEX/pub/libvex_basictypes.h \
|
||||
vtest.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
|
||||
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h \
|
||||
../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
|
||||
../../../VEX/pub/libvex_ir.h vbits.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
|
||||
/usr/include/stdlib.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-float.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib.h:
|
||||
|
||||
../../../include/pub_tool_basics.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
@@ -0,0 +1,101 @@
|
||||
vbit_test-main.o: main.c /usr/include/stdc-predef.h /usr/include/assert.h \
|
||||
/usr/include/features.h /usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h /usr/include/stdio.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/stdlib.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-float.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib.h /usr/include/string.h \
|
||||
/usr/include/i386-linux-gnu/bits/string.h \
|
||||
/usr/include/i386-linux-gnu/bits/string2.h /usr/include/endian.h \
|
||||
/usr/include/i386-linux-gnu/bits/endian.h \
|
||||
/usr/include/i386-linux-gnu/bits/string3.h ../../../include/valgrind.h \
|
||||
vtest.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
|
||||
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h \
|
||||
../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
|
||||
../../../VEX/pub/libvex_ir.h vbits.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
|
||||
/usr/include/stdlib.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-float.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib.h:
|
||||
|
||||
/usr/include/string.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/string.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/string2.h:
|
||||
|
||||
/usr/include/endian.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/endian.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/string3.h:
|
||||
|
||||
../../../include/valgrind.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
@@ -0,0 +1,73 @@
|
||||
vbit_test-qernary.o: qernary.c /usr/include/stdc-predef.h \
|
||||
/usr/include/assert.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h vtest.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
|
||||
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
|
||||
vbits.h /usr/include/stdio.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
@@ -0,0 +1,73 @@
|
||||
vbit_test-ternary.o: ternary.c /usr/include/stdc-predef.h \
|
||||
/usr/include/assert.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h vtest.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
|
||||
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
|
||||
vbits.h /usr/include/stdio.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
@@ -0,0 +1,73 @@
|
||||
vbit_test-unary.o: unary.c /usr/include/stdc-predef.h \
|
||||
/usr/include/assert.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h vtest.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
|
||||
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
|
||||
vbits.h /usr/include/stdio.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
@@ -0,0 +1,90 @@
|
||||
vbit_test-util.o: util.c /usr/include/stdc-predef.h /usr/include/stdio.h \
|
||||
/usr/include/features.h /usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/stdlib.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-float.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdlib.h /usr/include/assert.h \
|
||||
/usr/include/endian.h /usr/include/i386-linux-gnu/bits/endian.h \
|
||||
/usr/include/inttypes.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
|
||||
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h vtest.h \
|
||||
../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
|
||||
../../../VEX/pub/libvex_ir.h vbits.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
|
||||
/usr/include/stdlib.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib-float.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdlib.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/endian.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/endian.h:
|
||||
|
||||
/usr/include/inttypes.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
@@ -0,0 +1,78 @@
|
||||
vbit_test-valgrind.o: valgrind.c /usr/include/stdc-predef.h \
|
||||
/usr/include/assert.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h ../../../memcheck/memcheck.h \
|
||||
../../../include/valgrind.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h vtest.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
|
||||
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
|
||||
vbits.h /usr/include/stdio.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
../../../memcheck/memcheck.h:
|
||||
|
||||
../../../include/valgrind.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
|
||||
vbits.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
@@ -0,0 +1,80 @@
|
||||
vbit_test-vbits.o: vbits.c /usr/include/stdc-predef.h \
|
||||
/usr/include/stdio.h /usr/include/features.h \
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h \
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h \
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
|
||||
/usr/include/i386-linux-gnu/bits/types.h \
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
|
||||
/usr/include/_G_config.h /usr/include/wchar.h \
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h \
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/assert.h \
|
||||
/usr/include/endian.h /usr/include/i386-linux-gnu/bits/endian.h \
|
||||
/usr/include/inttypes.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
|
||||
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h vbits.h \
|
||||
vtest.h ../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
|
||||
../../../VEX/pub/libvex_ir.h
|
||||
|
||||
/usr/include/stdc-predef.h:
|
||||
|
||||
/usr/include/stdio.h:
|
||||
|
||||
/usr/include/features.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/sys/cdefs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wordsize.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/types.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/typesizes.h:
|
||||
|
||||
/usr/include/libio.h:
|
||||
|
||||
/usr/include/_G_config.h:
|
||||
|
||||
/usr/include/wchar.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/stdio2.h:
|
||||
|
||||
/usr/include/assert.h:
|
||||
|
||||
/usr/include/endian.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/endian.h:
|
||||
|
||||
/usr/include/inttypes.h:
|
||||
|
||||
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
|
||||
|
||||
/usr/include/stdint.h:
|
||||
|
||||
/usr/include/i386-linux-gnu/bits/wchar.h:
|
||||
|
||||
vbits.h:
|
||||
|
||||
vtest.h:
|
||||
|
||||
../../../VEX/pub/libvex.h:
|
||||
|
||||
../../../VEX/pub/libvex_basictypes.h:
|
||||
|
||||
../../../VEX/pub/libvex_ir.h:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
include $(top_srcdir)/Makefile.all.am
|
||||
|
||||
EXTRA_DIST = vbit-test.vgtest vbit-test.stderr.exp
|
||||
|
||||
dist_noinst_SCRIPTS = filter_stderr
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Headers
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
pkginclude_HEADERS =
|
||||
noinst_HEADERS = vtest.h vbits.h
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# vbit_test
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
noinst_PROGRAMS = vbit-test
|
||||
|
||||
if VGCONF_OS_IS_DARWIN
|
||||
noinst_DSYMS = $(noinst_PROGRAMS)
|
||||
endif
|
||||
|
||||
SOURCES = \
|
||||
main.c \
|
||||
unary.c \
|
||||
binary.c \
|
||||
ternary.c \
|
||||
qernary.c \
|
||||
util.c \
|
||||
vbits.c \
|
||||
irops.c \
|
||||
valgrind.c
|
||||
|
||||
vbit_test_SOURCES = $(SOURCES)
|
||||
vbit_test_CPPFLAGS = $(AM_CPPFLAGS_PRI) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/memcheck \
|
||||
-I$(top_srcdir)/VEX/pub
|
||||
vbit_test_CFLAGS = $(AM_CFLAGS_PRI) -std=c99
|
||||
vbit_test_DEPENDENCIES =
|
||||
vbit_test_LDADD =
|
||||
vbit_test_LDFLAGS = $(AM_CFLAGS_PRI) -std=c99 @LIB_UBSAN@
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
vbit-test
|
||||
|
||||
The program tests the effect of an undefined input bit to an IROp on the
|
||||
definedness of the result of that operation. It also checks that only those
|
||||
bits in the result are undefined that we expect to be undefined. That way
|
||||
we can detect false positives (there are bits in the result that are
|
||||
undefined but shouldn't) and false negatives (there are defined bits in
|
||||
the result that should be undefined).
|
||||
|
||||
By design, the tester will always be in-synch with the list of IROps
|
||||
in libvex_ir.h. Addition / removel of IROps will cause a compile or
|
||||
runtime error of the tester and thusly will not go unnoticed.
|
||||
|
||||
|
||||
How it works
|
||||
------------
|
||||
The underlying idea is to
|
||||
(1) use VALGRIND_SET_VBITS to set the V-bits of the operands of an IROp
|
||||
(2) execute that IROp
|
||||
(3) use VALGRIND_GET_VBITS to obtain the V-bits of the result
|
||||
(4) compare the result against our expectation
|
||||
Do that for all IROps and for all input bits of their operands.
|
||||
For all this to work, the tester must run under the auspices of memcheck.
|
||||
|
||||
The key step here is #2. To "execute an IROp" we need to inject some
|
||||
IR into the the superblock. This is accomplished by adding a new "special
|
||||
instruction" that is supported by all frontends. During the decoding step
|
||||
that instruction will be recognised and a suitable piece of IR will be
|
||||
inserted (function vex_inject_ir does just that). What is "suitable" depends
|
||||
on the IROp at hand and its operands. We need to know the addresses of
|
||||
those operands, their types and, trivially, which IROp we want to execute.
|
||||
This information is collected in the IR Injection Control Block (IRICB).
|
||||
To get the IRICB to VEX we use the new client request
|
||||
VG_USERREQ__VEX_INIT_FOR_IRI.
|
||||
|
||||
|
||||
Invocation
|
||||
----------
|
||||
Use vbit-test --help to obtain list of supported command line flags.
|
||||
|
||||
|
||||
Source code overview
|
||||
--------------------
|
||||
main.c
|
||||
Contains the main loop that iterates over all IROps in libvex_ir.h.
|
||||
Depending on the number of operands one of the functions test_unary,
|
||||
test_binary, etc. will be invoked to run all tests for that opreator.
|
||||
|
||||
irops.c
|
||||
List of IROps. For each operator it defines how undefined input bits
|
||||
influence the output (result) and whether the operator is supported on a
|
||||
given architecture.
|
||||
|
||||
util.c
|
||||
Miscellaneous convenience functions. It also includes sizeof_irtype and
|
||||
typeof_primop which were imported from VEX/priv/ir_defs.c.
|
||||
|
||||
unary.c
|
||||
The function test_unary_op is the work horse. It iterates over all input
|
||||
bits of the single operand. For each such bit, the corresponding V-bit will
|
||||
be set to undefined, the IROps is executed and the resulting V-bits will
|
||||
be compared against the expected result.
|
||||
The function check_result_for_unary will check the V-bits for correctness.
|
||||
|
||||
binary.c, ternary.c, qernary.c
|
||||
Like unary.c...
|
||||
|
||||
valgrind.c
|
||||
The main function there is valgrind_execute_test. It will
|
||||
(1) set the V-bits of the operands using the VALGRIND_SET_VBITS mechanism,
|
||||
(2) inject IR into the current IRSB to exacute a single IROp, and
|
||||
(3) obtain the V-bits of the result using the VALGRIND_GET_VBITS mechanism.
|
||||
The addresses of the operands and the result, as well as they V-bit vectors
|
||||
are stored in the test_data_t structure.
|
||||
|
||||
<valgrind>/VEX/priv/ir_inject.c
|
||||
The file provides the function vex_inject_ir which will inject a piece of
|
||||
IR into the current IRSB based on the information provided in the IRICB.
|
||||
That code snippet will perform a single IR operation
|
||||
|
||||
<valgrind>/include/valgrind.h
|
||||
Defines the macro VALGRIND_VEX_INJECT_IR for all architectures.
|
||||
Also defines a new client request VG_USERREQ__VEX_INIT_FOR_IRI.
|
||||
|
||||
|
||||
Adding a new IROp
|
||||
-----------------
|
||||
The following steps are needed
|
||||
(1) Add the operator to irops.c
|
||||
(2) If the operator propagates undefinedness from input to output in a new
|
||||
way:
|
||||
(a) Add a new enumerator to undef_t and document it there.
|
||||
(b) Add a new case in function check_result_for_XYZ depending on the
|
||||
arity of the operator. The code snippet there is supposed to check
|
||||
that the result matches what we expect.
|
||||
|
||||
|
||||
Status
|
||||
------
|
||||
vbit-test has been tested on x86-64, ppc64, s390x, and mips32.
|
||||
There is support for other architectures in valgrind.h and guest_ARCH_toIR.c
|
||||
but it has not been tested.
|
||||
@@ -0,0 +1,9 @@
|
||||
(1) For all operators: Add a test where both operands are completely
|
||||
defined, i.e. all v-bits 0.
|
||||
|
||||
(2) Add support for IROps with vector operands.
|
||||
|
||||
(3) Test floating point operations with various rounding modes.
|
||||
|
||||
(4) Iop_CmpORD32U and friends are not supported (ppc only)
|
||||
|
||||
@@ -0,0 +1,469 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h> // memset
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
/* A convenience function to compute either v1 & ~v2 & val2 or
|
||||
v1 & ~v2 & ~val2 depending on INVERT_VAL2. */
|
||||
static vbits_t
|
||||
and_combine(vbits_t v1, vbits_t v2, value_t val2, int invert_val2)
|
||||
{
|
||||
assert(v1.num_bits == v2.num_bits);
|
||||
|
||||
vbits_t new = { .num_bits = v2.num_bits };
|
||||
|
||||
if (invert_val2) {
|
||||
switch (v2.num_bits) {
|
||||
case 8: val2.u8 = ~val2.u8 & 0xff; break;
|
||||
case 16: val2.u16 = ~val2.u16 & 0xffff; break;
|
||||
case 32: val2.u32 = ~val2.u32; break;
|
||||
case 64: val2.u64 = ~val2.u64; break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
switch (v2.num_bits) {
|
||||
case 8:
|
||||
new.bits.u8 = (v1.bits.u8 & ~v2.bits.u8 & val2.u8) & 0xff;
|
||||
break;
|
||||
case 16:
|
||||
new.bits.u16 = (v1.bits.u16 & ~v2.bits.u16 & val2.u16) & 0xffff;
|
||||
break;
|
||||
case 32:
|
||||
new.bits.u32 = (v1.bits.u32 & ~v2.bits.u32 & val2.u32);
|
||||
break;
|
||||
case 64:
|
||||
new.bits.u64 = (v1.bits.u64 & ~v2.bits.u64 & val2.u64);
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Check the result of a binary operation. */
|
||||
static void
|
||||
check_result_for_binary(const irop_t *op, const test_data_t *data)
|
||||
{
|
||||
const opnd_t *result = &data->result;
|
||||
const opnd_t *opnd1 = &data->opnds[0];
|
||||
const opnd_t *opnd2 = &data->opnds[1];
|
||||
vbits_t expected_vbits;
|
||||
|
||||
/* Only handle those undef-kinds that actually occur. */
|
||||
switch (op->undef_kind) {
|
||||
case UNDEF_NONE:
|
||||
expected_vbits = defined_vbits(result->vbits.num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_ALL:
|
||||
expected_vbits = undefined_vbits(result->vbits.num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_LEFT:
|
||||
// LEFT with respect to the leftmost 1-bit in both operands
|
||||
expected_vbits = left_vbits(or_vbits(opnd1->vbits, opnd2->vbits),
|
||||
result->vbits.num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_SAME:
|
||||
assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
|
||||
assert(opnd1->vbits.num_bits == result->vbits.num_bits);
|
||||
|
||||
// SAME with respect to the 1-bits in both operands
|
||||
expected_vbits = or_vbits(opnd1->vbits, opnd2->vbits);
|
||||
break;
|
||||
|
||||
case UNDEF_CONCAT:
|
||||
assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
|
||||
assert(result->vbits.num_bits == 2 * opnd1->vbits.num_bits);
|
||||
expected_vbits = concat_vbits(opnd1->vbits, opnd2->vbits);
|
||||
break;
|
||||
|
||||
case UNDEF_SHL:
|
||||
/* If any bit in the 2nd operand is undefined, so are all bits
|
||||
of the result. */
|
||||
if (! completely_defined_vbits(opnd2->vbits)) {
|
||||
expected_vbits = undefined_vbits(result->vbits.num_bits);
|
||||
} else {
|
||||
assert(opnd2->vbits.num_bits == 8);
|
||||
unsigned shift_amount = opnd2->value.u8;
|
||||
|
||||
expected_vbits = shl_vbits(opnd1->vbits, shift_amount);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNDEF_SHR:
|
||||
/* If any bit in the 2nd operand is undefined, so are all bits
|
||||
of the result. */
|
||||
if (! completely_defined_vbits(opnd2->vbits)) {
|
||||
expected_vbits = undefined_vbits(result->vbits.num_bits);
|
||||
} else {
|
||||
assert(opnd2->vbits.num_bits == 8);
|
||||
unsigned shift_amount = opnd2->value.u8;
|
||||
|
||||
expected_vbits = shr_vbits(opnd1->vbits, shift_amount);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNDEF_SAR:
|
||||
/* If any bit in the 2nd operand is undefined, so are all bits
|
||||
of the result. */
|
||||
if (! completely_defined_vbits(opnd2->vbits)) {
|
||||
expected_vbits = undefined_vbits(result->vbits.num_bits);
|
||||
} else {
|
||||
assert(opnd2->vbits.num_bits == 8);
|
||||
unsigned shift_amount = opnd2->value.u8;
|
||||
|
||||
expected_vbits = sar_vbits(opnd1->vbits, shift_amount);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNDEF_AND: {
|
||||
/* Let v1, v2 be the V-bits of the 1st and 2nd operand, respectively
|
||||
Let b1, b2 be the actual value of the 1st and 2nd operand, respect.
|
||||
And output bit is undefined (i.e. its V-bit == 1), iff
|
||||
(1) (v1 == 1) && (v2 == 1) OR
|
||||
(2) (v1 == 1) && (v2 == 0 && b2 == 1) OR
|
||||
(3) (v2 == 1) && (v1 == 0 && b1 == 1)
|
||||
*/
|
||||
vbits_t term1, term2, term3;
|
||||
term1 = and_vbits(opnd1->vbits, opnd2->vbits);
|
||||
term2 = and_combine(opnd1->vbits, opnd2->vbits, opnd2->value, 0);
|
||||
term3 = and_combine(opnd2->vbits, opnd1->vbits, opnd1->value, 0);
|
||||
expected_vbits = or_vbits(term1, or_vbits(term2, term3));
|
||||
break;
|
||||
}
|
||||
|
||||
case UNDEF_OR: {
|
||||
/* Let v1, v2 be the V-bits of the 1st and 2nd operand, respectively
|
||||
Let b1, b2 be the actual value of the 1st and 2nd operand, respect.
|
||||
And output bit is undefined (i.e. its V-bit == 1), iff
|
||||
(1) (v1 == 1) && (v2 == 1) OR
|
||||
(2) (v1 == 1) && (v2 == 0 && b2 == 0) OR
|
||||
(3) (v2 == 1) && (v1 == 0 && b1 == 0)
|
||||
*/
|
||||
vbits_t term1, term2, term3;
|
||||
term1 = and_vbits(opnd1->vbits, opnd2->vbits);
|
||||
term2 = and_combine(opnd1->vbits, opnd2->vbits, opnd2->value, 1);
|
||||
term3 = and_combine(opnd2->vbits, opnd1->vbits, opnd1->value, 1);
|
||||
expected_vbits = or_vbits(term1, or_vbits(term2, term3));
|
||||
break;
|
||||
}
|
||||
|
||||
case UNDEF_ORD:
|
||||
/* Set expected_vbits for the Iop_CmpORD category of iops.
|
||||
* If any of the input bits is undefined the least significant
|
||||
* three bits in the result will be set, i.e. 0xe.
|
||||
*/
|
||||
expected_vbits = cmpord_vbits(opnd1->vbits.num_bits,
|
||||
opnd2->vbits.num_bits);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
if (! equal_vbits(result->vbits, expected_vbits))
|
||||
complain(op, data, expected_vbits);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
test_shift(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, i;
|
||||
opnd_t *opnds = data->opnds;
|
||||
int tests_done = 0;
|
||||
|
||||
/* When testing the 1st operand's undefinedness propagation,
|
||||
do so with all possible shift amnounts */
|
||||
for (unsigned amount = 0; amount < bitsof_irtype(opnds[0].type); ++amount) {
|
||||
opnds[1].value.u8 = amount;
|
||||
|
||||
// 1st (left) operand
|
||||
num_input_bits = bitsof_irtype(opnds[0].type);
|
||||
|
||||
for (i = 0; i < num_input_bits; ++i) {
|
||||
opnds[0].vbits = onehot_vbits(i, bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
}
|
||||
|
||||
// 2nd (right) operand
|
||||
|
||||
/* If the operand is an immediate value, there are no v-bits to set. */
|
||||
if (op->shift_amount_is_immediate) return tests_done;
|
||||
|
||||
num_input_bits = bitsof_irtype(opnds[1].type);
|
||||
|
||||
for (i = 0; i < num_input_bits; ++i) {
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = onehot_vbits(i, bitsof_irtype(opnds[1].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
|
||||
tests_done++;
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
|
||||
|
||||
static value_t
|
||||
all_bits_zero_value(unsigned num_bits)
|
||||
{
|
||||
value_t val;
|
||||
|
||||
switch (num_bits) {
|
||||
case 8: val.u8 = 0; break;
|
||||
case 16: val.u16 = 0; break;
|
||||
case 32: val.u32 = 0; break;
|
||||
case 64: val.u64 = 0; break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static value_t
|
||||
all_bits_one_value(unsigned num_bits)
|
||||
{
|
||||
value_t val;
|
||||
|
||||
switch (num_bits) {
|
||||
case 8: val.u8 = 0xff; break;
|
||||
case 16: val.u16 = 0xffff; break;
|
||||
case 32: val.u32 = ~0u; break;
|
||||
case 64: val.u64 = ~0ull; break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
test_and(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, bitpos;
|
||||
opnd_t *opnds = data->opnds;
|
||||
int tests_done = 0;
|
||||
|
||||
/* Undefinedness does not propagate if the other operand is 0.
|
||||
Use an all-bits-zero operand and test the other operand in
|
||||
the usual way (one bit undefined at a time). */
|
||||
|
||||
// 1st (left) operand variable, 2nd operand all-bits-zero
|
||||
num_input_bits = bitsof_irtype(opnds[0].type);
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[1].value = all_bits_zero_value(bitsof_irtype(opnds[1].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
|
||||
// 2nd (right) operand variable, 1st operand all-bits-zero
|
||||
num_input_bits = bitsof_irtype(opnds[1].type);
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[0].value = all_bits_zero_value(bitsof_irtype(opnds[0].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
|
||||
/* Undefinedness propagates if the other operand is 1.
|
||||
Use an all-bits-one operand and test the other operand in
|
||||
the usual way (one bit undefined at a time). */
|
||||
|
||||
// 1st (left) operand variable, 2nd operand all-bits-one
|
||||
num_input_bits = bitsof_irtype(opnds[0].type);
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[1].value = all_bits_one_value(bitsof_irtype(opnds[1].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
|
||||
// 2nd (right) operand variable, 1st operand all-bits-one
|
||||
num_input_bits = bitsof_irtype(opnds[1].type);
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[0].value = all_bits_one_value(bitsof_irtype(opnds[0].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
test_or(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, bitpos;
|
||||
opnd_t *opnds = data->opnds;
|
||||
int tests_done = 0;
|
||||
|
||||
/* Undefinedness does not propagate if the other operand is 1.
|
||||
Use an all-bits-one operand and test the other operand in
|
||||
the usual way (one bit undefined at a time). */
|
||||
|
||||
// 1st (left) operand variable, 2nd operand all-bits-one
|
||||
num_input_bits = bitsof_irtype(opnds[0].type);
|
||||
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[1].value = all_bits_one_value(bitsof_irtype(opnds[1].type));
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
|
||||
// 2nd (right) operand variable, 1st operand all-bits-one
|
||||
num_input_bits = bitsof_irtype(opnds[1].type);
|
||||
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[0].value = all_bits_one_value(bitsof_irtype(opnds[0].type));
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
|
||||
/* Undefinedness propagates if the other operand is 0.
|
||||
Use an all-bits-zero operand and test the other operand in
|
||||
the usual way (one bit undefined at a time). */
|
||||
|
||||
// 1st (left) operand variable, 2nd operand all-bits-zero
|
||||
num_input_bits = bitsof_irtype(opnds[0].type);
|
||||
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[1].value = all_bits_zero_value(bitsof_irtype(opnds[1].type));
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
|
||||
// 2nd (right) operand variable, 1st operand all-bits-zero
|
||||
num_input_bits = bitsof_irtype(opnds[1].type);
|
||||
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[0].value = all_bits_zero_value(bitsof_irtype(opnds[0].type));
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_binary_op(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, i, bitpos;
|
||||
opnd_t *opnds = data->opnds;
|
||||
int tests_done = 0;
|
||||
|
||||
/* Handle special cases upfront */
|
||||
switch (op->undef_kind) {
|
||||
case UNDEF_SHL:
|
||||
case UNDEF_SHR:
|
||||
case UNDEF_SAR:
|
||||
return test_shift(op, data);
|
||||
|
||||
case UNDEF_AND:
|
||||
return test_and(op, data);
|
||||
|
||||
case UNDEF_OR:
|
||||
return test_or(op, data);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* For each operand, set a single bit to undefined and observe how
|
||||
that propagates to the output. Do this for all bits in each
|
||||
operand. */
|
||||
for (i = 0; i < 2; ++i) {
|
||||
|
||||
/* If this is a shift op that requires an immediate shift amount,
|
||||
do not iterate the v-bits of the 2nd operand */
|
||||
if (i == 1 && op->shift_amount_is_immediate) break;
|
||||
|
||||
num_input_bits = bitsof_irtype(opnds[i].type);
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
|
||||
/* Set the value of the 2nd operand to something != 0. So division
|
||||
won't crash. */
|
||||
memset(&opnds[1].value, 0xff, sizeof opnds[1].value);
|
||||
|
||||
/* For immediate shift amounts choose a value of '1'. That should
|
||||
not cause a problem. */
|
||||
if (op->shift_amount_is_immediate)
|
||||
opnds[1].value.u8 = 1;
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_binary(op, data);
|
||||
|
||||
tests_done++;
|
||||
}
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#! /bin/sh
|
||||
|
||||
../filter_stderr "$@"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <assert.h> // assert
|
||||
#include <stdio.h> // printf
|
||||
#include <stdlib.h> // malloc
|
||||
#include <string.h> // memset
|
||||
#include "valgrind.h" // RUNNING_ON_VALGRIND
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
static test_data_t *
|
||||
new_test_data(const irop_t *op)
|
||||
{
|
||||
test_data_t *data = malloc(sizeof *data);
|
||||
|
||||
memset(data, 0x0, sizeof *data); // initialise
|
||||
|
||||
/* Obtain the operand types and set them */
|
||||
IRType t_dst, t1, t2, t3, t4;
|
||||
|
||||
typeof_primop(op->op, &t_dst, &t1, &t2, &t3, &t4);
|
||||
assert(t_dst != Ity_INVALID);
|
||||
assert(t1 != Ity_INVALID);
|
||||
|
||||
data->result.type = t_dst;
|
||||
if (is_floating_point_op_with_rounding_mode(op->op)) {
|
||||
data->opnds[0].type = t2;
|
||||
data->opnds[1].type = t3;
|
||||
data->opnds[2].type = t4;
|
||||
data->opnds[3].type = Ity_INVALID;
|
||||
} else {
|
||||
data->opnds[0].type = t1;
|
||||
data->opnds[1].type = t2;
|
||||
data->opnds[2].type = t3;
|
||||
data->opnds[3].type = t4;
|
||||
}
|
||||
|
||||
/* Set the rounding mode if the operation requires one.
|
||||
FIXME: We should iterate over all rounding modes. For that need
|
||||
FIXME: to distinguish between binary and decimal floating point */
|
||||
if (is_floating_point_op_with_rounding_mode(op->op)) {
|
||||
// for now just pick one
|
||||
data->rounding_mode = Irrm_NEAREST; // same as Irrm_DFP_NEAREST
|
||||
} else {
|
||||
data->rounding_mode = NO_ROUNDING_MODE;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
|
||||
/* Certain IROps require special handling. */
|
||||
static void
|
||||
fixup_irops(void)
|
||||
{
|
||||
#ifdef __powerpc__
|
||||
get_irop(Iop_ShlD64)->shift_amount_is_immediate = 1;
|
||||
get_irop(Iop_ShrD64)->shift_amount_is_immediate = 1;
|
||||
get_irop(Iop_ShlD128)->shift_amount_is_immediate = 1;
|
||||
get_irop(Iop_ShrD128)->shift_amount_is_immediate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
assert(sizeof(long long) == 8);
|
||||
int num_unary_tests = 0, num_binary_tests = 0;
|
||||
int num_ternary_tests = 0, num_qernary_tests = 0;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "-v") == 0) ++verbose;
|
||||
else if (strcmp(argv[i], "--help") == 0) {
|
||||
printf("\nvbit-test [ -v | --help ]\n");
|
||||
printf("\n\t-v verbose mode; show number of 1, 2, 3 and 4 operand tests\n");
|
||||
printf("\n\t-v -v verbose mode; shows IROps being tested\n");
|
||||
printf("\n\t-v -v -v verbose mode, extreme edition\n\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("%s ? Nothing happens.\n", argv[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (! RUNNING_ON_VALGRIND) {
|
||||
fprintf(stderr, "*** This program needs to run under memcheck.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
setbuf(stdout, NULL); // make stdout unbuffered
|
||||
|
||||
fixup_irops(); // determine need for special handling
|
||||
|
||||
// Iterate over all primops
|
||||
IROp first = Iop_INVALID + 1;
|
||||
IROp last = Iop_LAST;
|
||||
IROp opkind;
|
||||
|
||||
if (0) { // overwrite for debugging
|
||||
first = Iop_CasCmpEQ8; last = first + 1;
|
||||
}
|
||||
|
||||
// Iterate over all IROps in the enum type. That is the only way to
|
||||
// make sure the operator is tested on at least one platform.
|
||||
|
||||
// Loop assumes no holes in the enumerator values
|
||||
for (opkind = first; opkind < last; ++opkind) {
|
||||
|
||||
const irop_t *op = get_irop(opkind);
|
||||
if (op == NULL) continue;
|
||||
|
||||
test_data_t *data = new_test_data(op);
|
||||
|
||||
if (op->undef_kind == UNDEF_UNKNOWN) {
|
||||
fprintf(stderr, "...skipping %s; unknown undef propagation\n",
|
||||
op->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose > 1) printf("Testing operator %s\n", op->name);
|
||||
|
||||
IRICB iricb = new_iricb(op, data);
|
||||
|
||||
valgrind_vex_init_for_iri(&iricb);
|
||||
|
||||
switch (iricb.num_operands) {
|
||||
case 1:
|
||||
num_unary_tests += test_unary_op(op, data);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
num_binary_tests += test_binary_op(op, data);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
num_ternary_tests += test_ternary_op(op, data);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
num_qernary_tests += test_qernary_op(op, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("operator not handled");
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("\nvbit-test ran %d unary, %d binary, %d ternary and %d qernary tests.\n",
|
||||
num_unary_tests, num_binary_tests, num_ternary_tests,
|
||||
num_qernary_tests);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <assert.h>
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
/* Check the result of a quarternary operation. */
|
||||
static void
|
||||
check_result_for_qernary(const irop_t *op, const test_data_t *data)
|
||||
{
|
||||
const opnd_t *result = &data->result;
|
||||
const opnd_t *opnd1 = &data->opnds[0];
|
||||
const opnd_t *opnd2 = &data->opnds[1];
|
||||
const opnd_t *opnd3 = &data->opnds[2];
|
||||
const opnd_t *opnd4 = &data->opnds[3];
|
||||
vbits_t expected_vbits;
|
||||
|
||||
/* Only handle those undef-kinds that actually occur. */
|
||||
switch (op->undef_kind) {
|
||||
case UNDEF_ALL:
|
||||
expected_vbits = undefined_vbits(result->vbits.num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_SAME:
|
||||
// SAME with respect to the 1-bits in all operands
|
||||
expected_vbits = or_vbits(or_vbits(or_vbits(opnd1->vbits, opnd2->vbits),
|
||||
opnd3->vbits), opnd4->vbits);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
if (! equal_vbits(result->vbits, expected_vbits))
|
||||
complain(op, data, expected_vbits);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_qernary_op(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, i, bitpos;
|
||||
opnd_t *opnds = data->opnds;
|
||||
int tests_done = 0;
|
||||
|
||||
/* For each operand, set a single bit to undefined and observe how
|
||||
that propagates to the output. Do this for all bits in each
|
||||
operand. */
|
||||
for (i = 0; i < 4; ++i) {
|
||||
num_input_bits = bitsof_irtype(opnds[i].type);
|
||||
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[2].vbits = defined_vbits(bitsof_irtype(opnds[2].type));
|
||||
opnds[3].vbits = defined_vbits(bitsof_irtype(opnds[3].type));
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_qernary(op, data);
|
||||
|
||||
tests_done++;
|
||||
}
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <assert.h>
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
/* Check the result of a ternary operation. */
|
||||
static void
|
||||
check_result_for_ternary(const irop_t *op, const test_data_t *data)
|
||||
{
|
||||
const opnd_t *result = &data->result;
|
||||
const opnd_t *opnd1 = &data->opnds[0];
|
||||
const opnd_t *opnd2 = &data->opnds[1];
|
||||
const opnd_t *opnd3 = &data->opnds[2];
|
||||
vbits_t expected_vbits;
|
||||
|
||||
/* Only handle those undef-kinds that actually occur. */
|
||||
switch (op->undef_kind) {
|
||||
case UNDEF_ALL:
|
||||
expected_vbits = undefined_vbits(result->vbits.num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_SAME:
|
||||
// SAME with respect to the 1-bits in all operands
|
||||
expected_vbits = or_vbits(or_vbits(opnd1->vbits, opnd2->vbits),
|
||||
opnd3->vbits);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
if (! equal_vbits(result->vbits, expected_vbits))
|
||||
complain(op, data, expected_vbits);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_ternary_op(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, i, bitpos;
|
||||
opnd_t *opnds = data->opnds;
|
||||
int tests_done = 0;
|
||||
|
||||
/* For each operand, set a single bit to undefined and observe how
|
||||
that propagates to the output. Do this for all bits in each
|
||||
operand. */
|
||||
for (i = 0; i < 3; ++i) {
|
||||
num_input_bits = bitsof_irtype(opnds[i].type);
|
||||
|
||||
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
|
||||
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
|
||||
opnds[2].vbits = defined_vbits(bitsof_irtype(opnds[2].type));
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_ternary(op, data);
|
||||
|
||||
tests_done++;
|
||||
}
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <assert.h>
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
/* Check the result of a unary operation. */
|
||||
static void
|
||||
check_result_for_unary(const irop_t *op, const test_data_t *data)
|
||||
{
|
||||
const opnd_t *result = &data->result;
|
||||
const opnd_t *opnd = &data->opnds[0];
|
||||
unsigned num_bits = result->vbits.num_bits;
|
||||
vbits_t expected_vbits;
|
||||
|
||||
/* Only handle those undef-kinds that actually occur. */
|
||||
switch (op->undef_kind) {
|
||||
case UNDEF_ALL:
|
||||
expected_vbits = undefined_vbits(num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_SAME:
|
||||
expected_vbits = opnd->vbits;
|
||||
break;
|
||||
|
||||
case UNDEF_TRUNC:
|
||||
expected_vbits = truncate_vbits(opnd->vbits, num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_LEFT:
|
||||
expected_vbits = left_vbits(opnd->vbits, num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_UPPER:
|
||||
assert(num_bits * 2 == opnd->vbits.num_bits);
|
||||
expected_vbits = upper_vbits(opnd->vbits);
|
||||
break;
|
||||
|
||||
case UNDEF_SEXT:
|
||||
expected_vbits = sextend_vbits(opnd->vbits, num_bits);
|
||||
break;
|
||||
|
||||
case UNDEF_ZEXT:
|
||||
expected_vbits = zextend_vbits(opnd->vbits, num_bits);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
if (! equal_vbits(result->vbits, expected_vbits))
|
||||
complain(op, data, expected_vbits);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_unary_op(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned num_input_bits, bitpos;
|
||||
int tests_done = 0;
|
||||
|
||||
num_input_bits = bitsof_irtype(data->opnds[0].type);
|
||||
|
||||
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
|
||||
data->opnds[0].vbits = onehot_vbits(bitpos, num_input_bits);
|
||||
|
||||
valgrind_execute_test(op, data);
|
||||
|
||||
check_result_for_unary(op, data);
|
||||
tests_done++;
|
||||
}
|
||||
return tests_done;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <assert.h>
|
||||
#include "memcheck.h" // VALGRIND_SET_VBITS
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
/* Return a completely initialised control block */
|
||||
IRICB
|
||||
new_iricb(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
IRICB cb;
|
||||
|
||||
cb.op = op->op;
|
||||
cb.result = (HWord)&data->result.value;
|
||||
cb.opnd1 = (HWord)&data->opnds[0].value;
|
||||
cb.opnd2 = (HWord)&data->opnds[1].value;
|
||||
cb.opnd3 = (HWord)&data->opnds[2].value;
|
||||
cb.opnd4 = (HWord)&data->opnds[3].value;
|
||||
cb.t_result = data->result.type;
|
||||
cb.t_opnd1 = data->opnds[0].type;
|
||||
cb.t_opnd2 = data->opnds[1].type;
|
||||
cb.t_opnd3 = data->opnds[2].type;
|
||||
cb.t_opnd4 = data->opnds[3].type;
|
||||
|
||||
cb.rounding_mode = data->rounding_mode;
|
||||
|
||||
cb.num_operands = get_num_operands(op->op);
|
||||
|
||||
cb.shift_amount_is_immediate = op->shift_amount_is_immediate;
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
|
||||
/* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store
|
||||
such a value from/to a 4-byte container. It uses 32to1 and 1Uto32,
|
||||
respectively. */
|
||||
static void
|
||||
valgrind_set_vbits(opnd_t *opnd)
|
||||
{
|
||||
unsigned rc, num_bytes;
|
||||
|
||||
/* 1-bit wide values cannot be read. So we read a 4 bytes here */
|
||||
num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
|
||||
rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
|
||||
assert(rc == 1);
|
||||
|
||||
// Make sure the v-bits were set correctly
|
||||
vbits_t actual = { .num_bits = opnd->vbits.num_bits };
|
||||
rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes);
|
||||
assert(rc == 1);
|
||||
|
||||
assert(equal_vbits(opnd->vbits, actual));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
valgrind_get_vbits(opnd_t *opnd)
|
||||
{
|
||||
unsigned rc, num_bytes;
|
||||
|
||||
/* 1-bit wide values cannot be stored. So we store them by writing a
|
||||
single byte */
|
||||
num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
|
||||
opnd->vbits.num_bits = bitsof_irtype(opnd->type);
|
||||
rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
|
||||
assert(rc == 1);
|
||||
}
|
||||
|
||||
|
||||
/* Insert a client request that will initialize VEX for IR injection */
|
||||
void
|
||||
valgrind_vex_init_for_iri(IRICB *cb)
|
||||
{
|
||||
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI, cb, 0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
/* Insert a special opcode that will cause VEX to inject an IR stmt based
|
||||
on the information passed in the IRICB (in valgrind_vex_init_for_iri). */
|
||||
static void
|
||||
valgrind_vex_inject_ir(void)
|
||||
{
|
||||
VALGRIND_VEX_INJECT_IR();
|
||||
}
|
||||
|
||||
|
||||
/* Execute the test under valgrind. Well, yes, we're not really executing
|
||||
it here, just preparing for it... */
|
||||
void
|
||||
valgrind_execute_test(const irop_t *op, test_data_t *data)
|
||||
{
|
||||
unsigned i, num_operands;
|
||||
|
||||
if (verbose > 2) printf("---------- Running a test\n");
|
||||
num_operands = get_num_operands(op->op);
|
||||
|
||||
for (i = 0; i < num_operands; ++i) {
|
||||
valgrind_set_vbits(&data->opnds[i]);
|
||||
if (verbose > 2) {
|
||||
printf("opnd #%u: ", i);
|
||||
print_opnd(stdout, &data->opnds[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
if (verbose > 2)
|
||||
if (data->rounding_mode != NO_ROUNDING_MODE)
|
||||
printf("rounding mode %u\n", data->rounding_mode);
|
||||
|
||||
valgrind_vex_inject_ir();
|
||||
valgrind_get_vbits(&data->result);
|
||||
if (verbose > 2) {
|
||||
printf("result: ");
|
||||
print_opnd(stdout, &data->result);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
prog: vbit-test
|
||||
vgopts: -q
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,778 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#include <stdio.h> // fprintf
|
||||
#include <assert.h> // assert
|
||||
#if defined(__APPLE__)
|
||||
#include <machine/endian.h>
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#elif defined(__sun)
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
# if defined(_LITTLE_ENDIAN)
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
# else
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
# endif
|
||||
#else
|
||||
#include <endian.h>
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include "vbits.h"
|
||||
#include "vtest.h"
|
||||
|
||||
|
||||
/* Return the bits of V if they fit into 64-bit. If V has fewer than
|
||||
64 bits, the bit pattern is zero-extended to the left. */
|
||||
static uint64_t
|
||||
get_bits64(vbits_t v)
|
||||
{
|
||||
switch (v.num_bits) {
|
||||
case 1: return v.bits.u32;
|
||||
case 8: return v.bits.u8;
|
||||
case 16: return v.bits.u16;
|
||||
case 32: return v.bits.u32;
|
||||
case 64: return v.bits.u64;
|
||||
case 128:
|
||||
case 256:
|
||||
/* fall through */
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_vbits(FILE *fp, vbits_t v)
|
||||
{
|
||||
switch (v.num_bits) {
|
||||
case 1: fprintf(fp, "%08x", v.bits.u32); break;
|
||||
case 8: fprintf(fp, "%02x", v.bits.u8); break;
|
||||
case 16: fprintf(fp, "%04x", v.bits.u16); break;
|
||||
case 32: fprintf(fp, "%08x", v.bits.u32); break;
|
||||
case 64: fprintf(fp, "%016"PRIx64, v.bits.u64); break;
|
||||
case 128:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u128[1]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u128[0]);
|
||||
} else {
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u128[0]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u128[1]);
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[3]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[2]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[1]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[0]);
|
||||
} else {
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[0]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[1]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[2]);
|
||||
fprintf(fp, "%016"PRIx64, v.bits.u256[3]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return a value where all bits are set to undefined. */
|
||||
vbits_t
|
||||
undefined_vbits(unsigned num_bits)
|
||||
{
|
||||
vbits_t new = { .num_bits = num_bits };
|
||||
|
||||
switch (num_bits) {
|
||||
case 1: new.bits.u32 = 0x01; break;
|
||||
case 8: new.bits.u8 = 0xff; break;
|
||||
case 16: new.bits.u16 = 0xffff; break;
|
||||
case 32: new.bits.u32 = ~0; break;
|
||||
case 64: new.bits.u64 = ~0ull; break;
|
||||
case 128: new.bits.u128[0] = ~0ull;
|
||||
new.bits.u128[1] = ~0ull;
|
||||
break;
|
||||
case 256: new.bits.u256[0] = ~0ull;
|
||||
new.bits.u256[1] = ~0ull;
|
||||
new.bits.u256[2] = ~0ull;
|
||||
new.bits.u256[3] = ~0ull;
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/* Return a value where all bits are set to defined. */
|
||||
vbits_t
|
||||
defined_vbits(unsigned num_bits)
|
||||
{
|
||||
vbits_t new = { .num_bits = num_bits };
|
||||
|
||||
switch (num_bits) {
|
||||
case 1: new.bits.u32 = 0x0; break;
|
||||
case 8: new.bits.u8 = 0x0; break;
|
||||
case 16: new.bits.u16 = 0x0; break;
|
||||
case 32: new.bits.u32 = 0x0; break;
|
||||
case 64: new.bits.u64 = 0x0; break;
|
||||
case 128: new.bits.u128[0] = 0x0;
|
||||
new.bits.u128[1] = 0x0;
|
||||
break;
|
||||
case 256: new.bits.u256[0] = 0x0;
|
||||
new.bits.u256[1] = 0x0;
|
||||
new.bits.u256[2] = 0x0;
|
||||
new.bits.u256[3] = 0x0;
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/* Return 1, if equal. */
|
||||
int
|
||||
equal_vbits(vbits_t v1, vbits_t v2)
|
||||
{
|
||||
assert(v1.num_bits == v2.num_bits);
|
||||
|
||||
switch (v1.num_bits) {
|
||||
case 1: return v1.bits.u32 == v2.bits.u32;
|
||||
case 8: return v1.bits.u8 == v2.bits.u8;
|
||||
case 16: return v1.bits.u16 == v2.bits.u16;
|
||||
case 32: return v1.bits.u32 == v2.bits.u32;
|
||||
case 64: return v1.bits.u64 == v2.bits.u64;
|
||||
case 128: return v1.bits.u128[0] == v2.bits.u128[0] &&
|
||||
v1.bits.u128[1] == v2.bits.u128[1];
|
||||
case 256: return v1.bits.u256[0] == v2.bits.u256[0] &&
|
||||
v1.bits.u256[1] == v2.bits.u256[1] &&
|
||||
v1.bits.u256[2] == v2.bits.u256[2] &&
|
||||
v1.bits.u256[3] == v2.bits.u256[3];
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Truncate the bit pattern in V1 to NUM_BITS bits */
|
||||
vbits_t
|
||||
truncate_vbits(vbits_t v, unsigned num_bits)
|
||||
{
|
||||
assert(num_bits <= v.num_bits);
|
||||
|
||||
if (num_bits == v.num_bits) return v;
|
||||
|
||||
vbits_t new = { .num_bits = num_bits };
|
||||
|
||||
if (num_bits <= 64) {
|
||||
uint64_t bits;
|
||||
|
||||
if (v.num_bits <= 64)
|
||||
bits = get_bits64(v);
|
||||
else if (v.num_bits == 128)
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
bits = v.bits.u128[0];
|
||||
else
|
||||
bits = v.bits.u128[1];
|
||||
else if (v.num_bits == 256)
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
bits = v.bits.u256[0];
|
||||
else
|
||||
bits = v.bits.u256[3];
|
||||
else
|
||||
panic(__func__);
|
||||
|
||||
switch (num_bits) {
|
||||
case 1: new.bits.u32 = bits & 0x01; break;
|
||||
case 8: new.bits.u8 = bits & 0xff; break;
|
||||
case 16: new.bits.u16 = bits & 0xffff; break;
|
||||
case 32: new.bits.u32 = bits & ~0u; break;
|
||||
case 64: new.bits.u64 = bits & ~0ll; break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
if (num_bits == 128) {
|
||||
assert(v.num_bits == 256);
|
||||
/* From 256 bits to 128 */
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u128[0] = v.bits.u256[0];
|
||||
new.bits.u128[1] = v.bits.u256[1];
|
||||
} else {
|
||||
new.bits.u128[0] = v.bits.u256[2];
|
||||
new.bits.u128[1] = v.bits.u256[3];
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Cannot truncate to 256 bits from something larger */
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
|
||||
/* Helper function to compute left_vbits */
|
||||
static uint64_t
|
||||
left64(uint64_t x)
|
||||
{
|
||||
// left(x) = x | -x
|
||||
return x | (~x + 1);
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
left_vbits(vbits_t v, unsigned num_bits)
|
||||
{
|
||||
assert(num_bits >= v.num_bits);
|
||||
|
||||
vbits_t new = { .num_bits = num_bits };
|
||||
|
||||
if (v.num_bits <= 64) {
|
||||
uint64_t bits = left64(get_bits64(v));
|
||||
|
||||
switch (num_bits) {
|
||||
case 8: new.bits.u8 = bits & 0xff; break;
|
||||
case 16: new.bits.u16 = bits & 0xffff; break;
|
||||
case 32: new.bits.u32 = bits & ~0u; break;
|
||||
case 64: new.bits.u64 = bits & ~0ll; break;
|
||||
case 128:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u128[0] = bits;
|
||||
if (bits & (1ull << 63)) { // MSB is set
|
||||
new.bits.u128[1] = ~0ull;
|
||||
} else {
|
||||
new.bits.u128[1] = 0;
|
||||
}
|
||||
} else {
|
||||
new.bits.u128[1] = bits;
|
||||
if (bits & (1ull << 63)) { // MSB is set
|
||||
new.bits.u128[0] = ~0ull;
|
||||
} else {
|
||||
new.bits.u128[0] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u256[0] = bits;
|
||||
if (bits & (1ull << 63)) { // MSB is set
|
||||
new.bits.u256[1] = ~0ull;
|
||||
new.bits.u256[2] = ~0ull;
|
||||
new.bits.u256[3] = ~0ull;
|
||||
} else {
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
}
|
||||
} else {
|
||||
new.bits.u256[3] = bits;
|
||||
if (bits & (1ull << 63)) { // MSB is set
|
||||
new.bits.u256[0] = ~0ull;
|
||||
new.bits.u256[1] = ~0ull;
|
||||
new.bits.u256[2] = ~0ull;
|
||||
} else {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
if (v.num_bits == 128) {
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
if (v.bits.u128[1] != 0) {
|
||||
new.bits.u128[0] = v.bits.u128[0];
|
||||
new.bits.u128[1] = left64(v.bits.u128[1]);
|
||||
} else {
|
||||
new.bits.u128[0] = left64(v.bits.u128[0]);
|
||||
if (new.bits.u128[0] & (1ull << 63)) { // MSB is set
|
||||
new.bits.u128[1] = ~0ull;
|
||||
} else {
|
||||
new.bits.u128[1] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (v.bits.u128[0] != 0) {
|
||||
new.bits.u128[0] = left64(v.bits.u128[0]);
|
||||
new.bits.u128[1] = v.bits.u128[1];
|
||||
} else {
|
||||
new.bits.u128[1] = left64(v.bits.u128[1]);
|
||||
if (new.bits.u128[1] & (1ull << 63)) { // MSB is set
|
||||
new.bits.u128[0] = ~0ull;
|
||||
} else {
|
||||
new.bits.u128[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_bits == 128) return new;
|
||||
|
||||
assert(num_bits == 256);
|
||||
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
uint64_t b1 = new.bits.u128[1];
|
||||
uint64_t b0 = new.bits.u128[0];
|
||||
|
||||
new.bits.u256[0] = b0;
|
||||
new.bits.u256[1] = b1;
|
||||
|
||||
if (new.bits.u256[1] & (1ull << 63)) { // MSB is set
|
||||
new.bits.u256[2] = ~0ull;
|
||||
new.bits.u256[3] = ~0ull;
|
||||
} else {
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
}
|
||||
} else {
|
||||
uint64_t b1 = new.bits.u128[0];
|
||||
uint64_t b0 = new.bits.u128[1];
|
||||
|
||||
new.bits.u256[2] = b0;
|
||||
new.bits.u256[3] = b1;
|
||||
|
||||
if (new.bits.u256[2] & (1ull << 63)) { // MSB is set
|
||||
new.bits.u256[0] = ~0ull;
|
||||
new.bits.u256[1] = ~0ull;
|
||||
} else {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
}
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
or_vbits(vbits_t v1, vbits_t v2)
|
||||
{
|
||||
assert(v1.num_bits == v2.num_bits);
|
||||
|
||||
vbits_t new = { .num_bits = v1.num_bits };
|
||||
|
||||
switch (v1.num_bits) {
|
||||
case 8: new.bits.u8 = v1.bits.u8 | v2.bits.u8; break;
|
||||
case 16: new.bits.u16 = v1.bits.u16 | v2.bits.u16; break;
|
||||
case 32: new.bits.u32 = v1.bits.u32 | v2.bits.u32; break;
|
||||
case 64: new.bits.u64 = v1.bits.u64 | v2.bits.u64; break;
|
||||
case 128: new.bits.u128[0] = v1.bits.u128[0] | v2.bits.u128[0];
|
||||
new.bits.u128[1] = v1.bits.u128[1] | v2.bits.u128[1];
|
||||
break;
|
||||
case 256: new.bits.u256[0] = v1.bits.u256[0] | v2.bits.u256[0];
|
||||
new.bits.u256[1] = v1.bits.u256[1] | v2.bits.u256[1];
|
||||
new.bits.u256[2] = v1.bits.u256[2] | v2.bits.u256[2];
|
||||
new.bits.u256[3] = v1.bits.u256[3] | v2.bits.u256[3];
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
and_vbits(vbits_t v1, vbits_t v2)
|
||||
{
|
||||
assert(v1.num_bits == v2.num_bits);
|
||||
|
||||
vbits_t new = { .num_bits = v1.num_bits };
|
||||
|
||||
switch (v1.num_bits) {
|
||||
case 8: new.bits.u8 = v1.bits.u8 & v2.bits.u8; break;
|
||||
case 16: new.bits.u16 = v1.bits.u16 & v2.bits.u16; break;
|
||||
case 32: new.bits.u32 = v1.bits.u32 & v2.bits.u32; break;
|
||||
case 64: new.bits.u64 = v1.bits.u64 & v2.bits.u64; break;
|
||||
case 128: new.bits.u128[0] = v1.bits.u128[0] & v2.bits.u128[0];
|
||||
new.bits.u128[1] = v1.bits.u128[1] & v2.bits.u128[1];
|
||||
break;
|
||||
case 256: new.bits.u256[0] = v1.bits.u256[0] & v2.bits.u256[0];
|
||||
new.bits.u256[1] = v1.bits.u256[1] & v2.bits.u256[1];
|
||||
new.bits.u256[2] = v1.bits.u256[2] & v2.bits.u256[2];
|
||||
new.bits.u256[3] = v1.bits.u256[3] & v2.bits.u256[3];
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
concat_vbits(vbits_t v1, vbits_t v2)
|
||||
{
|
||||
assert(v1.num_bits == v2.num_bits);
|
||||
|
||||
vbits_t new = { .num_bits = v1.num_bits * 2 };
|
||||
|
||||
switch (v1.num_bits) {
|
||||
case 8: new.bits.u16 = v1.bits.u8;
|
||||
new.bits.u16 = (new.bits.u16 << 8) | v2.bits.u8; break;
|
||||
case 16: new.bits.u32 = v1.bits.u16;
|
||||
new.bits.u32 = (new.bits.u32 << 16) | v2.bits.u16; break;
|
||||
case 32: new.bits.u64 = v1.bits.u32;
|
||||
new.bits.u64 = (new.bits.u64 << 32) | v2.bits.u32; break;
|
||||
case 64:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u128[0] = v2.bits.u64;
|
||||
new.bits.u128[1] = v1.bits.u64;
|
||||
} else {
|
||||
new.bits.u128[0] = v1.bits.u64;
|
||||
new.bits.u128[1] = v2.bits.u64;
|
||||
}
|
||||
break;
|
||||
case 128:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u256[0] = v2.bits.u128[0];
|
||||
new.bits.u256[1] = v2.bits.u128[1];
|
||||
new.bits.u256[2] = v1.bits.u128[0];
|
||||
new.bits.u256[3] = v1.bits.u128[1];
|
||||
} else {
|
||||
new.bits.u256[0] = v1.bits.u128[0];
|
||||
new.bits.u256[1] = v1.bits.u128[1];
|
||||
new.bits.u256[2] = v2.bits.u128[0];
|
||||
new.bits.u256[3] = v2.bits.u128[1];
|
||||
}
|
||||
break;
|
||||
case 256: /* Fall through */
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
upper_vbits(vbits_t v)
|
||||
{
|
||||
vbits_t new = { .num_bits = v.num_bits / 2 };
|
||||
|
||||
switch (v.num_bits) {
|
||||
case 16: new.bits.u8 = v.bits.u16 >> 8; break;
|
||||
case 32: new.bits.u16 = v.bits.u32 >> 16; break;
|
||||
case 64: new.bits.u32 = v.bits.u64 >> 32; break;
|
||||
case 128:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
new.bits.u64 = v.bits.u128[1];
|
||||
else
|
||||
new.bits.u64 = v.bits.u128[0];
|
||||
break;
|
||||
case 256:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u128[0] = v.bits.u256[2];
|
||||
new.bits.u128[1] = v.bits.u256[3];
|
||||
} else {
|
||||
new.bits.u128[0] = v.bits.u256[0];
|
||||
new.bits.u128[1] = v.bits.u256[1];
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
zextend_vbits(vbits_t v, unsigned num_bits)
|
||||
{
|
||||
assert(num_bits >= v.num_bits);
|
||||
|
||||
if (num_bits == v.num_bits) return v;
|
||||
|
||||
vbits_t new = { .num_bits = num_bits };
|
||||
|
||||
if (v.num_bits <= 64) {
|
||||
uint64_t bits = get_bits64(v);
|
||||
|
||||
switch (num_bits) {
|
||||
case 8: new.bits.u8 = bits; break;
|
||||
case 16: new.bits.u16 = bits; break;
|
||||
case 32: new.bits.u32 = bits; break;
|
||||
case 64: new.bits.u64 = bits; break;
|
||||
case 128:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u128[0] = bits;
|
||||
new.bits.u128[1] = 0;
|
||||
} else {
|
||||
new.bits.u128[0] = 0;
|
||||
new.bits.u128[1] = bits;
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u256[0] = bits;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
} else {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = bits;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
if (v.num_bits == 128) {
|
||||
assert(num_bits == 256);
|
||||
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
new.bits.u256[0] = v.bits.u128[0];
|
||||
new.bits.u256[1] = v.bits.u128[1];
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
} else {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = v.bits.u128[1];
|
||||
new.bits.u256[3] = v.bits.u128[0];
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Cannot zero-extend a 256-bit value to something larger */
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
sextend_vbits(vbits_t v, unsigned num_bits)
|
||||
{
|
||||
assert(num_bits >= v.num_bits);
|
||||
|
||||
int sextend = 0;
|
||||
|
||||
switch (v.num_bits) {
|
||||
case 8: if (v.bits.u8 == 0x80) sextend = 1; break;
|
||||
case 16: if (v.bits.u16 == 0x8000) sextend = 1; break;
|
||||
case 32: if (v.bits.u32 == 0x80000000) sextend = 1; break;
|
||||
case 64: if (v.bits.u64 == (1ull << 63)) sextend = 1; break;
|
||||
case 128: if (v.bits.u128[1] == (1ull << 63)) sextend = 1; break;
|
||||
case 256: if (v.bits.u256[3] == (1ull << 63)) sextend = 1; break;
|
||||
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return sextend ? left_vbits(v, num_bits) : zextend_vbits(v, num_bits);
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
onehot_vbits(unsigned bitno, unsigned num_bits)
|
||||
{
|
||||
assert(bitno < num_bits);
|
||||
|
||||
vbits_t new = { .num_bits = num_bits };
|
||||
|
||||
switch (num_bits) {
|
||||
case 1: new.bits.u32 = 1 << bitno; break;
|
||||
case 8: new.bits.u8 = 1 << bitno; break;
|
||||
case 16: new.bits.u16 = 1 << bitno; break;
|
||||
case 32: new.bits.u32 = 1u << bitno; break;
|
||||
case 64: new.bits.u64 = 1ull << bitno; break;
|
||||
case 128:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
if (bitno < 64) {
|
||||
new.bits.u128[0] = 1ull << bitno;
|
||||
new.bits.u128[1] = 0;
|
||||
} else {
|
||||
new.bits.u128[0] = 0;
|
||||
new.bits.u128[1] = 1ull << (bitno - 64);
|
||||
}
|
||||
} else {
|
||||
if (bitno < 64) {
|
||||
new.bits.u128[0] = 0;
|
||||
new.bits.u128[1] = 1ull << bitno;
|
||||
} else {
|
||||
new.bits.u128[0] = 1ull << (bitno - 64);
|
||||
new.bits.u128[1] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
|
||||
if (bitno < 64) {
|
||||
new.bits.u256[0] = 1ull << bitno;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
} else if (bitno < 128) {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 1ull << (bitno - 64);
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
} else if (bitno < 192) {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 1ull << (bitno - 128);
|
||||
new.bits.u256[3] = 0;
|
||||
} else {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 1ull << (bitno - 192);
|
||||
}
|
||||
} else {
|
||||
if (bitno < 64) {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 1ull << bitno;
|
||||
} else if (bitno < 128) {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 1ull << (bitno - 64);
|
||||
new.bits.u256[3] = 0;
|
||||
} else if (bitno < 192) {
|
||||
new.bits.u256[0] = 0;
|
||||
new.bits.u256[1] = 1ull << (bitno - 128);
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
} else {
|
||||
new.bits.u256[0] = 1ull << (bitno - 192);
|
||||
new.bits.u256[1] = 0;
|
||||
new.bits.u256[2] = 0;
|
||||
new.bits.u256[3] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
completely_defined_vbits(vbits_t v)
|
||||
{
|
||||
return equal_vbits(v, defined_vbits(v.num_bits));
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
shl_vbits(vbits_t v, unsigned shift_amount)
|
||||
{
|
||||
assert(shift_amount < v.num_bits);
|
||||
|
||||
vbits_t new = v;
|
||||
|
||||
switch (v.num_bits) {
|
||||
case 8: new.bits.u8 <<= shift_amount; break;
|
||||
case 16: new.bits.u16 <<= shift_amount; break;
|
||||
case 32: new.bits.u32 <<= shift_amount; break;
|
||||
case 64: new.bits.u64 <<= shift_amount; break;
|
||||
case 128: /* fall through */
|
||||
case 256: /* fall through */
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
shr_vbits(vbits_t v, unsigned shift_amount)
|
||||
{
|
||||
assert(shift_amount < v.num_bits);
|
||||
|
||||
vbits_t new = v;
|
||||
|
||||
switch (v.num_bits) {
|
||||
case 8: new.bits.u8 >>= shift_amount; break;
|
||||
case 16: new.bits.u16 >>= shift_amount; break;
|
||||
case 32: new.bits.u32 >>= shift_amount; break;
|
||||
case 64: new.bits.u64 >>= shift_amount; break;
|
||||
case 128: /* fall through */
|
||||
case 256: /* fall through */
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
vbits_t
|
||||
sar_vbits(vbits_t v, unsigned shift_amount)
|
||||
{
|
||||
assert(shift_amount < v.num_bits);
|
||||
|
||||
vbits_t new = v;
|
||||
int msb;
|
||||
|
||||
switch (v.num_bits) {
|
||||
case 8:
|
||||
new.bits.u8 >>= shift_amount;
|
||||
msb = (v.bits.u8 & 0x80) != 0;
|
||||
break;
|
||||
case 16:
|
||||
new.bits.u16 >>= shift_amount;
|
||||
msb = (v.bits.u16 & 0x8000) != 0;
|
||||
break;
|
||||
case 32:
|
||||
new.bits.u32 >>= shift_amount;
|
||||
msb = (v.bits.u32 & (1u << 31)) != 0;
|
||||
break;
|
||||
case 64:
|
||||
new.bits.u64 >>= shift_amount;
|
||||
msb = (v.bits.u64 & (1ull << 63)) != 0;
|
||||
break;
|
||||
case 128: /* fall through */
|
||||
case 256: /* fall through */
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
if (msb)
|
||||
new = left_vbits(new, new.num_bits);
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Return a value for the POWER Iop_CmpORD class iops */
|
||||
vbits_t
|
||||
cmpord_vbits(unsigned v1_num_bits, unsigned v2_num_bits)
|
||||
{
|
||||
vbits_t new = { .num_bits = v1_num_bits };
|
||||
|
||||
/* Size of values being compared must be the same */
|
||||
assert( v1_num_bits == v2_num_bits);
|
||||
|
||||
/* Comparison only produces 32-bit or 64-bit value where
|
||||
* the lower 3 bits are set to indicate, less than, equal and greater then.
|
||||
*/
|
||||
switch (v1_num_bits) {
|
||||
case 32:
|
||||
new.bits.u32 = 0xE;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
new.bits.u64 = 0xE;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#ifndef VBITS_H
|
||||
#define VBITS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef uint64_t uint128_t[2];
|
||||
typedef uint64_t uint256_t[4];
|
||||
|
||||
/* A type to represent V-bits */
|
||||
typedef struct {
|
||||
unsigned num_bits;
|
||||
union {
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
uint128_t u128;
|
||||
uint256_t u256;
|
||||
} bits;
|
||||
} vbits_t;
|
||||
|
||||
|
||||
/* A type large enough to hold any IRtype'd value. At this point
|
||||
we do not expect to test with specific floating point values.
|
||||
So we don't need to represent them. */
|
||||
typedef union {
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
uint128_t u128;
|
||||
uint256_t u256;
|
||||
} value_t;
|
||||
|
||||
|
||||
void print_vbits(FILE *, vbits_t);
|
||||
vbits_t undefined_vbits(unsigned num_bits);
|
||||
vbits_t defined_vbits(unsigned num_bits);
|
||||
int equal_vbits(vbits_t, vbits_t);
|
||||
vbits_t truncate_vbits(vbits_t, unsigned num_bits);
|
||||
vbits_t left_vbits(vbits_t, unsigned num_bits);
|
||||
vbits_t or_vbits(vbits_t, vbits_t);
|
||||
vbits_t and_vbits(vbits_t, vbits_t);
|
||||
vbits_t concat_vbits(vbits_t, vbits_t);
|
||||
vbits_t upper_vbits(vbits_t);
|
||||
vbits_t sextend_vbits(vbits_t, unsigned num_bits);
|
||||
vbits_t zextend_vbits(vbits_t, unsigned num_bits);
|
||||
vbits_t onehot_vbits(unsigned bitno, unsigned num_bits);
|
||||
vbits_t shl_vbits(vbits_t, unsigned amount);
|
||||
vbits_t shr_vbits(vbits_t, unsigned amount);
|
||||
vbits_t sar_vbits(vbits_t, unsigned amount);
|
||||
int completely_defined_vbits(vbits_t);
|
||||
vbits_t cmpord_vbits(unsigned v1_num_bits, unsigned v2_num_bits);
|
||||
|
||||
#endif // VBITS_H
|
||||
@@ -0,0 +1,137 @@
|
||||
/* -*- mode: C; c-basic-offset: 3; -*- */
|
||||
|
||||
#ifndef VTEST_H
|
||||
#define VTEST_H
|
||||
|
||||
/* Main header file for the V-bit tester */
|
||||
|
||||
#include <stdint.h> // uint64_t
|
||||
#include "libvex.h" // IROp
|
||||
#include "vbits.h" // vbits_t
|
||||
|
||||
|
||||
/* How undefinedness propagates from input to output */
|
||||
|
||||
typedef enum {
|
||||
// For any undefined input bit, all output bits are defined.
|
||||
UNDEF_NONE,
|
||||
|
||||
// For any undefined input bit, all output bits are undefined.
|
||||
UNDEF_ALL,
|
||||
|
||||
// For each undefined input bit, the corresponding output bit
|
||||
// in the same position is undefined. No other bit is undefined.
|
||||
UNDEF_SAME,
|
||||
|
||||
// For each undefined input bit, the corresponding output bit
|
||||
// in the same position is undefined. No other bit is undefined.
|
||||
// If the corresponding output bit does not exist, the input bit
|
||||
// does not cause any output bits to be undefined.
|
||||
UNDEF_TRUNC,
|
||||
|
||||
// For each undefined input bit, the corresponding output bit
|
||||
// in the same position is undefined. No other bit is undefined.
|
||||
// Output bits that do no not have a corresponding input bit are
|
||||
// defined.
|
||||
UNDEF_ZEXT,
|
||||
|
||||
// For each undefined input bit, the corresponding output bit
|
||||
// in the same position is undefined. If the MSB of the input value
|
||||
// is undefined, so are all output bits with higher significance
|
||||
// than the MSB input bit.
|
||||
UNDEF_SEXT,
|
||||
|
||||
// For each undefined input bit, the corresponding output bit
|
||||
// and all output bits with higher significance are undefined.
|
||||
UNDEF_LEFT,
|
||||
|
||||
UNDEF_CONCAT, // nHLto2n ops e.g. Iop_32HLto64
|
||||
UNDEF_UPPER, // 2nHIton ops e.g. Iop_64HIto32
|
||||
UNDEF_SHL, // shift-left
|
||||
UNDEF_SHR, // logical shift-right
|
||||
UNDEF_SAR, // arithmetic shift-right
|
||||
UNDEF_OR, // bitwise OR operation
|
||||
UNDEF_AND, // bitwise AND operation
|
||||
|
||||
UNDEF_ORD, // Iop_CmpORD compare
|
||||
|
||||
// For IROps I don't know anything about
|
||||
UNDEF_UNKNOWN
|
||||
} undef_t;
|
||||
|
||||
|
||||
// Everything we want to know about an IROp
|
||||
typedef struct {
|
||||
IROp op;
|
||||
const char *name;
|
||||
undef_t undef_kind;
|
||||
int shift_amount_is_immediate;
|
||||
// Indicate whether IROp can be tested on a particular architecture
|
||||
unsigned s390x : 1;
|
||||
unsigned amd64 : 1;
|
||||
unsigned ppc32 : 1;
|
||||
unsigned ppc64 : 1;
|
||||
unsigned arm : 1;
|
||||
unsigned arm64 : 1;
|
||||
unsigned x86 : 1;
|
||||
unsigned mips32 : 1;
|
||||
unsigned mips64 : 1;
|
||||
unsigned tilegx : 1;
|
||||
} irop_t;
|
||||
|
||||
|
||||
/* The maximum number of input operands */
|
||||
#define MAX_OPERANDS 4
|
||||
|
||||
/* An operand of an IROp (also used for the result) */
|
||||
typedef struct {
|
||||
IRType type;
|
||||
vbits_t vbits;
|
||||
value_t value;
|
||||
} opnd_t;
|
||||
|
||||
|
||||
/* Carries the data needed to execute and evaluate a test. I.e.
|
||||
inputs and results (V-bits and actual value). */
|
||||
typedef struct {
|
||||
opnd_t result;
|
||||
opnd_t opnds[MAX_OPERANDS];
|
||||
unsigned rounding_mode;
|
||||
} test_data_t;
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
irop_t *get_irop(IROp);
|
||||
int is_floating_point_op_with_rounding_mode(IROp);
|
||||
int get_num_operands(IROp);
|
||||
|
||||
void print_opnd(FILE *, const opnd_t *);
|
||||
|
||||
int test_unary_op(const irop_t *, test_data_t *);
|
||||
int test_binary_op(const irop_t *, test_data_t *);
|
||||
int test_ternary_op(const irop_t *, test_data_t *);
|
||||
int test_qernary_op(const irop_t *, test_data_t *);
|
||||
|
||||
void valgrind_vex_init_for_iri(IRICB *);
|
||||
void valgrind_execute_test(const irop_t *, test_data_t *);
|
||||
|
||||
IRICB new_iricb(const irop_t *, test_data_t *);
|
||||
|
||||
void panic(const char *) __attribute__((noreturn));
|
||||
void complain(const irop_t *, const test_data_t *, vbits_t expected);
|
||||
|
||||
/* Imported from VEX */
|
||||
unsigned sizeof_irtype(IRType);
|
||||
void typeof_primop(IROp, IRType *t_dst, IRType *t_arg1, IRType *t_arg2,
|
||||
IRType *t_arg3, IRType *t_arg4);
|
||||
|
||||
static __inline__ unsigned bitsof_irtype(IRType type)
|
||||
{
|
||||
return type == Ity_I1 ? 1 : sizeof_irtype(type) * 8;
|
||||
}
|
||||
|
||||
|
||||
/* Exported variables */
|
||||
extern int verbose;
|
||||
|
||||
#endif // VTEST_H
|
||||
Reference in New Issue
Block a user