]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/tilegx/sync.md
testsuite, Darwin: Fix darwin-comm-1.c error messages for Darwin <= 10.
[thirdparty/gcc.git] / gcc / config / tilegx / sync.md
CommitLineData
dd552284
WL
1;; GCC machine description for Tilera TILE-Gx synchronization
2;; instructions.
7adcbafe 3;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
dd552284
WL
4;; Contributed by Walter Lee (walt@tilera.com)
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
10;; by the Free Software Foundation; either version 3, or (at your
11;; option) any later version.
12;;
13;; GCC is distributed in the hope that it will be useful, but WITHOUT
14;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16;; 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_code_iterator fetchop [plus ior and])
23(define_code_attr fetchop_name [(plus "add") (ior "or") (and "and")])
24
25(define_insn "mtspr_cmpexch<mode>"
26 [(set (reg:I48MODE TILEGX_CMPEXCH_REG)
27 (unspec_volatile:I48MODE
28 [(match_operand:I48MODE 0 "reg_or_0_operand" "rO")]
29 UNSPEC_SPR_MOVE))]
30 ""
31 "mtspr\tCMPEXCH_VALUE, %r0"
32 [(set_attr "type" "X1")])
33
34
35(define_expand "atomic_compare_and_swap<mode>"
36 [(match_operand:DI 0 "register_operand" "") ;; bool output
37 (match_operand:I48MODE 1 "register_operand" "") ;; val output
38 (match_operand:I48MODE 2 "nonautoincmem_operand" "") ;; memory
39 (match_operand:I48MODE 3 "reg_or_0_operand" "") ;; expected value
40 (match_operand:I48MODE 4 "reg_or_0_operand" "") ;; desired value
41 (match_operand:SI 5 "const_int_operand" "") ;; is_weak
42 (match_operand:SI 6 "const_int_operand" "") ;; mod_s
43 (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
44 ""
45{
46 enum memmodel mod_s = (enum memmodel) INTVAL (operands[6]);
47
48 if (operands[3] != const0_rtx)
49 operands[3] = force_reg (<MODE>mode, operands[3]);
50 if (operands[4] != const0_rtx)
51 operands[4] = force_reg (<MODE>mode, operands[4]);
52
53 tilegx_pre_atomic_barrier (mod_s);
54 emit_insn (gen_mtspr_cmpexch<mode> (operands[3]));
55 emit_insn (gen_atomic_compare_and_swap_bare<mode> (operands[1], operands[2],
56 operands[4]));
57 tilegx_post_atomic_barrier (mod_s);
58 emit_insn (gen_insn_cmpeq_<mode>di (operands[0], operands[1], operands[3]));
59 DONE;
60})
61
62
63(define_insn "atomic_compare_and_swap_bare<mode>"
64 [(set (match_operand:I48MODE 0 "register_operand" "=r")
65 (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
66 (set (match_dup 1)
67 (unspec_volatile:I48MODE
68 [(match_dup 1)
69 (reg:I48MODE TILEGX_CMPEXCH_REG)
70 (match_operand:I48MODE 2 "reg_or_0_operand" "rO")]
71 UNSPEC_CMPXCHG))]
72 ""
73 "cmpexch<four_if_si>\t%0, %1, %r2"
9b0370aa 74 [(set_attr "type" "X1_remote")])
dd552284
WL
75
76
77(define_expand "atomic_exchange<mode>"
78 [(match_operand:I48MODE 0 "register_operand" "") ;; result
79 (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
80 (match_operand:I48MODE 2 "reg_or_0_operand" "") ;; input
81 (match_operand:SI 3 "const_int_operand" "")] ;; model
82 ""
83{
84 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
85
86 tilegx_pre_atomic_barrier (model);
87 emit_insn (gen_atomic_exchange_bare<mode> (operands[0], operands[1],
88 operands[2]));
89 tilegx_post_atomic_barrier (model);
90 DONE;
91})
92
93
94(define_insn "atomic_exchange_bare<mode>"
95 [(set (match_operand:I48MODE 0 "register_operand" "=r")
96 (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
97 (set (match_dup 1)
98 (unspec_volatile:I48MODE
99 [(match_operand:I48MODE 2 "reg_or_0_operand" "rO")]
100 UNSPEC_XCHG))]
101 ""
102 "exch<four_if_si>\t%0, %1, %r2"
9b0370aa 103 [(set_attr "type" "X1_remote")])
dd552284
WL
104
105
106(define_expand "atomic_fetch_<fetchop_name><mode>"
107 [(match_operand:I48MODE 0 "register_operand" "") ;; result
108 (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
109 (unspec_volatile:I48MODE
110 [(fetchop:I48MODE
111 (match_dup 1)
112 (match_operand:I48MODE 2 "reg_or_0_operand" ""))] ;; value
113 UNSPEC_ATOMIC)
114 (match_operand:SI 3 "const_int_operand" "")] ;; model
115 ""
116{
117 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
118
119 tilegx_pre_atomic_barrier (model);
120 emit_insn (gen_atomic_fetch_<fetchop_name>_bare<mode> (operands[0],
121 operands[1],
122 operands[2]));
7eb0f141 123 tilegx_post_atomic_barrier (model);
dd552284
WL
124 DONE;
125})
126
127
128(define_insn "atomic_fetch_<fetchop_name>_bare<mode>"
129 [(set (match_operand:I48MODE 0 "register_operand" "=r")
130 (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
131 (set (match_dup 1)
132 (unspec_volatile:I48MODE
133 [(fetchop:I48MODE
134 (match_dup 1)
135 (match_operand:I48MODE 2 "reg_or_0_operand" "rO"))]
136 UNSPEC_ATOMIC))]
137 ""
138 "fetch<fetchop_name><four_if_si>\t%0, %1, %r2"
9b0370aa 139 [(set_attr "type" "X1_remote")])
dd552284
WL
140
141
142(define_expand "atomic_fetch_sub<mode>"
143 [(match_operand:I48MODE 0 "register_operand" "") ;; result
144 (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
145 (unspec_volatile:I48MODE
146 [(minus:I48MODE
147 (match_dup 1)
148 (match_operand:I48MODE 2 "reg_or_0_operand" ""))] ;; value
149 UNSPEC_ATOMIC)
150 (match_operand:SI 3 "const_int_operand" "")] ;; model
151 ""
152{
6bb0e248 153 rtx addend;
dd552284
WL
154 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
155
156 if (operands[2] != const0_rtx)
6bb0e248
WL
157 {
158 addend = gen_reg_rtx (<MODE>mode);
159 emit_move_insn (addend,
160 gen_rtx_MINUS (<MODE>mode, const0_rtx, operands[2]));
161 }
162 else
163 addend = operands[2];
dd552284
WL
164
165 tilegx_pre_atomic_barrier (model);
166 emit_insn (gen_atomic_fetch_add_bare<mode> (operands[0],
167 operands[1],
6bb0e248 168 addend));
2bcf3c5c 169 tilegx_post_atomic_barrier (model);
dd552284
WL
170 DONE;
171})
327a1118
WL
172
173
174(define_expand "atomic_test_and_set"
175 [(match_operand:QI 0 "register_operand" "") ;; bool output
176 (match_operand:QI 1 "nonautoincmem_operand" "+U") ;; memory
177 (match_operand:SI 2 "const_int_operand" "")] ;; model
178 ""
179{
341c653c 180 rtx addr, aligned_addr, aligned_mem, offset, word, shmt, tmp;
327a1118
WL
181 rtx result = operands[0];
182 rtx mem = operands[1];
183 enum memmodel model = (enum memmodel) INTVAL (operands[2]);
184
185 addr = force_reg (Pmode, XEXP (mem, 0));
186
187 aligned_addr = gen_reg_rtx (Pmode);
188 emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-8)));
189
190 aligned_mem = change_address (mem, DImode, aligned_addr);
191 set_mem_alias_set (aligned_mem, 0);
192
341c653c
WL
193 tmp = gen_reg_rtx (Pmode);
194 if (BYTES_BIG_ENDIAN)
195 {
196 emit_move_insn (gen_lowpart (DImode, tmp),
197 gen_rtx_NOT (DImode, gen_lowpart (DImode, addr)));
198 }
199 else
200 {
201 tmp = addr;
202 }
203
327a1118 204 offset = gen_reg_rtx (DImode);
341c653c 205 emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, tmp),
327a1118
WL
206 GEN_INT (7)));
207
341c653c
WL
208 tmp = gen_reg_rtx (DImode);
209 emit_move_insn (tmp, GEN_INT (1));
327a1118
WL
210
211 shmt = gen_reg_rtx (DImode);
212 emit_move_insn (shmt, gen_rtx_ASHIFT (DImode, offset, GEN_INT (3)));
213
214 word = gen_reg_rtx (DImode);
341c653c 215 emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp,
327a1118
WL
216 gen_lowpart (SImode, shmt)));
217
341c653c 218 tmp = gen_reg_rtx (DImode);
327a1118 219 tilegx_pre_atomic_barrier (model);
341c653c 220 emit_insn (gen_atomic_fetch_or_baredi (tmp, aligned_mem, word));
327a1118
WL
221 tilegx_post_atomic_barrier (model);
222
223 emit_move_insn (gen_lowpart (DImode, result),
341c653c 224 gen_rtx_LSHIFTRT (DImode, tmp,
327a1118
WL
225 gen_lowpart (SImode, shmt)));
226 DONE;
227})