| /* { 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; |
| } |