blob: 63e7807d3d92f317942da9b5b9eb516c4bdbac5d [file] [log] [blame]
/* { dg-require-effective-target int32plus } */
#ifdef __UINT32_TYPE__
typedef __UINT32_TYPE__ uint32_t;
#else
typedef __UINT32_TYPE__ unsigned;
#endif
struct bitfield {
unsigned char f0:7;
unsigned char :1;
unsigned char f1:7;
unsigned char :1;
unsigned char f2:7;
unsigned char :1;
unsigned char f3:7;
};
struct ok {
unsigned char f0;
unsigned char f1;
unsigned char f2;
unsigned char f3;
};
union bf_or_uint32 {
struct ok inval;
struct bitfield bfval;
};
__attribute__ ((noinline, noclone)) uint32_t
partial_read_le32 (union bf_or_uint32 in)
{
return in.bfval.f0 | (in.bfval.f1 << 8)
| (in.bfval.f2 << 16) | (in.bfval.f3 << 24);
}
__attribute__ ((noinline, noclone)) uint32_t
partial_read_be32 (union bf_or_uint32 in)
{
return in.bfval.f3 | (in.bfval.f2 << 8)
| (in.bfval.f1 << 16) | (in.bfval.f0 << 24);
}
__attribute__ ((noinline, noclone)) uint32_t
fake_read_le32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
*y = 1;
c2 = x[2];
c3 = x[3];
return c0 | c1 << 8 | c2 << 16 | c3 << 24;
}
__attribute__ ((noinline, noclone)) uint32_t
fake_read_be32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
*y = 1;
c2 = x[2];
c3 = x[3];
return c3 | c2 << 8 | c1 << 16 | c0 << 24;
}
__attribute__ ((noinline, noclone)) uint32_t
incorrect_read_le32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
c2 = x[2];
c3 = x[3];
*y = 1;
return c0 | c1 << 8 | c2 << 16 | c3 << 24;
}
__attribute__ ((noinline, noclone)) uint32_t
incorrect_read_be32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
c2 = x[2];
c3 = x[3];
*y = 1;
return c3 | c2 << 8 | c1 << 16 | c0 << 24;
}
int
main ()
{
union bf_or_uint32 bfin;
uint32_t out;
char cin[] = { 0x83, 0x85, 0x87, 0x89 };
if (sizeof (uint32_t) * __CHAR_BIT__ != 32)
return 0;
bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
out = partial_read_le32 (bfin);
/* Test what bswap would do if its check are not strict enough instead of
what is the expected result as there is too many possible results with
bitfields. */
if (out == 0x89878583)
__builtin_abort ();
bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
out = partial_read_be32 (bfin);
/* Test what bswap would do if its check are not strict enough instead of
what is the expected result as there is too many possible results with
bitfields. */
if (out == 0x83858789)
__builtin_abort ();
out = fake_read_le32 (cin, &cin[2]);
if (out != 0x89018583)
__builtin_abort ();
cin[2] = 0x87;
out = fake_read_be32 (cin, &cin[2]);
if (out != 0x83850189)
__builtin_abort ();
cin[2] = 0x87;
out = incorrect_read_le32 (cin, &cin[2]);
if (out != 0x89878583)
__builtin_abort ();
cin[2] = 0x87;
out = incorrect_read_be32 (cin, &cin[2]);
if (out != 0x83858789)
__builtin_abort ();
return 0;
}