Add <bit> and <version> to freestanding headers
[official-gcc.git] / gcc / config / tilegx / sync.md
blob4a15c00838e24b7a328f25b9e3bb7a2192a9d5b6
1 ;; GCC machine description for Tilera TILE-Gx synchronization
2 ;; instructions.
3 ;; Copyright (C) 2011-2018 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.
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.
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/>.
22 (define_code_iterator fetchop [plus ior and])
23 (define_code_attr fetchop_name [(plus "add") (ior "or") (and "and")])
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")])
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   ""
46   enum memmodel mod_s = (enum memmodel) INTVAL (operands[6]);
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]);
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;
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")])
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   ""
84   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
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;
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")])
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   ""
117   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
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;
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")])
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   ""
153   rtx addend;
154   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
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];
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;
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   ""
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]);
185   addr = force_reg (Pmode, XEXP (mem, 0));
187   aligned_addr = gen_reg_rtx (Pmode);
188   emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-8)));
190   aligned_mem = change_address (mem, DImode, aligned_addr);
191   set_mem_alias_set (aligned_mem, 0);
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     }
204   offset = gen_reg_rtx (DImode);
205   emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, tmp),
206                                        GEN_INT (7)));
208   tmp = gen_reg_rtx (DImode);
209   emit_move_insn (tmp, GEN_INT (1));
211   shmt = gen_reg_rtx (DImode);
212   emit_move_insn (shmt, gen_rtx_ASHIFT (DImode, offset, GEN_INT (3)));
214   word = gen_reg_rtx (DImode);
215   emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp,
216                                         gen_lowpart (SImode, shmt)));
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);
223   emit_move_insn (gen_lowpart (DImode, result),
224                   gen_rtx_LSHIFTRT (DImode, tmp,
225                                     gen_lowpart (SImode, shmt)));
226   DONE;