sync.md revision 1.1 1 1.1 mrg ;; GCC machine description for i386 synchronization instructions.
2 1.1 mrg ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
3 1.1 mrg ;; Free Software Foundation, Inc.
4 1.1 mrg ;;
5 1.1 mrg ;; This file is part of GCC.
6 1.1 mrg ;;
7 1.1 mrg ;; GCC is free software; you can redistribute it and/or modify
8 1.1 mrg ;; it under the terms of the GNU General Public License as published by
9 1.1 mrg ;; the Free Software Foundation; either version 3, or (at your option)
10 1.1 mrg ;; any later version.
11 1.1 mrg ;;
12 1.1 mrg ;; GCC is distributed in the hope that it will be useful,
13 1.1 mrg ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 mrg ;; GNU General Public License for more details.
16 1.1 mrg ;;
17 1.1 mrg ;; You should have received a copy of the GNU General Public License
18 1.1 mrg ;; along with GCC; see the file COPYING3. If not see
19 1.1 mrg ;; <http://www.gnu.org/licenses/>.
20 1.1 mrg
21 1.1 mrg (define_mode_iterator CASMODE
22 1.1 mrg [QI HI SI (DI "TARGET_64BIT || TARGET_CMPXCHG8B")
23 1.1 mrg (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
24 1.1 mrg (define_mode_iterator DCASMODE
25 1.1 mrg [(DI "!TARGET_64BIT && TARGET_CMPXCHG8B && !flag_pic")
26 1.1 mrg (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
27 1.1 mrg (define_mode_attr doublemodesuffix [(DI "8") (TI "16")])
28 1.1 mrg (define_mode_attr DCASHMODE [(DI "SI") (TI "DI")])
29 1.1 mrg
30 1.1 mrg (define_expand "memory_barrier"
31 1.1 mrg [(set (match_dup 0)
32 1.1 mrg (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
33 1.1 mrg ""
34 1.1 mrg {
35 1.1 mrg operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
36 1.1 mrg MEM_VOLATILE_P (operands[0]) = 1;
37 1.1 mrg
38 1.1 mrg if (!(TARGET_64BIT || TARGET_SSE2))
39 1.1 mrg {
40 1.1 mrg emit_insn (gen_memory_barrier_nosse (operands[0]));
41 1.1 mrg DONE;
42 1.1 mrg }
43 1.1 mrg })
44 1.1 mrg
45 1.1 mrg (define_insn "memory_barrier_nosse"
46 1.1 mrg [(set (match_operand:BLK 0 "" "")
47 1.1 mrg (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))
48 1.1 mrg (clobber (reg:CC FLAGS_REG))]
49 1.1 mrg "!(TARGET_64BIT || TARGET_SSE2)"
50 1.1 mrg "lock{%;} or{l}\t{$0, (%%esp)|DWORD PTR [esp], 0}"
51 1.1 mrg [(set_attr "memory" "unknown")])
52 1.1 mrg
53 1.1 mrg ;; ??? It would be possible to use cmpxchg8b on pentium for DImode
54 1.1 mrg ;; changes. It's complicated because the insn uses ecx:ebx as the
55 1.1 mrg ;; new value; note that the registers are reversed from the order
56 1.1 mrg ;; that they'd be in with (reg:DI 2 ecx). Similarly for TImode
57 1.1 mrg ;; data in 64-bit mode.
58 1.1 mrg
59 1.1 mrg (define_expand "sync_compare_and_swap<mode>"
60 1.1 mrg [(parallel
61 1.1 mrg [(set (match_operand:CASMODE 0 "register_operand" "")
62 1.1 mrg (match_operand:CASMODE 1 "memory_operand" ""))
63 1.1 mrg (set (match_dup 1)
64 1.1 mrg (unspec_volatile:CASMODE
65 1.1 mrg [(match_dup 1)
66 1.1 mrg (match_operand:CASMODE 2 "register_operand" "")
67 1.1 mrg (match_operand:CASMODE 3 "register_operand" "")]
68 1.1 mrg UNSPECV_CMPXCHG))
69 1.1 mrg (set (reg:CCZ FLAGS_REG)
70 1.1 mrg (compare:CCZ
71 1.1 mrg (unspec_volatile:CASMODE
72 1.1 mrg [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG)
73 1.1 mrg (match_dup 2)))])]
74 1.1 mrg "TARGET_CMPXCHG"
75 1.1 mrg {
76 1.1 mrg if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode)
77 1.1 mrg {
78 1.1 mrg enum machine_mode hmode = <MODE>mode == DImode ? SImode : DImode;
79 1.1 mrg rtx low = simplify_gen_subreg (hmode, operands[3], <MODE>mode, 0);
80 1.1 mrg rtx high = simplify_gen_subreg (hmode, operands[3], <MODE>mode,
81 1.1 mrg GET_MODE_SIZE (hmode));
82 1.1 mrg low = force_reg (hmode, low);
83 1.1 mrg high = force_reg (hmode, high);
84 1.1 mrg if (<MODE>mode == DImode)
85 1.1 mrg {
86 1.1 mrg if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode))
87 1.1 mrg operands[1] = replace_equiv_address (operands[1],
88 1.1 mrg force_reg (Pmode,
89 1.1 mrg XEXP (operands[1],
90 1.1 mrg 0)));
91 1.1 mrg emit_insn (gen_sync_double_compare_and_swapdi
92 1.1 mrg (operands[0], operands[1], operands[2], low, high));
93 1.1 mrg }
94 1.1 mrg else if (<MODE>mode == TImode)
95 1.1 mrg emit_insn (gen_sync_double_compare_and_swapti
96 1.1 mrg (operands[0], operands[1], operands[2], low, high));
97 1.1 mrg else
98 1.1 mrg gcc_unreachable ();
99 1.1 mrg DONE;
100 1.1 mrg }
101 1.1 mrg })
102 1.1 mrg
103 1.1 mrg (define_insn "*sync_compare_and_swap<mode>"
104 1.1 mrg [(set (match_operand:SWI 0 "register_operand" "=a")
105 1.1 mrg (match_operand:SWI 1 "memory_operand" "+m"))
106 1.1 mrg (set (match_dup 1)
107 1.1 mrg (unspec_volatile:SWI
108 1.1 mrg [(match_dup 1)
109 1.1 mrg (match_operand:SWI 2 "register_operand" "a")
110 1.1 mrg (match_operand:SWI 3 "register_operand" "<r>")]
111 1.1 mrg UNSPECV_CMPXCHG))
112 1.1 mrg (set (reg:CCZ FLAGS_REG)
113 1.1 mrg (compare:CCZ
114 1.1 mrg (unspec_volatile:SWI
115 1.1 mrg [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG)
116 1.1 mrg (match_dup 2)))]
117 1.1 mrg "TARGET_CMPXCHG"
118 1.1 mrg "lock{%;} cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
119 1.1 mrg
120 1.1 mrg (define_insn "sync_double_compare_and_swap<mode>"
121 1.1 mrg [(set (match_operand:DCASMODE 0 "register_operand" "=A")
122 1.1 mrg (match_operand:DCASMODE 1 "memory_operand" "+m"))
123 1.1 mrg (set (match_dup 1)
124 1.1 mrg (unspec_volatile:DCASMODE
125 1.1 mrg [(match_dup 1)
126 1.1 mrg (match_operand:DCASMODE 2 "register_operand" "A")
127 1.1 mrg (match_operand:<DCASHMODE> 3 "register_operand" "b")
128 1.1 mrg (match_operand:<DCASHMODE> 4 "register_operand" "c")]
129 1.1 mrg UNSPECV_CMPXCHG))
130 1.1 mrg (set (reg:CCZ FLAGS_REG)
131 1.1 mrg (compare:CCZ
132 1.1 mrg (unspec_volatile:DCASMODE
133 1.1 mrg [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)]
134 1.1 mrg UNSPECV_CMPXCHG)
135 1.1 mrg (match_dup 2)))]
136 1.1 mrg ""
137 1.1 mrg "lock{%;} cmpxchg<doublemodesuffix>b\t%1")
138 1.1 mrg
139 1.1 mrg ;; Theoretically we'd like to use constraint "r" (any reg) for operand
140 1.1 mrg ;; 3, but that includes ecx. If operand 3 and 4 are the same (like when
141 1.1 mrg ;; the input is -1LL) GCC might chose to allocate operand 3 to ecx, like
142 1.1 mrg ;; operand 4. This breaks, as the xchg will move the PIC register contents
143 1.1 mrg ;; to %ecx then --> boom. Operands 3 and 4 really need to be different
144 1.1 mrg ;; registers, which in this case means operand 3 must not be ecx.
145 1.1 mrg ;; Instead of playing tricks with fake early clobbers or the like we
146 1.1 mrg ;; just enumerate all regs possible here, which (as this is !TARGET_64BIT)
147 1.1 mrg ;; are just esi and edi.
148 1.1 mrg (define_insn "*sync_double_compare_and_swapdi_pic"
149 1.1 mrg [(set (match_operand:DI 0 "register_operand" "=A")
150 1.1 mrg (match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m"))
151 1.1 mrg (set (match_dup 1)
152 1.1 mrg (unspec_volatile:DI
153 1.1 mrg [(match_dup 1)
154 1.1 mrg (match_operand:DI 2 "register_operand" "A")
155 1.1 mrg (match_operand:SI 3 "register_operand" "SD")
156 1.1 mrg (match_operand:SI 4 "register_operand" "c")]
157 1.1 mrg UNSPECV_CMPXCHG))
158 1.1 mrg (set (reg:CCZ FLAGS_REG)
159 1.1 mrg (compare:CCZ
160 1.1 mrg (unspec_volatile:DI
161 1.1 mrg [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)]
162 1.1 mrg UNSPECV_CMPXCHG)
163 1.1 mrg (match_dup 2)))]
164 1.1 mrg "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic"
165 1.1 mrg "xchg{l}\t%%ebx, %3\;lock{%;} cmpxchg8b\t%1\;xchg{l}\t%%ebx, %3")
166 1.1 mrg
167 1.1 mrg (define_insn "sync_old_add<mode>"
168 1.1 mrg [(set (match_operand:SWI 0 "register_operand" "=<r>")
169 1.1 mrg (unspec_volatile:SWI
170 1.1 mrg [(match_operand:SWI 1 "memory_operand" "+m")] UNSPECV_XCHG))
171 1.1 mrg (set (match_dup 1)
172 1.1 mrg (plus:SWI (match_dup 1)
173 1.1 mrg (match_operand:SWI 2 "register_operand" "0")))
174 1.1 mrg (clobber (reg:CC FLAGS_REG))]
175 1.1 mrg "TARGET_XADD"
176 1.1 mrg "lock{%;} xadd{<imodesuffix>}\t{%0, %1|%1, %0}")
177 1.1 mrg
178 1.1 mrg ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
179 1.1 mrg (define_insn "sync_lock_test_and_set<mode>"
180 1.1 mrg [(set (match_operand:SWI 0 "register_operand" "=<r>")
181 1.1 mrg (unspec_volatile:SWI
182 1.1 mrg [(match_operand:SWI 1 "memory_operand" "+m")] UNSPECV_XCHG))
183 1.1 mrg (set (match_dup 1)
184 1.1 mrg (match_operand:SWI 2 "register_operand" "0"))]
185 1.1 mrg ""
186 1.1 mrg "xchg{<imodesuffix>}\t{%1, %0|%0, %1}")
187 1.1 mrg
188 1.1 mrg (define_insn "sync_add<mode>"
189 1.1 mrg [(set (match_operand:SWI 0 "memory_operand" "+m")
190 1.1 mrg (unspec_volatile:SWI
191 1.1 mrg [(plus:SWI (match_dup 0)
192 1.1 mrg (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))]
193 1.1 mrg UNSPECV_LOCK))
194 1.1 mrg (clobber (reg:CC FLAGS_REG))]
195 1.1 mrg ""
196 1.1 mrg {
197 1.1 mrg if (TARGET_USE_INCDEC)
198 1.1 mrg {
199 1.1 mrg if (operands[1] == const1_rtx)
200 1.1 mrg return "lock{%;} inc{<imodesuffix>}\t%0";
201 1.1 mrg if (operands[1] == constm1_rtx)
202 1.1 mrg return "lock{%;} dec{<imodesuffix>}\t%0";
203 1.1 mrg }
204 1.1 mrg
205 1.1 mrg return "lock{%;} add{<imodesuffix>}\t{%1, %0|%0, %1}";
206 1.1 mrg })
207 1.1 mrg
208 1.1 mrg (define_insn "sync_sub<mode>"
209 1.1 mrg [(set (match_operand:SWI 0 "memory_operand" "+m")
210 1.1 mrg (unspec_volatile:SWI
211 1.1 mrg [(minus:SWI (match_dup 0)
212 1.1 mrg (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))]
213 1.1 mrg UNSPECV_LOCK))
214 1.1 mrg (clobber (reg:CC FLAGS_REG))]
215 1.1 mrg ""
216 1.1 mrg {
217 1.1 mrg if (TARGET_USE_INCDEC)
218 1.1 mrg {
219 1.1 mrg if (operands[1] == const1_rtx)
220 1.1 mrg return "lock{%;} dec{<imodesuffix>}\t%0";
221 1.1 mrg if (operands[1] == constm1_rtx)
222 1.1 mrg return "lock{%;} inc{<imodesuffix>}\t%0";
223 1.1 mrg }
224 1.1 mrg
225 1.1 mrg return "lock{%;} sub{<imodesuffix>}\t{%1, %0|%0, %1}";
226 1.1 mrg })
227 1.1 mrg
228 1.1 mrg (define_insn "sync_<code><mode>"
229 1.1 mrg [(set (match_operand:SWI 0 "memory_operand" "+m")
230 1.1 mrg (unspec_volatile:SWI
231 1.1 mrg [(any_logic:SWI (match_dup 0)
232 1.1 mrg (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))]
233 1.1 mrg UNSPECV_LOCK))
234 1.1 mrg (clobber (reg:CC FLAGS_REG))]
235 1.1 mrg ""
236 1.1 mrg "lock{%;} <logicprefix>{<imodesuffix>}\t{%1, %0|%0, %1}")
237