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