1 ;; GCC machine description for Tilera TILE-Gx synchronization
3 ;; Copyright (C) 2011, 2012
4 ;; Free Software Foundation, Inc.
5 ;; Contributed by Walter Lee (walt@tilera.com)
7 ;; This file is part of GCC.
9 ;; GCC is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published
11 ;; by the Free Software Foundation; either version 3, or (at your
12 ;; option) any later version.
14 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
15 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 ;; License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3. If not see
21 ;; <http://www.gnu.org/licenses/>.
23 (define_code_iterator fetchop [plus ior and])
24 (define_code_attr fetchop_name [(plus "add") (ior "or") (and "and")])
26 (define_insn "mtspr_cmpexch<mode>"
27 [(set (reg:I48MODE TILEGX_CMPEXCH_REG)
28 (unspec_volatile:I48MODE
29 [(match_operand:I48MODE 0 "reg_or_0_operand" "rO")]
32 "mtspr\tCMPEXCH_VALUE, %r0"
33 [(set_attr "type" "X1")])
36 (define_expand "atomic_compare_and_swap<mode>"
37 [(match_operand:DI 0 "register_operand" "") ;; bool output
38 (match_operand:I48MODE 1 "register_operand" "") ;; val output
39 (match_operand:I48MODE 2 "nonautoincmem_operand" "") ;; memory
40 (match_operand:I48MODE 3 "reg_or_0_operand" "") ;; expected value
41 (match_operand:I48MODE 4 "reg_or_0_operand" "") ;; desired value
42 (match_operand:SI 5 "const_int_operand" "") ;; is_weak
43 (match_operand:SI 6 "const_int_operand" "") ;; mod_s
44 (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
47 enum memmodel mod_s = (enum memmodel) INTVAL (operands[6]);
49 if (operands[3] != const0_rtx)
50 operands[3] = force_reg (<MODE>mode, operands[3]);
51 if (operands[4] != const0_rtx)
52 operands[4] = force_reg (<MODE>mode, operands[4]);
54 tilegx_pre_atomic_barrier (mod_s);
55 emit_insn (gen_mtspr_cmpexch<mode> (operands[3]));
56 emit_insn (gen_atomic_compare_and_swap_bare<mode> (operands[1], operands[2],
58 tilegx_post_atomic_barrier (mod_s);
59 emit_insn (gen_insn_cmpeq_<mode>di (operands[0], operands[1], operands[3]));
64 (define_insn "atomic_compare_and_swap_bare<mode>"
65 [(set (match_operand:I48MODE 0 "register_operand" "=r")
66 (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
68 (unspec_volatile:I48MODE
70 (reg:I48MODE TILEGX_CMPEXCH_REG)
71 (match_operand:I48MODE 2 "reg_or_0_operand" "rO")]
74 "cmpexch<four_if_si>\t%0, %1, %r2"
75 [(set_attr "type" "X1_L2")])
78 (define_expand "atomic_exchange<mode>"
79 [(match_operand:I48MODE 0 "register_operand" "") ;; result
80 (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
81 (match_operand:I48MODE 2 "reg_or_0_operand" "") ;; input
82 (match_operand:SI 3 "const_int_operand" "")] ;; model
85 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
87 tilegx_pre_atomic_barrier (model);
88 emit_insn (gen_atomic_exchange_bare<mode> (operands[0], operands[1],
90 tilegx_post_atomic_barrier (model);
95 (define_insn "atomic_exchange_bare<mode>"
96 [(set (match_operand:I48MODE 0 "register_operand" "=r")
97 (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
99 (unspec_volatile:I48MODE
100 [(match_operand:I48MODE 2 "reg_or_0_operand" "rO")]
103 "exch<four_if_si>\t%0, %1, %r2"
104 [(set_attr "type" "X1_2cycle")])
107 (define_expand "atomic_fetch_<fetchop_name><mode>"
108 [(match_operand:I48MODE 0 "register_operand" "") ;; result
109 (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
110 (unspec_volatile:I48MODE
113 (match_operand:I48MODE 2 "reg_or_0_operand" ""))] ;; value
115 (match_operand:SI 3 "const_int_operand" "")] ;; model
118 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
120 tilegx_pre_atomic_barrier (model);
121 emit_insn (gen_atomic_fetch_<fetchop_name>_bare<mode> (operands[0],
124 tilegx_pre_atomic_barrier (model);
129 (define_insn "atomic_fetch_<fetchop_name>_bare<mode>"
130 [(set (match_operand:I48MODE 0 "register_operand" "=r")
131 (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
133 (unspec_volatile:I48MODE
136 (match_operand:I48MODE 2 "reg_or_0_operand" "rO"))]
139 "fetch<fetchop_name><four_if_si>\t%0, %1, %r2"
140 [(set_attr "type" "X1_2cycle")])
143 (define_expand "atomic_fetch_sub<mode>"
144 [(match_operand:I48MODE 0 "register_operand" "") ;; result
145 (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
146 (unspec_volatile:I48MODE
149 (match_operand:I48MODE 2 "reg_or_0_operand" ""))] ;; value
151 (match_operand:SI 3 "const_int_operand" "")] ;; model
154 enum memmodel model = (enum memmodel) INTVAL (operands[3]);
156 if (operands[2] != const0_rtx)
157 emit_move_insn (operands[2], gen_rtx_NEG (<MODE>mode, operands[2]));
159 tilegx_pre_atomic_barrier (model);
160 emit_insn (gen_atomic_fetch_add_bare<mode> (operands[0],
163 tilegx_pre_atomic_barrier (model);