OSDN Git Service

* builtins.c (expand_builtin_sync_operation): Revert last change.
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / sync.md
1 ;; GCC machine description for Alpha synchronization instructions.
2 ;; Copyright (C) 2005
3 ;; Free Software Foundation, Inc.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING.  If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
21
22 (define_mode_macro I48MODE [SI DI])
23 (define_mode_attr modesuffix [(SI "l") (DI "q")])
24
25 (define_code_macro FETCHOP [plus minus ior xor and])
26 (define_code_attr fetchop_name
27   [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
28 (define_code_attr fetchop_pred
29   [(plus "add_operand") (minus "reg_or_8bit_operand")
30    (ior "or_operand") (xor "or_operand") (and "and_operand")])
31 (define_code_attr fetchop_constr
32   [(plus "rKL") (minus "rI") (ior "rIN") (xor "rIN") (and "riNHM")])
33
34
35 (define_expand "memory_barrier"
36   [(set (mem:BLK (match_dup 0))
37         (unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MB))]
38   ""
39 {
40   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
41   MEM_VOLATILE_P (operands[0]) = 1;
42 })
43
44 (define_insn "*mb_internal"
45   [(set (match_operand:BLK 0 "" "")
46         (unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MB))]
47   ""
48   "mb"
49   [(set_attr "type" "mb")])
50
51 (define_insn "load_locked_<mode>"
52   [(set (match_operand:I48MODE 0 "register_operand" "=r")
53         (unspec_volatile:I48MODE
54           [(match_operand:I48MODE 1 "memory_operand" "m")]
55           UNSPECV_LL))]
56   ""
57   "ld<modesuffix>_l %0,%1"
58   [(set_attr "type" "ld_l")])
59
60 (define_insn "store_conditional_<mode>"
61   [(set (match_operand:DI 0 "register_operand" "=r")
62         (unspec_volatile:DI [(const_int 0)] UNSPECV_SC))
63    (set (match_operand:I48MODE 1 "memory_operand" "=m")
64         (match_operand:I48MODE 2 "reg_or_0_operand" "0"))]
65   ""
66   "st<modesuffix>_c %0,%1"
67   [(set_attr "type" "st_c")])
68
69 ;; The Alpha Architecture Handbook says that it is UNPREDICTABLE whether
70 ;; the lock is cleared by a TAKEN branch.  If we were to honor that, it
71 ;; would mean that we could not expand a ll/sc sequence until after the
72 ;; final basic-block reordering pass.  Fortunately, it appears that no
73 ;; Alpha implementation ever built actually clears the lock on branches,
74 ;; taken or not.
75
76 (define_insn_and_split "sync_<fetchop_name><mode>"
77   [(set (match_operand:I48MODE 0 "memory_operand" "+m")
78         (unspec_volatile:I48MODE
79           [(FETCHOP:I48MODE (match_dup 0)
80              (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
81           UNSPECV_ATOMIC))
82    (clobber (match_scratch:I48MODE 2 "=&r"))]
83   ""
84   "#"
85   "reload_completed"
86   [(const_int 0)]
87 {
88   alpha_split_atomic_op (<CODE>, operands[0], operands[1],
89                          NULL, NULL, operands[2]);
90   DONE;
91 }
92   [(set_attr "type" "multi")])
93
94 (define_insn_and_split "sync_nand<mode>"
95   [(set (match_operand:I48MODE 0 "memory_operand" "+m")
96         (unspec_volatile:I48MODE
97           [(and:I48MODE (not:I48MODE (match_dup 0))
98              (match_operand:I48MODE 1 "register_operand" "r"))]
99           UNSPECV_ATOMIC))
100    (clobber (match_scratch:I48MODE 2 "=&r"))]
101   ""
102   "#"
103   "reload_completed"
104   [(const_int 0)]
105 {
106   alpha_split_atomic_op (NOT, operands[0], operands[1],
107                          NULL, NULL, operands[2]);
108   DONE;
109 }
110   [(set_attr "type" "multi")])
111
112 (define_insn_and_split "sync_old_<fetchop_name><mode>"
113   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
114         (match_operand:I48MODE 1 "memory_operand" "+m"))
115    (set (match_dup 1)
116         (unspec_volatile:I48MODE
117           [(FETCHOP:I48MODE (match_dup 1)
118              (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
119           UNSPECV_ATOMIC))
120    (clobber (match_scratch:I48MODE 3 "=&r"))]
121   ""
122   "#"
123   "reload_completed"
124   [(const_int 0)]
125 {
126   alpha_split_atomic_op (<CODE>, operands[1], operands[2],
127                          operands[0], NULL, operands[3]);
128   DONE;
129 }
130   [(set_attr "type" "multi")])
131
132 (define_insn_and_split "sync_old_nand<mode>"
133   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
134         (match_operand:I48MODE 1 "memory_operand" "+m"))
135    (set (match_dup 1)
136         (unspec_volatile:I48MODE
137           [(and:I48MODE (not:I48MODE (match_dup 1))
138              (match_operand:I48MODE 2 "register_operand" "r"))]
139           UNSPECV_ATOMIC))
140    (clobber (match_scratch:I48MODE 3 "=&r"))]
141   ""
142   "#"
143   "reload_completed"
144   [(const_int 0)]
145 {
146   alpha_split_atomic_op (NOT, operands[1], operands[2],
147                          operands[0], NULL, operands[3]);
148   DONE;
149 }
150   [(set_attr "type" "multi")])
151
152 (define_insn_and_split "sync_new_<fetchop_name><mode>"
153   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
154         (FETCHOP:I48MODE 
155           (match_operand:I48MODE 1 "memory_operand" "+m")
156           (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
157    (set (match_dup 1)
158         (unspec_volatile:I48MODE
159           [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
160           UNSPECV_ATOMIC))
161    (clobber (match_scratch:I48MODE 3 "=&r"))]
162   ""
163   "#"
164   "reload_completed"
165   [(const_int 0)]
166 {
167   alpha_split_atomic_op (<CODE>, operands[1], operands[2],
168                          NULL, operands[0], operands[3]);
169   DONE;
170 }
171   [(set_attr "type" "multi")])
172
173 (define_insn_and_split "sync_new_nand<mode>"
174   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
175         (and:I48MODE 
176           (not:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m"))
177           (match_operand:I48MODE 2 "reg_or_8bit_operand" "rI")))
178    (set (match_dup 1)
179         (unspec_volatile:I48MODE
180           [(and:I48MODE (not:I48MODE (match_dup 1)) (match_dup 2))]
181           UNSPECV_ATOMIC))
182    (clobber (match_scratch:I48MODE 3 "=&r"))]
183   ""
184   "#"
185   "reload_completed"
186   [(const_int 0)]
187 {
188   alpha_split_atomic_op (NOT, operands[1], operands[2],
189                          NULL, operands[0], operands[3]);
190   DONE;
191 }
192   [(set_attr "type" "multi")])
193
194 (define_expand "sync_compare_and_swap<mode>"
195   [(parallel
196      [(set (match_operand:I48MODE 0 "register_operand" "")
197            (match_operand:I48MODE 1 "memory_operand" ""))
198       (set (match_dup 1)
199            (unspec_volatile:I48MODE
200              [(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
201               (match_operand:I48MODE 3 "add_operand" "rKL")]
202              UNSPECV_CMPXCHG))
203       (clobber (match_scratch:I48MODE 4 "=&r"))])]
204   ""
205 {
206   if (<MODE>mode == SImode)
207     operands[2] = convert_modes (DImode, SImode, operands[2], 0);
208 })
209
210 (define_insn_and_split "*sync_compare_and_swap<mode>"
211   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
212         (match_operand:I48MODE 1 "memory_operand" "+m"))
213    (set (match_dup 1)
214         (unspec_volatile:I48MODE
215           [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
216            (match_operand:I48MODE 3 "add_operand" "rKL")]
217           UNSPECV_CMPXCHG))
218    (clobber (match_scratch:I48MODE 4 "=&r"))]
219   ""
220   "#"
221   "reload_completed"
222   [(const_int 0)]
223 {
224   rtx retval, mem, oldval, newval, scratch;
225   rtx cond, label1, label2, x;
226   rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
227
228   retval = operands[0];
229   mem = operands[1];
230   oldval = operands[2];
231   newval = operands[3];
232   scratch = operands[4];
233   cond = gen_lowpart (DImode, scratch);
234
235   emit_insn (gen_memory_barrier ());
236
237   label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
238   label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
239   emit_label (XEXP (label1, 0));
240
241   emit_insn (gen_load_locked_<mode> (retval, mem));
242
243   x = gen_lowpart (DImode, retval);
244   if (oldval == const0_rtx)
245     x = gen_rtx_NE (DImode, x, const0_rtx);
246   else
247     {
248       x = gen_rtx_EQ (DImode, x, oldval);
249       emit_insn (gen_rtx_SET (VOIDmode, cond, x));
250       x = gen_rtx_EQ (DImode, cond, const0_rtx);
251     }
252   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label2, pc_rtx);
253   x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
254   REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
255     
256   emit_move_insn (scratch, newval);
257
258   emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
259
260   x = gen_rtx_EQ (DImode, cond, const0_rtx);
261   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label1, pc_rtx);
262   x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
263   REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
264
265   emit_insn (gen_memory_barrier ());
266   emit_label (XEXP (label2, 0));
267   DONE;
268 }
269   [(set_attr "type" "multi")])
270
271 (define_insn_and_split "sync_lock_test_and_set<mode>"
272   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
273         (match_operand:I48MODE 1 "memory_operand" "+m"))
274    (set (match_dup 1)
275         (unspec_volatile:I48MODE
276           [(match_operand:I48MODE 2 "add_operand" "rKL")]
277           UNSPECV_XCHG))
278    (clobber (match_scratch:I48MODE 3 "=&r"))]
279   ""
280   "#"
281   "reload_completed"
282   [(const_int 0)]
283 {
284   rtx retval, mem, val, scratch;
285   rtx cond, label1, x;
286   rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
287
288   retval = operands[0];
289   mem = operands[1];
290   val = operands[2];
291   scratch = operands[3];
292   cond = gen_lowpart (DImode, scratch);
293
294   emit_insn (gen_memory_barrier ());
295
296   label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
297   emit_label (XEXP (label1, 0));
298
299   emit_insn (gen_load_locked_<mode> (retval, mem));
300
301   emit_move_insn (scratch, val);
302   
303   emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
304
305   x = gen_rtx_EQ (DImode, cond, const0_rtx);
306   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label1, pc_rtx);
307   x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
308   REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
309
310   DONE;
311 }
312   [(set_attr "type" "multi")])