1 /* Copyright (C) 2002  Free Software Foundation.
2    by Hans-Peter Nilsson  <hp@axis.com>
3 
4    Making sure that asm clobbers conflicting with asm-declared input
5    operands are detected: ``You may not write a clobber description in a
6    way that overlaps with an input or output operand''.
7 
8    You must be this tall ---> fit two long longs in asm-declared registers
9    to enter this amusement.  */
10 
11 /* { dg-do compile { target alpha*-*-* cris-*-* crisv32-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */
12 /* { dg-options "-O2" } */
13 
14 /* Constructed examples; input/output (same register), output, input, and
15    input and output (different registers).  */
16 
17 /* The long longs are used to test overlap for multi-register
18    registers.  REG2 and REG4 must be the second halves (defined as
19    higher-numbered parts) of REG1 and REG3 respectively when two registers
20    are needed.  */
21 
22 #if defined (__alpha__)
23 # define REG1 "$1"
24 # define REG2 "$2"
25 #elif defined (__CRIS__)
26 # define REG1 "r10"
27 # define REG2 "r11"
28 # define REG3 "r12"
29 # define REG4 "r13"
30 # define REG5 "r9"
31 #elif defined (__i386__)
32 # define REG1 "%eax"
33 # define REG2 "%edx"
34 /* On Darwin -fpic is on by default, so don't use %ebx. */
35 # define REG3 "%esi"
36 # define REG4 "%edi"
37 #elif defined (__MMIX__)
38 # define REG1 "$8"
39 # define REG2 "$9"
40 #elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
41 	|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) \
42 	|| defined (__ppc)
43 # define REG1 "6"
44 # define REG2 "7"
45 # if !defined(_ARCH_PPC64)
46 #  define REG3 "8"
47 #  define REG4 "9"
48 # endif
49 #elif defined (__x86_64__)
50 # define REG1 "rax"
51 # define REG2 "rdx"
52 #endif
53 
54 /* For readability of the tests.  */
55 #ifdef REG3
56 # define REG1a REG1
57 # define REG1b REG2
58 # define REG2a REG3
59 # define REG2b REG4
60 #else
61 # define REG1a REG1
62 # define REG1b REG1
63 # define REG2a REG2
64 # define REG2b REG2
65 #endif
66 
67 /* REG5 is just another reg if there is one; the difference to REG4 is to
68    keep the original set of registers for CRIS.  */
69 #ifndef REG5
70 #define REG5 REG2b
71 #endif
72 
73 void *
foo(void * p)74 foo (void *p)
75 {
76   register void *q asm (REG1) = p;
77   asm ("foo1 %0" : "=r" (q) : "0" (q) : REG1); /* { dg-error "conflict" } */
78   return q;
79 }
80 
81 void *
nfoo(void * p)82 nfoo (void *p)
83 {
84   register void *q asm (REG1) = p;
85   asm ("foo1 %0" : "=r" (q) : "0" (q) : REG2);
86   return q;
87 }
88 
89 long long
foolla(long long llp)90 foolla (long long llp)
91 {
92   register long long ll asm (REG1a) = llp;
93   asm ("foo1a %0" : "=r" (ll) : "0" (ll) : REG1a); /* { dg-error "conflict" } */
94   return ll;
95 }
96 
97 long long
nfoolla(long long llp)98 nfoolla (long long llp)
99 {
100   register long long ll asm (REG1a) = llp;
101   asm ("foo1a %0" : "=r" (ll) : "0" (ll) : REG2a);
102   return ll;
103 }
104 
105 long long
foollb(long long llp)106 foollb (long long llp)
107 {
108   register long long ll asm (REG1a) = llp;
109   asm ("foo1b %0" : "=r" (ll) : "0" (ll) : REG1b); /* { dg-error "conflict" } */
110   return ll;
111 }
112 
113 void *
bar(void * p)114 bar (void *p)
115 {
116   register void *q asm (REG1);
117   register void *w asm (REG2) = p;
118   asm ("bar1 %1,%0" : "=r" (q) : "r" (w) : REG1); /* { dg-error "conflict" } */
119   return q;
120 }
121 
122 long long
barlla(long long llp)123 barlla (long long llp)
124 {
125   register long long ll asm (REG1a);
126   register long long mm asm (REG2a) = llp;
127   asm ("bar1a %1,%0" : "=r" (ll) : "r" (mm) : REG1b); /* { dg-error "conflict" } */
128   return ll;
129 }
130 
131 long long
barllb(long long llp)132 barllb (long long llp)
133 {
134   register long long ll asm (REG1a);
135   register long long mm asm (REG2a) = llp;
136   asm ("bar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b); /* { dg-error "conflict" } */
137   return ll;
138 }
139 
140 void *
foobar(void * p)141 foobar (void *p)
142 {
143   register void *q asm (REG1);
144   register void *w asm (REG2) = p;
145   asm ("foobar1 %1,%0" : "=r" (q) : "r" (w) : REG2); /* { dg-error "conflict" } */
146   return q;
147 }
148 
149 void *
nfoobar(void * p)150 nfoobar (void *p)
151 {
152   register void *q asm (REG1);
153   register void *w = p;
154   asm ("foobar1 %1,%0" : "=r" (q) : "r" (w) : REG2);
155   return q;
156 }
157 
158 long long
foobarlla(long long llp)159 foobarlla (long long llp)
160 {
161   register long long ll asm (REG1a);
162   register long long mm asm (REG2a) = llp;
163   asm ("foobar1a %1,%0" : "=r" (ll) : "r" (mm) : REG1b); /* { dg-error "conflict" } */
164   return ll;
165 }
166 
167 long long
nfoobarlla(long long llp)168 nfoobarlla (long long llp)
169 {
170   register long long ll asm (REG1a);
171   register long long mm = llp;
172   asm ("foobar1a %1,%0" : "=r" (ll) : "r" (mm) : REG2a);
173   return ll;
174 }
175 
176 long long
foobarllb(long long llp)177 foobarllb (long long llp)
178 {
179   register long long ll asm (REG1a);
180   register long long mm asm (REG2a) = llp;
181   asm ("foobar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b); /* { dg-error "conflict" } */
182   return ll;
183 }
184 
185 long long
nfoobarllb(long long llp)186 nfoobarllb (long long llp)
187 {
188   register long long ll asm (REG1a);
189   register long long mm = llp;
190   asm ("foobar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b);
191   return ll;
192 }
193 
194 void *
baz(void * p)195 baz (void *p)
196 {
197   register void *q asm (REG1);
198   register void *w asm (REG2) = p;
199   asm ("baz1 %1,%0" : "=r" (q) : "r" (w) : REG1, REG2); /* { dg-error "conflict" } */
200   return q;
201 }
202 
203 void *
nbaz(void * p)204 nbaz (void *p)
205 {
206   register void *q;
207   register void *w = p;
208   asm ("baz1 %1,%0" : "=r" (q) : "r" (w) : REG1, REG2);
209   return q;
210 }
211 
212 void *
nbaz2(void * p)213 nbaz2 (void *p)
214 {
215   register void *q asm (REG1);
216   register void *w asm (REG2) = p;
217   asm ("baz1 %1,%0" : "=r" (q) : "r" (w));
218   return q;
219 }
220 
221 long long
bazlla(long long llp)222 bazlla (long long llp)
223 {
224   register long long ll asm (REG1a);
225   register long long mm asm (REG2a) = llp;
226   asm ("baz1a %1,%0" : "=r" (ll) : "r" (mm) : REG1a, REG2a); /* { dg-error "conflict" } */
227   return ll;
228 }
229 
230 long long
bazllb(long long llp)231 bazllb (long long llp)
232 {
233   register long long ll asm (REG1a);
234   register long long mm asm (REG2a) = llp;
235   asm ("baz2a %1,%0" : "=r" (ll) : "r" (mm) : REG1b, REG2b); /* { dg-error "conflict" } */
236   return ll;
237 }
238 
239 /* Real-world example of bug.  */
240 
241 #ifdef _WIN64
242 typedef unsigned int loc_size_t __attribute__ ((mode (DI)));
243 #else
244 typedef __SIZE_TYPE__ loc_size_t;
245 #endif
246 
247 struct stat;
248 int
_dl_stat(const char * file_name,struct stat * buf)249 _dl_stat (const char *file_name, struct stat *buf)
250 {
251   register long a asm (REG1) = (long) (loc_size_t) file_name;
252   register long b asm (REG2) = (long) (loc_size_t) buf;
253 
254   asm volatile ("movu.w %1,$r9\n\tbreak 13" : "=r" (a) : "g" (106), "0" (a), "r" (b) : REG1, REG5); /* { dg-error "conflict" } */
255   if (a >= 0)
256     return (int) a;
257   return (int) -1;
258 }
259