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