remove unused files
[platform/upstream/gcc48.git] / gcc / config / arm / sync.md
1 ;; Machine description for ARM processor synchronization primitives.
2 ;; Copyright (C) 2010-2013 Free Software Foundation, Inc.
3 ;; Written by Marcus Shawcroft (marcus.shawcroft@arm.com)
4 ;; 64bit Atomics by Dave Gilbert (david.gilbert@linaro.org)
5 ;;
6 ;; This file is part of GCC.
7 ;;
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
12 ;;
13 ;; GCC is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;; General Public License for more details.
17 ;;
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3.  If not see
20 ;; <http://www.gnu.org/licenses/>.  */
21
22 (define_mode_attr sync_predtab
23   [(QI "TARGET_HAVE_LDREXBH && TARGET_HAVE_MEMORY_BARRIER")
24    (HI "TARGET_HAVE_LDREXBH && TARGET_HAVE_MEMORY_BARRIER")
25    (SI "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER")
26    (DI "TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN
27         && TARGET_HAVE_MEMORY_BARRIER")])
28
29 (define_code_iterator syncop [plus minus ior xor and])
30
31 (define_code_attr sync_optab
32   [(ior "or") (xor "xor") (and "and") (plus "add") (minus "sub")])
33
34 (define_mode_attr sync_sfx
35   [(QI "b") (HI "h") (SI "") (DI "d")])
36
37 (define_expand "memory_barrier"
38   [(set (match_dup 0)
39         (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
40   "TARGET_HAVE_MEMORY_BARRIER"
41 {
42   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
43   MEM_VOLATILE_P (operands[0]) = 1;
44 })
45
46 (define_insn "*memory_barrier"
47   [(set (match_operand:BLK 0 "" "")
48         (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
49   "TARGET_HAVE_MEMORY_BARRIER"
50   {
51     if (TARGET_HAVE_DMB)
52       {
53         /* Note we issue a system level barrier. We should consider issuing
54            a inner shareabilty zone barrier here instead, ie. "DMB ISH".  */
55         /* ??? Differentiate based on SEQ_CST vs less strict?  */
56         return "dmb\tsy";
57       }
58
59     if (TARGET_HAVE_DMB_MCR)
60       return "mcr\tp15, 0, r0, c7, c10, 5";
61
62     gcc_unreachable ();
63   }
64   [(set_attr "length" "4")
65    (set_attr "conds" "unconditional")
66    (set_attr "predicable" "no")])
67
68 ;; Note that ldrd and vldr are *not* guaranteed to be single-copy atomic,
69 ;; even for a 64-bit aligned address.  Instead we use a ldrexd unparied
70 ;; with a store.
71 (define_expand "atomic_loaddi"
72   [(match_operand:DI 0 "s_register_operand")            ;; val out
73    (match_operand:DI 1 "mem_noofs_operand")             ;; memory
74    (match_operand:SI 2 "const_int_operand")]            ;; model
75   "TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN"
76 {
77   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
78   expand_mem_thread_fence (model);
79   emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
80   if (model == MEMMODEL_SEQ_CST)
81     expand_mem_thread_fence (model);
82   DONE;
83 })
84
85 (define_insn "atomic_loaddi_1"
86   [(set (match_operand:DI 0 "s_register_operand" "=r")
87         (unspec:DI [(match_operand:DI 1 "mem_noofs_operand" "Ua")]
88                    UNSPEC_LL))]
89   "TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN"
90   "ldrexd%?\t%0, %H0, %C1"
91   [(set_attr "predicable" "yes")])
92
93 (define_expand "atomic_compare_and_swap<mode>"
94   [(match_operand:SI 0 "s_register_operand" "")         ;; bool out
95    (match_operand:QHSD 1 "s_register_operand" "")       ;; val out
96    (match_operand:QHSD 2 "mem_noofs_operand" "")        ;; memory
97    (match_operand:QHSD 3 "general_operand" "")          ;; expected
98    (match_operand:QHSD 4 "s_register_operand" "")       ;; desired
99    (match_operand:SI 5 "const_int_operand")             ;; is_weak
100    (match_operand:SI 6 "const_int_operand")             ;; mod_s
101    (match_operand:SI 7 "const_int_operand")]            ;; mod_f
102   "<sync_predtab>"
103 {
104   arm_expand_compare_and_swap (operands);
105   DONE;
106 })
107
108 (define_insn_and_split "atomic_compare_and_swap<mode>_1"
109   [(set (reg:CC_Z CC_REGNUM)                                    ;; bool out
110         (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ATOMIC_CAS))
111    (set (match_operand:SI 0 "s_register_operand" "=&r")         ;; val out
112         (zero_extend:SI
113           (match_operand:NARROW 1 "mem_noofs_operand" "+Ua")))  ;; memory
114    (set (match_dup 1)
115         (unspec_volatile:NARROW
116           [(match_operand:SI 2 "arm_add_operand" "rIL")         ;; expected
117            (match_operand:NARROW 3 "s_register_operand" "r")    ;; desired
118            (match_operand:SI 4 "const_int_operand")             ;; is_weak
119            (match_operand:SI 5 "const_int_operand")             ;; mod_s
120            (match_operand:SI 6 "const_int_operand")]            ;; mod_f
121           VUNSPEC_ATOMIC_CAS))
122    (clobber (match_scratch:SI 7 "=&r"))]
123   "<sync_predtab>"
124   "#"
125   "&& reload_completed"
126   [(const_int 0)]
127   {
128     arm_split_compare_and_swap (operands);
129     DONE;
130   })
131
132 (define_mode_attr cas_cmp_operand
133   [(SI "arm_add_operand") (DI "cmpdi_operand")])
134 (define_mode_attr cas_cmp_str
135   [(SI "rIL") (DI "rDi")])
136
137 (define_insn_and_split "atomic_compare_and_swap<mode>_1"
138   [(set (reg:CC_Z CC_REGNUM)                                    ;; bool out
139         (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ATOMIC_CAS))
140    (set (match_operand:SIDI 0 "s_register_operand" "=&r")       ;; val out
141         (match_operand:SIDI 1 "mem_noofs_operand" "+Ua"))       ;; memory
142    (set (match_dup 1)
143         (unspec_volatile:SIDI
144           [(match_operand:SIDI 2 "<cas_cmp_operand>" "<cas_cmp_str>") ;; expect
145            (match_operand:SIDI 3 "s_register_operand" "r")      ;; desired
146            (match_operand:SI 4 "const_int_operand")             ;; is_weak
147            (match_operand:SI 5 "const_int_operand")             ;; mod_s
148            (match_operand:SI 6 "const_int_operand")]            ;; mod_f
149           VUNSPEC_ATOMIC_CAS))
150    (clobber (match_scratch:SI 7 "=&r"))]
151   "<sync_predtab>"
152   "#"
153   "&& reload_completed"
154   [(const_int 0)]
155   {
156     arm_split_compare_and_swap (operands);
157     DONE;
158   })
159
160 (define_insn_and_split "atomic_exchange<mode>"
161   [(set (match_operand:QHSD 0 "s_register_operand" "=&r")       ;; output
162         (match_operand:QHSD 1 "mem_noofs_operand" "+Ua"))       ;; memory
163    (set (match_dup 1)
164         (unspec_volatile:QHSD
165           [(match_operand:QHSD 2 "s_register_operand" "r")      ;; input
166            (match_operand:SI 3 "const_int_operand" "")]         ;; model
167           VUNSPEC_ATOMIC_XCHG))
168    (clobber (reg:CC CC_REGNUM))
169    (clobber (match_scratch:SI 4 "=&r"))]
170   "<sync_predtab>"
171   "#"
172   "&& reload_completed"
173   [(const_int 0)]
174   {
175     arm_split_atomic_op (SET, operands[0], NULL, operands[1],
176                          operands[2], operands[3], operands[4]);
177     DONE;
178   })
179
180 (define_mode_attr atomic_op_operand
181   [(QI "reg_or_int_operand")
182    (HI "reg_or_int_operand")
183    (SI "reg_or_int_operand")
184    (DI "s_register_operand")])
185
186 (define_mode_attr atomic_op_str
187   [(QI "rn") (HI "rn") (SI "rn") (DI "r")])
188
189 (define_insn_and_split "atomic_<sync_optab><mode>"
190   [(set (match_operand:QHSD 0 "mem_noofs_operand" "+Ua")
191         (unspec_volatile:QHSD
192           [(syncop:QHSD (match_dup 0)
193              (match_operand:QHSD 1 "<atomic_op_operand>" "<atomic_op_str>"))
194            (match_operand:SI 2 "const_int_operand")]            ;; model
195           VUNSPEC_ATOMIC_OP))
196    (clobber (reg:CC CC_REGNUM))
197    (clobber (match_scratch:QHSD 3 "=&r"))
198    (clobber (match_scratch:SI 4 "=&r"))]
199   "<sync_predtab>"
200   "#"
201   "&& reload_completed"
202   [(const_int 0)]
203   {
204     arm_split_atomic_op (<CODE>, NULL, operands[3], operands[0],
205                          operands[1], operands[2], operands[4]);
206     DONE;
207   })
208
209 (define_insn_and_split "atomic_nand<mode>"
210   [(set (match_operand:QHSD 0 "mem_noofs_operand" "+Ua")
211         (unspec_volatile:QHSD
212           [(not:QHSD
213              (and:QHSD (match_dup 0)
214                (match_operand:QHSD 1 "<atomic_op_operand>" "<atomic_op_str>")))
215            (match_operand:SI 2 "const_int_operand")]            ;; model
216           VUNSPEC_ATOMIC_OP))
217    (clobber (reg:CC CC_REGNUM))
218    (clobber (match_scratch:QHSD 3 "=&r"))
219    (clobber (match_scratch:SI 4 "=&r"))]
220   "<sync_predtab>"
221   "#"
222   "&& reload_completed"
223   [(const_int 0)]
224   {
225     arm_split_atomic_op (NOT, NULL, operands[3], operands[0],
226                          operands[1], operands[2], operands[4]);
227     DONE;
228   })
229
230 (define_insn_and_split "atomic_fetch_<sync_optab><mode>"
231   [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
232         (match_operand:QHSD 1 "mem_noofs_operand" "+Ua"))
233    (set (match_dup 1)
234         (unspec_volatile:QHSD
235           [(syncop:QHSD (match_dup 1)
236              (match_operand:QHSD 2 "<atomic_op_operand>" "<atomic_op_str>"))
237            (match_operand:SI 3 "const_int_operand")]            ;; model
238           VUNSPEC_ATOMIC_OP))
239    (clobber (reg:CC CC_REGNUM))
240    (clobber (match_scratch:QHSD 4 "=&r"))
241    (clobber (match_scratch:SI 5 "=&r"))]
242   "<sync_predtab>"
243   "#"
244   "&& reload_completed"
245   [(const_int 0)]
246   {
247     arm_split_atomic_op (<CODE>, operands[0], operands[4], operands[1],
248                          operands[2], operands[3], operands[5]);
249     DONE;
250   })
251
252 (define_insn_and_split "atomic_fetch_nand<mode>"
253   [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
254         (match_operand:QHSD 1 "mem_noofs_operand" "+Ua"))
255    (set (match_dup 1)
256         (unspec_volatile:QHSD
257           [(not:QHSD
258              (and:QHSD (match_dup 1)
259                (match_operand:QHSD 2 "<atomic_op_operand>" "<atomic_op_str>")))
260            (match_operand:SI 3 "const_int_operand")]            ;; model
261           VUNSPEC_ATOMIC_OP))
262    (clobber (reg:CC CC_REGNUM))
263    (clobber (match_scratch:QHSD 4 "=&r"))
264    (clobber (match_scratch:SI 5 "=&r"))]
265   "<sync_predtab>"
266   "#"
267   "&& reload_completed"
268   [(const_int 0)]
269   {
270     arm_split_atomic_op (NOT, operands[0], operands[4], operands[1],
271                          operands[2], operands[3], operands[5]);
272     DONE;
273   })
274
275 (define_insn_and_split "atomic_<sync_optab>_fetch<mode>"
276   [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
277         (syncop:QHSD
278           (match_operand:QHSD 1 "mem_noofs_operand" "+Ua")
279           (match_operand:QHSD 2 "<atomic_op_operand>" "<atomic_op_str>")))
280    (set (match_dup 1)
281         (unspec_volatile:QHSD
282           [(match_dup 1) (match_dup 2)
283            (match_operand:SI 3 "const_int_operand")]            ;; model
284           VUNSPEC_ATOMIC_OP))
285    (clobber (reg:CC CC_REGNUM))
286    (clobber (match_scratch:SI 4 "=&r"))]
287   "<sync_predtab>"
288   "#"
289   "&& reload_completed"
290   [(const_int 0)]
291   {
292     arm_split_atomic_op (<CODE>, NULL, operands[0], operands[1],
293                          operands[2], operands[3], operands[4]);
294     DONE;
295   })
296
297 (define_insn_and_split "atomic_nand_fetch<mode>"
298   [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
299         (not:QHSD
300           (and:QHSD
301             (match_operand:QHSD 1 "mem_noofs_operand" "+Ua")
302             (match_operand:QHSD 2 "<atomic_op_operand>" "<atomic_op_str>"))))
303    (set (match_dup 1)
304         (unspec_volatile:QHSD
305           [(match_dup 1) (match_dup 2)
306            (match_operand:SI 3 "const_int_operand")]            ;; model
307           VUNSPEC_ATOMIC_OP))
308    (clobber (reg:CC CC_REGNUM))
309    (clobber (match_scratch:SI 4 "=&r"))]
310   "<sync_predtab>"
311   "#"
312   "&& reload_completed"
313   [(const_int 0)]
314   {
315     arm_split_atomic_op (NOT, NULL, operands[0], operands[1],
316                          operands[2], operands[3], operands[4]);
317     DONE;
318   })
319
320 (define_insn "arm_load_exclusive<mode>"
321   [(set (match_operand:SI 0 "s_register_operand" "=r")
322         (zero_extend:SI
323           (unspec_volatile:NARROW
324             [(match_operand:NARROW 1 "mem_noofs_operand" "Ua")]
325             VUNSPEC_LL)))]
326   "TARGET_HAVE_LDREXBH"
327   "ldrex<sync_sfx>%?\t%0, %C1"
328   [(set_attr "predicable" "yes")])
329
330 (define_insn "arm_load_exclusivesi"
331   [(set (match_operand:SI 0 "s_register_operand" "=r")
332         (unspec_volatile:SI
333           [(match_operand:SI 1 "mem_noofs_operand" "Ua")]
334           VUNSPEC_LL))]
335   "TARGET_HAVE_LDREX"
336   "ldrex%?\t%0, %C1"
337   [(set_attr "predicable" "yes")])
338
339 (define_insn "arm_load_exclusivedi"
340   [(set (match_operand:DI 0 "s_register_operand" "=r")
341         (unspec_volatile:DI
342           [(match_operand:DI 1 "mem_noofs_operand" "Ua")]
343           VUNSPEC_LL))]
344   "TARGET_HAVE_LDREXD"
345   "ldrexd%?\t%0, %H0, %C1"
346   [(set_attr "predicable" "yes")])
347
348 (define_insn "arm_store_exclusive<mode>"
349   [(set (match_operand:SI 0 "s_register_operand" "=&r")
350         (unspec_volatile:SI [(const_int 0)] VUNSPEC_SC))
351    (set (match_operand:QHSD 1 "mem_noofs_operand" "=Ua")
352         (unspec_volatile:QHSD
353           [(match_operand:QHSD 2 "s_register_operand" "r")]
354           VUNSPEC_SC))]
355   "<sync_predtab>"
356   {
357     if (<MODE>mode == DImode)
358       {
359         rtx value = operands[2];
360         /* The restrictions on target registers in ARM mode are that the two
361            registers are consecutive and the first one is even; Thumb is
362            actually more flexible, but DI should give us this anyway.
363            Note that the 1st register always gets the lowest word in memory.  */
364         gcc_assert ((REGNO (value) & 1) == 0 || TARGET_THUMB2);
365         operands[3] = gen_rtx_REG (SImode, REGNO (value) + 1);
366         return "strexd%?\t%0, %2, %3, %C1";
367       }
368     return "strex<sync_sfx>%?\t%0, %2, %C1";
369   }
370   [(set_attr "predicable" "yes")])