Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/tilegx/sync.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
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 }) |