xref: /netbsd/external/gpl3/gcc/dist/gcc/config/c6x/sync.md (revision f0fbc68b)
1;; GCC machine description for C6X synchronization instructions.
2;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
3;;
4;; This file is part of GCC.
5;;
6;; GCC is free software; you can redistribute it and/or modify
7;; it under the terms of the GNU General Public License as published by
8;; the Free Software Foundation; either version 3, or (at your option)
9;; any later version.
10;;
11;; GCC is distributed in the hope that it will be useful,
12;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;; GNU General Public License for more details.
15;;
16;; You should have received a copy of the GNU General Public License
17;; along with GCC; see the file COPYING3.  If not see
18;; <http://www.gnu.org/licenses/>.
19
20;; C64X+ has atomic instructions, but they are not atomic on all
21;; devices and have other problems.  We use normal loads and stores,
22;; and place them in overlapping branch shadows to ensure interrupts
23;; are disabled during the sequence, which guarantees atomicity on all
24;; single-core systems.
25
26(define_code_iterator FETCHOP [plus minus ior xor and])
27(define_code_attr fetchop_name
28  [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
29(define_code_attr fetchop_pred
30  [(plus "reg_or_scst5_operand") (minus "register_operand")
31   (ior "reg_or_scst5_operand") (xor "reg_or_scst5_operand")
32   (and "reg_or_scst5_operand")])
33(define_code_attr fetchop_constr
34  [(plus "bIs5") (minus "b") (ior "bIs5") (xor "bIs5") (and "bIs5")])
35(define_code_attr fetchop_opcode
36  [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
37(define_code_attr fetchop_inops02
38  [(plus "%2, %0") (minus "%0, %2") (ior "%2, %0") (xor "%2, %0")
39   (and "%2, %0")])
40(define_code_attr fetchop_inops21
41  [(plus "%1, %2") (minus "%2, %1") (ior "%1, %2") (xor "%1, %2")
42   (and "%1, %2")])
43
44(define_expand "sync_compare_and_swapsi"
45  [(parallel
46     [(set (match_operand:SI 0 "register_operand" "")
47	   (match_operand:SI 1 "memory_operand" ""))
48      (set (match_dup 1)
49	   (unspec_volatile:SI
50	     [(match_operand:SI 2 "register_operand" "")
51	      (match_operand:SI 3 "register_operand" "")]
52	     UNSPECV_CAS))
53      (clobber (match_scratch:SI 4 ""))])]
54  ""
55{
56})
57
58(define_expand "sync_<fetchop_name>si"
59  [(parallel
60    [(set (match_operand:SI 0 "memory_operand" "")
61	  (unspec:SI
62	   [(FETCHOP:SI (match_dup 0)
63			(match_operand:SI 1 "<fetchop_pred>" ""))]
64	   UNSPEC_ATOMIC))
65     (clobber (match_scratch:SI 2 ""))])]
66  ""
67{
68})
69
70(define_expand "sync_old_<fetchop_name>si"
71  [(parallel
72    [(set (match_operand:SI 0 "register_operand" "")
73	  (match_operand:SI 1 "memory_operand" ""))
74     (set (match_dup 1)
75	  (unspec:SI
76	   [(FETCHOP:SI (match_dup 1)
77			(match_operand:SI 2 "<fetchop_pred>" ""))]
78	   UNSPEC_ATOMIC))
79     (clobber (match_scratch:SI 3 ""))])]
80  ""
81{
82})
83
84(define_expand "sync_new_<fetchop_name>si"
85  [(parallel
86    [(set (match_operand:SI 0 "register_operand" "")
87	  (FETCHOP:SI (match_operand:SI 1 "memory_operand" "")
88		      (match_operand:SI 2 "<fetchop_pred>" "")))
89     (set (match_dup 1)
90	  (unspec:SI [(FETCHOP:SI (match_dup 1) (match_dup 2))]
91		     UNSPEC_ATOMIC))
92     (clobber (match_scratch:SI 3 ""))])]
93  ""
94{
95})
96
97(define_expand "sync_nandsi"
98  [(parallel
99    [(set (match_operand:SI 0 "memory_operand" "")
100	  (unspec:SI
101	   [(not:SI (and:SI (match_dup 0)
102			    (match_operand:SI 1 "reg_or_scst5_operand" "")))]
103	   UNSPEC_ATOMIC))
104     (clobber (match_scratch:SI 2 ""))])]
105  ""
106{
107})
108
109(define_expand "sync_old_nandsi"
110  [(parallel
111    [(set (match_operand:SI 0 "register_operand" "")
112	  (match_operand:SI 1 "memory_operand" ""))
113     (set (match_dup 1)
114	  (unspec:SI
115	   [(not:SI (and:SI (match_dup 1)
116		    (match_operand:SI 2 "reg_or_scst5_operand" "")))]
117	   UNSPEC_ATOMIC))
118     (clobber (match_scratch:SI 3 ""))])]
119  ""
120{
121})
122
123(define_expand "sync_new_nandsi"
124  [(parallel
125    [(set (match_operand:SI 0 "register_operand" "")
126	  (not:SI (and:SI (match_operand:SI 1 "memory_operand" "")
127			  (match_operand:SI 2 "reg_or_scst5_operand" ""))))
128     (set (match_dup 1)
129	  (unspec:SI [(not:SI (and:SI (match_dup 1) (match_dup 2)))]
130		     UNSPEC_ATOMIC))
131     (clobber (match_scratch:SI 3 ""))])]
132  ""
133{
134})
135
136(define_insn "*sync_compare_and_swapsi"
137  [(set (match_operand:SI 0 "register_operand" "=&b")
138	(match_operand:SI 1 "memory_operand" "+m"))
139   (set (match_dup 1)
140	(unspec_volatile:SI
141	  [(match_operand:SI 2 "register_operand" "B")
142	   (match_operand:SI 3 "register_operand" "b")]
143	  UNSPECV_CAS))
144   (clobber (match_scratch:SI 4 "=&B"))]
145  ""
146  "0: b .s2 1f ; 0\n\\
147   || ldw .d%U1t%U0 %1, %0\n\\
148   nop 4\n\\
149|| b .s2 2f ; 1\n\\
150   cmpeq .l2 %0, %2, %2 ; 5\n\\
1511: [%2] stw .d%U1t%U3 %3, %1 ; 6\n\\
1522:"
153  [(set_attr "type" "atomic")])
154
155(define_insn "sync_<fetchop_name>si_insn"
156  [(set (match_operand:SI 0 "memory_operand" "+m")
157	(unspec:SI
158	  [(FETCHOP:SI (match_dup 0)
159	     (match_operand:SI 1 "<fetchop_pred>" "<fetchop_constr>"))]
160	  UNSPEC_ATOMIC))
161   (clobber (match_scratch:SI 2 "=&B"))]
162  ""
163  "0: b .s2 1f ; 0\n\\
164|| ldw .d%U0t%U2 %0, %2\n\\
165   nop 4\n\\
166|| b .s2 2f ; 1\n\\
167   <fetchop_opcode> .l2 <fetchop_inops21>, %2 ; 5\n\\
1681: stw .d%U0t%U2 %2, %0 ; 6\n\\
1692:"
170  [(set_attr "type" "atomic")])
171
172(define_insn "sync_old_<fetchop_name>si_insn"
173  [(set (match_operand:SI 0 "register_operand" "=&b")
174	(match_operand:SI 1 "memory_operand" "+m"))
175   (set (match_dup 1)
176	(unspec:SI
177	  [(FETCHOP:SI (match_dup 1)
178	     (match_operand:SI 2 "<fetchop_pred>" "<fetchop_constr>"))]
179	  UNSPEC_ATOMIC))
180   (clobber (match_scratch:SI 3 "=&B"))]
181  ""
182  "0: b .s2 1f ; 0\n\\
183|| ldw .d%U1t%U0 %1, %0\n\\
184   nop 4\n\\
185|| b .s2 2f ; 1\n\\
186   <fetchop_opcode> .l2 <fetchop_inops02>, %3 ; 5\n\\
1871: stw .d%U1t%U3 %3, %1 ; 6\n\\
1882:"
189  [(set_attr "type" "atomic")])
190
191(define_insn "sync_new_<fetchop_name>si_insn"
192  [(set (match_operand:SI 0 "register_operand" "=&b")
193	(FETCHOP:SI (match_operand:SI 1 "memory_operand" "+m")
194	   (match_operand:SI 2 "<fetchop_pred>" "<fetchop_constr>")))
195   (set (match_dup 1)
196	(unspec:SI
197	  [(FETCHOP:SI (match_dup 1)
198		       (match_dup 2))]
199	  UNSPEC_ATOMIC))
200   (clobber (match_scratch:SI 3 "=&B"))]
201  ""
202  "0: b .s2 1f ; 0\n\\
203|| ldw .d%U1t%U0 %1, %0\n\\
204   nop 4\n\\
205|| b .s2 2f ; 1\n\\
206   <fetchop_opcode> .l2 <fetchop_inops02>, %0 ; 5\n\\
2071: stw .d%U1t%U0 %0, %1 ; 6\n\\
2082:"
209  [(set_attr "type" "atomic")])
210
211(define_insn "sync_nandsi_insn"
212  [(set (match_operand:SI 0 "memory_operand" "+m")
213	(unspec:SI
214	  [(not:SI (and:SI (match_dup 0)
215			   (match_operand:SI 1 "reg_or_scst5_operand" "bIs5")))]
216	  UNSPEC_ATOMIC))
217   (clobber (match_scratch:SI 2 "=&B"))]
218  ""
219  "0: b .s2 1f ; 0\n\\
220|| ldw .d%U0t%U2 %0, %2\n\\
221   nop 1\n\\
222   nop 3\n\\
223|| b .s2 2f ; 2\n\\
224   and .l2 %1, %2, %2 ; 5\n\\
2251: not .l2 %2, %2 ; 6\n\\
226   stw .d%U0t%U2 %2, %0 ; 7\n\\
2272:"
228  [(set_attr "type" "atomic")])
229
230(define_insn "sync_old_nandsi_insn"
231  [(set (match_operand:SI 0 "register_operand" "=&b")
232	(match_operand:SI 1 "memory_operand" "+m"))
233   (set (match_dup 1)
234	(unspec:SI
235	  [(not:SI (and:SI (match_dup 1)
236			   (match_operand:SI 2 "reg_or_scst5_operand" "bIs5")))]
237	  UNSPEC_ATOMIC))
238   (clobber (match_scratch:SI 3 "=&B"))]
239  ""
240  "0: b .s2 1f ; 0\n\\
241|| ldw .d%U1t%U0 %1, %0\n\\
242   nop 1\n\\
243   nop 3\n\\
244|| b .s2 2f ; 2\n\\
245   and .l2 %2, %0, %3 ; 5\n\\
2461: not .l2 %3, %3 ; 6\n\\
247   stw .d%U1t%U3 %3, %1 ; 7\n\\
2482:"
249  [(set_attr "type" "atomic")])
250
251(define_insn "sync_new_nandsi_insn"
252  [(set (match_operand:SI 0 "register_operand" "=&b")
253	(not:SI (and:SI (match_operand:SI 1 "memory_operand" "+m")
254			(match_operand:SI 2 "reg_or_scst5_operand" "bIs5"))))
255   (set (match_dup 1)
256	(unspec:SI
257	  [(not:SI (and:SI (match_dup 1) (match_dup 2)))]
258	  UNSPEC_ATOMIC))
259   (clobber (match_scratch:SI 3 "=&B"))]
260  ""
261  "0: b .s2 1f ; 0\n\\
262|| ldw .d%U1t%U0 %1, %0\n\\
263   nop 1\n\\
264   nop 3\n\\
265|| b .s2 2f ; 2\n\\
266   and .l2 %2, %0, %0 ; 5\n\\
2671: not .l2 %0, %0 ; 6\n\\
268   stw .d%U1t%U0 %0, %1 ; 7\n\\
2692:"
270  [(set_attr "type" "atomic")])
271