111
|
1 ;; GCC machine description for Tilera TILE-Gx synchronization
|
|
2 ;; instructions.
|
|
3 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
|
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"
|
|
74 [(set_attr "type" "X1_remote")])
|
|
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"
|
|
103 [(set_attr "type" "X1_remote")])
|
|
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]));
|
|
123 tilegx_post_atomic_barrier (model);
|
|
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"
|
|
139 [(set_attr "type" "X1_remote")])
|
|
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 {
|
|
153 rtx addend;
|
|
154 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
|
|
155
|
|
156 if (operands[2] != const0_rtx)
|
|
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];
|
|
164
|
|
165 tilegx_pre_atomic_barrier (model);
|
|
166 emit_insn (gen_atomic_fetch_add_bare<mode> (operands[0],
|
|
167 operands[1],
|
|
168 addend));
|
|
169 tilegx_post_atomic_barrier (model);
|
|
170 DONE;
|
|
171 })
|
|
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 {
|
|
180 rtx addr, aligned_addr, aligned_mem, offset, word, shmt, tmp;
|
|
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
|
|
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
|
|
204 offset = gen_reg_rtx (DImode);
|
|
205 emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, tmp),
|
|
206 GEN_INT (7)));
|
|
207
|
|
208 tmp = gen_reg_rtx (DImode);
|
|
209 emit_move_insn (tmp, GEN_INT (1));
|
|
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);
|
|
215 emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp,
|
|
216 gen_lowpart (SImode, shmt)));
|
|
217
|
|
218 tmp = gen_reg_rtx (DImode);
|
|
219 tilegx_pre_atomic_barrier (model);
|
|
220 emit_insn (gen_atomic_fetch_or_baredi (tmp, aligned_mem, word));
|
|
221 tilegx_post_atomic_barrier (model);
|
|
222
|
|
223 emit_move_insn (gen_lowpart (DImode, result),
|
|
224 gen_rtx_LSHIFTRT (DImode, tmp,
|
|
225 gen_lowpart (SImode, shmt)));
|
|
226 DONE;
|
|
227 })
|