1 /* { dg-do run } */
2 /* { dg-options "-O2" } */
3 
4 struct emac {
5         unsigned reg[23];
6 };
7 
8 struct mop {
9         unsigned long long addr;
10         unsigned int size;
11 };
12 
13 unsigned int __attribute__((__noinline__))
level(const struct emac * obj)14 level(const struct emac *obj)
15 {
16 	return 0;
17 }
18 
19 void __attribute__((__noinline__))
info(struct emac * dev,unsigned long long addr)20 info(struct emac *dev, unsigned long long addr)
21 {
22 	asm("" : : : "memory");
23 }
24 
25 unsigned long long __attribute__((__noinline__))
get_value(const struct mop * mop)26 get_value(const struct mop *mop)
27 {
28         return 0x1234567890abcdefull;
29 }
30 
31 int __attribute__((__noinline__))
emac_operation(struct emac * obj,struct mop * mop)32 emac_operation(struct emac *obj, struct mop *mop)
33 {
34         unsigned long long addr = mop->addr;
35         int index = addr >> 2;
36 	unsigned int value, old_value;
37 
38         if (mop->size != 4)
39                 return 0;
40 
41         if (index >= 23) {
42                 if (level(obj) >= 1)
43                         info(obj, addr);
44                 return 0;
45         }
46 
47         value = get_value(mop);
48         old_value = obj->reg[index];
49 
50         info(obj, 0);
51 
52         switch (index) {
53         case 0:
54                 obj->reg[0] = old_value;
55                 break;
56         case 7:
57         case 8:
58                 obj->reg[index] = value;
59                 break;
60         }
61 
62         return 0;
63 }
64 
main(void)65 int main(void)
66 {
67 	struct emac e = { { 0 } };
68 	struct mop mop = { 32, 4 };
69 
70 	e.reg[8] = 0xdeadbeef;
71 	emac_operation(&e, &mop);
72 
73 	if (e.reg[8] != 0x90abcdef)
74 	   __builtin_abort();
75 
76 	   return 0;
77 }
78