* config/sh/linux.h (TARGET_DEFAULT): Add MASK_SOFT_ATOMIC.
[official-gcc.git] / gcc / config / sh / sync.md
blobec4ec517b45d16c4b349030b7088272ac6d8aa02
1 ;; GCC machine description for SH synchronization instructions.
2 ;; Copyright (C) 2011
3 ;; Free Software Foundation, Inc.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 (define_c_enum "unspec" [
22   UNSPEC_ATOMIC
25 (define_c_enum "unspecv" [
26   UNSPECV_CMPXCHG_1
27   UNSPECV_CMPXCHG_2
28   UNSPECV_CMPXCHG_3
31 (define_mode_iterator I124 [QI HI SI])
33 (define_mode_attr i124suffix [(QI "b") (HI "w") (SI "l")])
34 (define_mode_attr i124extend_insn [(QI "exts.b") (HI "exts.w") (SI "mov")])
36 (define_code_iterator FETCHOP [plus minus ior xor and])
37 (define_code_attr fetchop_name
38   [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
39 (define_code_attr fetchop_insn
40   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
42 ;; Linux specific atomic patterns for the Renesas / SuperH SH CPUs.
43 ;; Linux kernel for SH3/4 has implemented the support for software
44 ;; atomic sequences.
46 (define_expand "atomic_compare_and_swap<mode>"
47   [(match_operand:QI 0 "register_operand" "")           ;; bool success output
48    (match_operand:I124 1 "register_operand" "")         ;; oldval output
49    (match_operand:I124 2 "memory_operand" "")           ;; memory
50    (match_operand:I124 3 "register_operand" "")         ;; expected input
51    (match_operand:I124 4 "register_operand" "")         ;; newval input
52    (match_operand:SI 5 "const_int_operand" "")          ;; is_weak
53    (match_operand:SI 6 "const_int_operand" "")          ;; success model
54    (match_operand:SI 7 "const_int_operand" "")]         ;; failure model
55   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
57   rtx addr;
59   addr = force_reg (Pmode, XEXP (operands[2], 0));
60   emit_insn (gen_atomic_compare_and_swap<mode>_soft
61              (gen_lowpart (SImode, operands[1]), addr, operands[3],
62               operands[4]));
63   if (<MODE>mode == QImode)
64     emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[1]),
65                                      operands[1]));
66   else if (<MODE>mode == HImode)
67     emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[1]),
68                                      operands[1]));
69   emit_insn (gen_movqi (operands[0], gen_rtx_REG (QImode, T_REG)));
70   DONE;
73 (define_insn "atomic_compare_and_swap<mode>_soft"
74   [(set (match_operand:SI 0 "register_operand" "=&u")
75         (unspec_volatile:SI
76           [(mem:I124 (match_operand:SI 1 "register_operand" "u"))
77            (match_operand:I124 2 "register_operand" "u")
78            (match_operand:I124 3 "register_operand" "u")]
79           UNSPECV_CMPXCHG_1))
80    (set (mem:I124 (match_dup 1))
81         (unspec_volatile:I124 [(const_int 0)] UNSPECV_CMPXCHG_2))
82    (set (reg:QI T_REG)
83         (unspec_volatile:QI [(const_int 0)] UNSPECV_CMPXCHG_3))
84    (clobber (match_scratch:SI 4 "=&u"))
85    (clobber (reg:SI R0_REG))
86    (clobber (reg:SI R1_REG))]
87   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
88   "*
90   return \"\\
91 mova\\t1f, r0\\n\\
92 \\t<i124extend_insn>\\t%2, %4\\n\\
93 \\tmov\\tr15, r1\\n\\
94 \\tmov\\t#(0f-1f), r15\\n\\
95 0:\\tmov.<i124suffix>\\t@%1, %0\\n\\
96 \\tcmp/eq\\t%0, %4\\n\\
97 \\tbf\\t1f\\n\\
98 \\tmov.<i124suffix>\\t%3, @%1\\n\\
99 \\t.align\\t2\\n\\
100 1:\\tmov\tr1, r15\";
102   [(set_attr "length" "20")])
104 (define_expand "atomic_fetch_<fetchop_name><mode>"
105   [(set (match_operand:I124 0 "register_operand" "")
106         (match_operand:I124 1 "memory_operand" ""))
107    (set (match_dup 1)
108         (unspec:I124
109           [(FETCHOP:I124 (match_dup 1)
110              (match_operand:I124 2 "register_operand" ""))]
111           UNSPEC_ATOMIC))
112    (match_operand:SI 3 "const_int_operand" "")]
113   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
115   rtx addr;
117   addr = force_reg (Pmode, XEXP (operands[1], 0));
118   emit_insn (gen_atomic_fetch_<fetchop_name><mode>_soft
119              (operands[0], addr, operands[2]));
120   if (<MODE>mode == QImode)
121     emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
122                                      operands[0]));
123   else if (<MODE>mode == HImode)
124     emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
125                                      operands[0]));
126   DONE;
129 (define_insn "atomic_fetch_<fetchop_name><mode>_soft"
130   [(set (match_operand:I124 0 "register_operand" "=&u")
131         (mem:I124 (match_operand:SI 1 "register_operand" "u")))
132    (set (mem:I124 (match_dup 1))
133         (unspec:I124
134           [(FETCHOP:I124 (mem:I124 (match_dup 1))
135              (match_operand:I124 2 "register_operand" "u"))]
136           UNSPEC_ATOMIC))
137    (clobber (match_scratch:I124 3 "=&u"))
138    (clobber (reg:SI R0_REG))
139    (clobber (reg:SI R1_REG))]
140   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
141   "*
143   return \"\\
144 mova\\t1f, r0\\n\\
145 \\tmov\\tr15, r1\\n\\
146 \\tmov\\t#(0f-1f), r15\\n\\
147 0:\\tmov.<i124suffix>\\t@%1, %0\\n\\
148 \\tmov\\t%0, %3\\n\\
149 \\t<fetchop_insn>\\t%2, %3\\n\\
150 \\tmov.<i124suffix>\\t%3, @%1\\n\\
151 \\t.align\\t2\\n\\
152 1:\\tmov\tr1, r15\";
154   [(set_attr "length" "18")])
156 (define_expand "atomic_fetch_nand<mode>"
157   [(set (match_operand:I124 0 "register_operand" "")
158         (match_operand:I124 1 "memory_operand" ""))
159    (set (match_dup 1)
160         (unspec:I124
161           [(not:I124 (and:I124 (match_dup 1)
162              (match_operand:I124 2 "register_operand" "")))]
163           UNSPEC_ATOMIC))
164    (match_operand:SI 3 "const_int_operand" "")]
165   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
167   rtx addr;
169   addr = force_reg (Pmode, XEXP (operands[1], 0));
170   emit_insn (gen_atomic_fetch_nand<mode>_soft
171              (operands[0], addr, operands[2]));
172   if (<MODE>mode == QImode)
173     emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
174                                      operands[0]));
175   else if (<MODE>mode == HImode)
176     emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
177                                      operands[0]));
178   DONE;
181 (define_insn "atomic_fetch_nand<mode>_soft"
182   [(set (match_operand:I124 0 "register_operand" "=&u")
183         (mem:I124 (match_operand:SI 1 "register_operand" "u")))
184    (set (mem:I124 (match_dup 1))
185         (unspec:I124
186           [(not:I124 (and:I124 (mem:I124 (match_dup 1))
187              (match_operand:I124 2 "register_operand" "u")))]
188           UNSPEC_ATOMIC))
189    (clobber (match_scratch:I124 3 "=&u"))
190    (clobber (reg:SI R0_REG))
191    (clobber (reg:SI R1_REG))]
192   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
193   "*
195   return \"\\
196 mova\\t1f, r0\\n\\
197 \\tmov\\tr15, r1\\n\\
198 \\tmov\\t#(0f-1f), r15\\n\\
199 0:\\tmov.<i124suffix>\\t@%1, %0\\n\\
200 \\tmov\\t%2, %3\\n\\
201 \\tand\\t%0, %3\\n\\
202 \\tnot\\t%3, %3\\n\\
203 \\tmov.<i124suffix>\\t%3, @%1\\n\\
204 \\t.align\\t2\\n\\
205 1:\\tmov\tr1, r15\";
207   [(set_attr "length" "20")])
209 (define_expand "atomic_<fetchop_name>_fetch<mode>"
210   [(set (match_operand:I124 0 "register_operand" "")
211         (FETCHOP:I124
212           (match_operand:I124 1 "memory_operand" "")
213           (match_operand:I124 2 "register_operand" "")))
214    (set (match_dup 1)
215         (unspec:I124
216           [(FETCHOP:I124 (match_dup 1) (match_dup 2))]
217           UNSPEC_ATOMIC))
218    (match_operand:SI 3 "const_int_operand" "")]
219   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
221   rtx addr;
223   addr = force_reg (Pmode, XEXP (operands[1], 0));
224   emit_insn (gen_atomic_<fetchop_name>_fetch<mode>_soft
225              (operands[0], addr, operands[2]));
226   if (<MODE>mode == QImode)
227     emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
228                                      operands[0]));
229   else if (<MODE>mode == HImode)
230     emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
231                                      operands[0]));
232   DONE;
235 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft"
236   [(set (match_operand:I124 0 "register_operand" "=&u")
237         (FETCHOP:I124
238           (mem:I124 (match_operand:SI 1 "register_operand" "u"))
239           (match_operand:I124 2 "register_operand" "u")))
240    (set (mem:I124 (match_dup 1))
241         (unspec:I124
242           [(FETCHOP:I124 (mem:I124 (match_dup 1)) (match_dup 2))]
243           UNSPEC_ATOMIC))
244    (clobber (reg:SI R0_REG))
245    (clobber (reg:SI R1_REG))]
246   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
247   "*
249   return \"\\
250 mova\\t1f, r0\\n\\
251 \\tmov\\tr15, r1\\n\\
252 \\tmov\\t#(0f-1f), r15\\n\\
253 0:\\tmov.<i124suffix>\\t@%1, %0\\n\\
254 \\t<fetchop_insn>\\t%2, %0\\n\\
255 \\tmov.<i124suffix>\\t%0, @%1\\n\\
256 \\t.align\\t2\\n\\
257 1:\\tmov\tr1, r15\";
259   [(set_attr "length" "16")])
261 (define_expand "atomic_nand_fetch<mode>"
262   [(set (match_operand:I124 0 "register_operand" "")
263         (not:I124 (and:I124
264           (match_operand:I124 1 "memory_operand" "")
265           (match_operand:I124 2 "register_operand" ""))))
266    (set (match_dup 1)
267         (unspec:I124
268           [(not:I124 (and:I124 (match_dup 1) (match_dup 2)))]
269           UNSPEC_ATOMIC))
270    (match_operand:SI 3 "const_int_operand" "")]
271   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
273   rtx addr;
275   addr = force_reg (Pmode, XEXP (operands[1], 0));
276   emit_insn (gen_atomic_nand_fetch<mode>_soft
277              (operands[0], addr, operands[2]));
278   if (<MODE>mode == QImode)
279     emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
280                                      operands[0]));
281   else if (<MODE>mode == HImode)
282     emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
283                                      operands[0]));
284   DONE;
287 (define_insn "atomic_nand_fetch<mode>_soft"
288   [(set (match_operand:I124 0 "register_operand" "=&u")
289         (not:I124 (and:I124
290           (mem:I124 (match_operand:SI 1 "register_operand" "u"))
291           (match_operand:I124 2 "register_operand" "u"))))
292    (set (mem:I124 (match_dup 1))
293         (unspec:I124
294           [(not:I124 (and:I124 (mem:I124 (match_dup 1)) (match_dup 2)))]
295           UNSPEC_ATOMIC))
296    (clobber (reg:SI R0_REG))
297    (clobber (reg:SI R1_REG))]
298   "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
299   "*
301   return \"\\
302 mova\\t1f, r0\\n\\
303 \\tmov\\tr15, r1\\n\\
304 \\tmov\\t#(0f-1f), r15\\n\\
305 0:\\tmov.<i124suffix>\\t@%1, %0\\n\\
306 \\tand\\t%2, %0\\n\\
307 \\tnot\\t%0, %0\\n\\
308 \\tmov.<i124suffix>\\t%0, @%1\\n\\
309 \\t.align\\t2\\n\\
310 1:\\tmov\tr1, r15\";
312   [(set_attr "length" "18")])