mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-10 01:16:12 +00:00
86 lines
2.5 KiB
C
86 lines
2.5 KiB
C
/* https://bugs.kde.org/show_bug.cgi?id=308626 */
|
|
|
|
#include "../../memcheck.h"
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
typedef unsigned int UInt;
|
|
|
|
/* Calculate ctz(x) using bsfl instruction. */
|
|
static int ctz(UInt x)
|
|
{
|
|
assert(sizeof(UInt) == 4);
|
|
int result=8*sizeof(UInt);
|
|
/* BSFL does not change the destination when the input is zero. */
|
|
asm("bsfl %1,%0" : "=r" (result) : "r" (x), "0" (result) : "cc");
|
|
return result;
|
|
}
|
|
|
|
/* Set the V bits at "addr". Note the convention: A zero bit means
|
|
"defined"; 1 means "undefined". */
|
|
static void set_vbits(UInt *addr, UInt vbits)
|
|
{
|
|
(void)VALGRIND_SET_VBITS(addr, &vbits, sizeof(unsigned));
|
|
}
|
|
|
|
static void doit(unsigned vbits, unsigned val)
|
|
{
|
|
/* Since we are about to mark "val" partially undefined, make a
|
|
copy that we can use without generating a memcheck warning. */
|
|
unsigned val_copy = val;
|
|
|
|
/* Mark "val" partially undefined. */
|
|
set_vbits(&val, vbits);
|
|
|
|
/* Convince GCC it does not know what is in "val" so it does not
|
|
optimize away any uses of it. */
|
|
__asm__ ("" : "=r" (val) : "0" (val));
|
|
|
|
int result = ctz(val);
|
|
|
|
/* The following code is carefully constructed: The conditional
|
|
itself should generate a memcheck warning if and only if it is
|
|
false. (Specifically, if the first "1" bit in val comes before
|
|
the first "undefined" bit, or the entire word is valid, then
|
|
ctz(val) is defined; else it is undefined.) */
|
|
if (result < ctz(vbits) || vbits == 0) {
|
|
/* There should be no memcheck warning on this printf, since
|
|
"result" is fully-defined in this case. */
|
|
printf("vbits=0x%08x ctz(0x%08x)=%d\n", vbits, val_copy, result);
|
|
}
|
|
else {
|
|
/* memcheck should have output a warning. But we want
|
|
something here so there is no possibiliy of Valgrind
|
|
optimizing out the conditional itself. */
|
|
fprintf(stderr, "0x%08x: Invalid value is %d\n", val_copy,
|
|
ctz(val_copy));
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
doit(0x00000000, 0x00000000);
|
|
doit(0x00000000, 0x00000001);
|
|
doit(0x00000001, 0x00000000);
|
|
doit(0x00000001, 0x00000001);
|
|
|
|
/* valid bit / data bit sandwich */
|
|
doit(0x00000090, 0x00000040);
|
|
doit(0x00000040, 0x00000090);
|
|
|
|
/* Interleaving */
|
|
doit(0x00000500, 0x00000a00);
|
|
doit(0x00000a00, 0x00000500);
|
|
|
|
doit(0x000f0000, 0x001e0000);
|
|
doit(0x001e0000, 0x000f0000);
|
|
|
|
doit(0xffffffff, 0xffffffff);
|
|
doit(0xfffffffe, 0xffffffff);
|
|
doit(0xffffffff, 0xfffffffe);
|
|
doit(0xfffffffe, 0xfffffffe);
|
|
|
|
return 0;
|
|
}
|