annotate gcc/config/tilegx/sync.md @ 111:04ced10e8804

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