1/* { dg-do run } */
2/* { dg-options "-O2" } */
3
4struct emac {
5        unsigned reg[23];
6};
7
8struct mop {
9        unsigned long long addr;
10        unsigned int size;
11};
12
13unsigned int __attribute__((__noinline__))
14level(const struct emac *obj)
15{
16	return 0;
17}
18
19void __attribute__((__noinline__))
20info(struct emac *dev, unsigned long long addr)
21{
22	asm("" : : : "memory");
23}
24
25unsigned long long __attribute__((__noinline__))
26get_value(const struct mop *mop)
27{
28        return 0x1234567890abcdefull;
29}
30
31int __attribute__((__noinline__))
32emac_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
65int 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