1 /* { dg-require-effective-target int32plus } */
2
3 #ifdef __UINT32_TYPE__
4 typedef __UINT32_TYPE__ uint32_t;
5 #else
6 typedef __UINT32_TYPE__ unsigned;
7 #endif
8
9 struct bitfield {
10 unsigned char f0:7;
11 unsigned char :1;
12 unsigned char f1:7;
13 unsigned char :1;
14 unsigned char f2:7;
15 unsigned char :1;
16 unsigned char f3:7;
17 };
18
19 struct ok {
20 unsigned char f0;
21 unsigned char f1;
22 unsigned char f2;
23 unsigned char f3;
24 };
25
26 union bf_or_uint32 {
27 struct ok inval;
28 struct bitfield bfval;
29 };
30
31 __attribute__ ((noinline, noclone)) uint32_t
partial_read_le32(union bf_or_uint32 in)32 partial_read_le32 (union bf_or_uint32 in)
33 {
34 return in.bfval.f0 | (in.bfval.f1 << 8)
35 | (in.bfval.f2 << 16) | (in.bfval.f3 << 24);
36 }
37
38 __attribute__ ((noinline, noclone)) uint32_t
partial_read_be32(union bf_or_uint32 in)39 partial_read_be32 (union bf_or_uint32 in)
40 {
41 return in.bfval.f3 | (in.bfval.f2 << 8)
42 | (in.bfval.f1 << 16) | (in.bfval.f0 << 24);
43 }
44
45 __attribute__ ((noinline, noclone)) uint32_t
fake_read_le32(char * x,char * y)46 fake_read_le32 (char *x, char *y)
47 {
48 unsigned char c0, c1, c2, c3;
49
50 c0 = x[0];
51 c1 = x[1];
52 *y = 1;
53 c2 = x[2];
54 c3 = x[3];
55 return c0 | c1 << 8 | c2 << 16 | c3 << 24;
56 }
57
58 __attribute__ ((noinline, noclone)) uint32_t
fake_read_be32(char * x,char * y)59 fake_read_be32 (char *x, char *y)
60 {
61 unsigned char c0, c1, c2, c3;
62
63 c0 = x[0];
64 c1 = x[1];
65 *y = 1;
66 c2 = x[2];
67 c3 = x[3];
68 return c3 | c2 << 8 | c1 << 16 | c0 << 24;
69 }
70
71 __attribute__ ((noinline, noclone)) uint32_t
incorrect_read_le32(char * x,char * y)72 incorrect_read_le32 (char *x, char *y)
73 {
74 unsigned char c0, c1, c2, c3;
75
76 c0 = x[0];
77 c1 = x[1];
78 c2 = x[2];
79 c3 = x[3];
80 *y = 1;
81 return c0 | c1 << 8 | c2 << 16 | c3 << 24;
82 }
83
84 __attribute__ ((noinline, noclone)) uint32_t
incorrect_read_be32(char * x,char * y)85 incorrect_read_be32 (char *x, char *y)
86 {
87 unsigned char c0, c1, c2, c3;
88
89 c0 = x[0];
90 c1 = x[1];
91 c2 = x[2];
92 c3 = x[3];
93 *y = 1;
94 return c3 | c2 << 8 | c1 << 16 | c0 << 24;
95 }
96
97 int
main()98 main ()
99 {
100 union bf_or_uint32 bfin;
101 uint32_t out;
102 char cin[] = { 0x83, 0x85, 0x87, 0x89 };
103
104 if (sizeof (uint32_t) * __CHAR_BIT__ != 32)
105 return 0;
106 bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
107 out = partial_read_le32 (bfin);
108 /* Test what bswap would do if its check are not strict enough instead of
109 what is the expected result as there is too many possible results with
110 bitfields. */
111 if (out == 0x89878583)
112 __builtin_abort ();
113 bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
114 out = partial_read_be32 (bfin);
115 /* Test what bswap would do if its check are not strict enough instead of
116 what is the expected result as there is too many possible results with
117 bitfields. */
118 if (out == 0x83858789)
119 __builtin_abort ();
120 out = fake_read_le32 (cin, &cin[2]);
121 if (out != 0x89018583)
122 __builtin_abort ();
123 cin[2] = 0x87;
124 out = fake_read_be32 (cin, &cin[2]);
125 if (out != 0x83850189)
126 __builtin_abort ();
127 cin[2] = 0x87;
128 out = incorrect_read_le32 (cin, &cin[2]);
129 if (out != 0x89878583)
130 __builtin_abort ();
131 cin[2] = 0x87;
132 out = incorrect_read_be32 (cin, &cin[2]);
133 if (out != 0x83858789)
134 __builtin_abort ();
135 return 0;
136 }
137