OSDN Git Service

Update Copyright years for files modified in 2008 and/or 2009.
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sync.md
1 ;; GCC machine description for SPARC synchronization instructions.
2 ;; Copyright (C) 2005, 2007, 2009
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 3, 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 COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 (define_mode_iterator I12MODE [QI HI])
22 (define_mode_iterator I24MODE [HI SI])
23 (define_mode_iterator I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")])
24 (define_mode_attr modesuffix [(SI "") (DI "x")])
25
26 (define_expand "memory_barrier"
27   [(set (match_dup 0)
28         (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
29   "TARGET_V8 || TARGET_V9"
30 {
31   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
32   MEM_VOLATILE_P (operands[0]) = 1;
33
34 })
35
36 (define_insn "*stbar"
37   [(set (match_operand:BLK 0 "" "")
38         (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
39   "TARGET_V8"
40   "stbar"
41   [(set_attr "type" "multi")])
42
43 ;; membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad
44 (define_insn "*membar"
45   [(set (match_operand:BLK 0 "" "")
46         (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
47   "TARGET_V9"
48   "membar\t15"
49   [(set_attr "type" "multi")])
50
51 (define_expand "sync_compare_and_swap<mode>"
52   [(match_operand:I12MODE 0 "register_operand" "")
53    (match_operand:I12MODE 1 "memory_operand" "")
54    (match_operand:I12MODE 2 "register_operand" "")
55    (match_operand:I12MODE 3 "register_operand" "")]
56   "TARGET_V9"
57 {
58   sparc_expand_compare_and_swap_12 (operands[0], operands[1],
59                                     operands[2], operands[3]);
60   DONE;
61 })
62
63 (define_expand "sync_compare_and_swap<mode>"
64   [(parallel
65      [(set (match_operand:I48MODE 0 "register_operand" "=r")
66            (match_operand:I48MODE 1 "memory_operand" ""))
67       (set (match_dup 1)
68            (unspec_volatile:I48MODE
69              [(match_operand:I48MODE 2 "register_operand" "")
70               (match_operand:I48MODE 3 "register_operand" "")]
71              UNSPECV_CAS))])]
72   "TARGET_V9"
73 {
74   if (! REG_P (XEXP (operands[1], 0)))
75     {
76       rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
77       operands[1] = replace_equiv_address (operands[1], addr);
78     }
79   emit_insn (gen_memory_barrier ());
80 })
81
82 (define_insn "*sync_compare_and_swap<mode>"
83   [(set (match_operand:I48MODE 0 "register_operand" "=r")
84         (match_operand:I48MODE 1 "memory_reg_operand" "+m"))
85    (set (match_dup 1)
86         (unspec_volatile:I48MODE
87           [(match_operand:I48MODE 2 "register_operand" "r")
88            (match_operand:I48MODE 3 "register_operand" "0")]
89           UNSPECV_CAS))]
90   "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
91   "cas<modesuffix>\t%1, %2, %0"
92   [(set_attr "type" "multi")])
93
94 (define_insn "*sync_compare_and_swapdi_v8plus"
95   [(set (match_operand:DI 0 "register_operand" "=h")
96         (match_operand:DI 1 "memory_reg_operand" "+m"))
97    (set (match_dup 1)
98         (unspec_volatile:DI
99           [(match_operand:DI 2 "register_operand" "h")
100            (match_operand:DI 3 "register_operand" "0")]
101           UNSPECV_CAS))]
102   "TARGET_V8PLUS"
103 {
104   if (sparc_check_64 (operands[3], insn) <= 0)
105     output_asm_insn ("srl\t%L3, 0, %L3", operands);
106   output_asm_insn ("sllx\t%H3, 32, %H3", operands);
107   output_asm_insn ("or\t%L3, %H3, %L3", operands);
108   if (sparc_check_64 (operands[2], insn) <= 0)
109     output_asm_insn ("srl\t%L2, 0, %L2", operands);
110   output_asm_insn ("sllx\t%H2, 32, %H3", operands);
111   output_asm_insn ("or\t%L2, %H3, %H3", operands);
112   output_asm_insn ("casx\t%1, %H3, %L3", operands);
113   return "srlx\t%L3, 32, %H3";
114 }
115   [(set_attr "type" "multi")
116    (set_attr "length" "8")])
117
118 (define_expand "sync_lock_test_and_set<mode>"
119   [(match_operand:I12MODE 0 "register_operand" "")
120    (match_operand:I12MODE 1 "memory_operand" "")
121    (match_operand:I12MODE 2 "arith_operand" "")]
122   "!TARGET_V9"
123 {
124   if (operands[2] != const1_rtx)
125     FAIL;
126   if (TARGET_V8)
127     emit_insn (gen_memory_barrier ());
128   if (<MODE>mode != QImode)
129     operands[1] = adjust_address (operands[1], QImode, 0);
130   emit_insn (gen_ldstub<mode> (operands[0], operands[1]));
131   DONE;
132 })
133
134 (define_expand "sync_lock_test_and_setsi"
135   [(parallel
136      [(set (match_operand:SI 0 "register_operand" "")
137            (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
138                                UNSPECV_SWAP))
139       (set (match_dup 1)
140            (match_operand:SI 2 "arith_operand" ""))])]
141   ""
142 {
143   if (! TARGET_V8 && ! TARGET_V9)
144     {
145       if (operands[2] != const1_rtx)
146         FAIL;
147       operands[1] = adjust_address (operands[1], QImode, 0);
148       emit_insn (gen_ldstubsi (operands[0], operands[1]));
149       DONE;
150     }
151   emit_insn (gen_memory_barrier ());
152   operands[2] = force_reg (SImode, operands[2]);
153 })
154
155 (define_insn "*swapsi"
156   [(set (match_operand:SI 0 "register_operand" "=r")
157         (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
158                             UNSPECV_SWAP))
159    (set (match_dup 1)
160         (match_operand:SI 2 "register_operand" "0"))]
161   "TARGET_V8 || TARGET_V9"
162   "swap\t%1, %0"
163   [(set_attr "type" "multi")])
164
165 (define_expand "ldstubqi"
166   [(parallel [(set (match_operand:QI 0 "register_operand" "")
167                    (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
168                                        UNSPECV_LDSTUB))
169               (set (match_dup 1) (const_int -1))])]
170   ""
171   "")
172
173 (define_expand "ldstub<mode>"
174   [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
175                    (zero_extend:I24MODE
176                       (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
177                                           UNSPECV_LDSTUB)))
178               (set (match_dup 1) (const_int -1))])]
179   ""
180   "")
181
182 (define_insn "*ldstubqi"
183   [(set (match_operand:QI 0 "register_operand" "=r")
184         (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
185                             UNSPECV_LDSTUB))
186    (set (match_dup 1) (const_int -1))]
187   ""
188   "ldstub\t%1, %0"
189   [(set_attr "type" "multi")])
190
191 (define_insn "*ldstub<mode>"
192   [(set (match_operand:I24MODE 0 "register_operand" "=r")
193         (zero_extend:I24MODE
194           (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
195                               UNSPECV_LDSTUB)))
196    (set (match_dup 1) (const_int -1))]
197   ""
198   "ldstub\t%1, %0"
199   [(set_attr "type" "multi")])