]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/sh/sync.md
linux.h (TARGET_DEFAULT): Add MASK_SOFT_ATOMIC.
[thirdparty/gcc.git] / gcc / config / sh / sync.md
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.
11 ;;
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.
16 ;;
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/>.
20
21 (define_c_enum "unspec" [
22 UNSPEC_ATOMIC
23 ])
24
25 (define_c_enum "unspecv" [
26 UNSPECV_CMPXCHG_1
27 UNSPECV_CMPXCHG_2
28 UNSPECV_CMPXCHG_3
29 ])
30
31 (define_mode_iterator I124 [QI HI SI])
32
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")])
35
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")])
41
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.
45
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"
56 {
57 rtx addr;
58
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;
71 })
72
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 "*
89 {
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\";
101 }"
102 [(set_attr "length" "20")])
103
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"
114 {
115 rtx addr;
116
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;
127 })
128
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 "*
142 {
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\";
153 }"
154 [(set_attr "length" "18")])
155
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"
166 {
167 rtx addr;
168
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;
179 })
180
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 "*
194 {
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\";
206 }"
207 [(set_attr "length" "20")])
208
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"
220 {
221 rtx addr;
222
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;
233 })
234
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 "*
248 {
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\";
258 }"
259 [(set_attr "length" "16")])
260
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"
272 {
273 rtx addr;
274
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;
285 })
286
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 "*
300 {
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\";
311 }"
312 [(set_attr "length" "18")])