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