1169689Skan;; GCC machine description for SPARC synchronization instructions.
2169689Skan;; Copyright (C) 2005
3169689Skan;; Free Software Foundation, Inc.
4169689Skan;;
5169689Skan;; This file is part of GCC.
6169689Skan;;
7169689Skan;; GCC is free software; you can redistribute it and/or modify
8169689Skan;; it under the terms of the GNU General Public License as published by
9169689Skan;; the Free Software Foundation; either version 2, or (at your option)
10169689Skan;; any later version.
11169689Skan;;
12169689Skan;; GCC is distributed in the hope that it will be useful,
13169689Skan;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14169689Skan;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15169689Skan;; GNU General Public License for more details.
16169689Skan;;
17169689Skan;; You should have received a copy of the GNU General Public License
18169689Skan;; along with GCC; see the file COPYING.  If not, write to
19169689Skan;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20169689Skan;; Boston, MA 02110-1301, USA.
21169689Skan
22169689Skan(define_mode_macro I12MODE [QI HI])
23169689Skan(define_mode_macro I24MODE [HI SI])
24169689Skan(define_mode_macro I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")])
25169689Skan(define_mode_attr modesuffix [(SI "") (DI "x")])
26169689Skan
27169689Skan(define_expand "memory_barrier"
28169689Skan  [(set (mem:BLK (match_dup 0))
29169689Skan	(unspec_volatile:BLK [(mem:BLK (match_dup 0)) (match_dup 1)]
30169689Skan			     UNSPECV_MEMBAR))]
31169689Skan  "TARGET_V8 || TARGET_V9"
32169689Skan{
33169689Skan  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
34169689Skan  MEM_VOLATILE_P (operands[0]) = 1;
35169689Skan  if (TARGET_V9)
36169689Skan    /* member #StoreStore | #LoadStore | #StoreLoad | #LoadLoad */
37169689Skan    operands[1] = GEN_INT (15);
38169689Skan  else
39169689Skan    /* stbar */
40169689Skan    operands[1] = GEN_INT (8);
41169689Skan})
42169689Skan
43169689Skan(define_insn "*stbar"
44169689Skan  [(set (match_operand:BLK 0 "" "")
45169689Skan	(unspec_volatile:BLK [(match_operand:BLK 1 "" "")
46169689Skan			      (const_int 8)] UNSPECV_MEMBAR))]
47169689Skan  "TARGET_V8"
48169689Skan  "stbar"
49169689Skan  [(set_attr "type" "multi")])
50169689Skan
51169689Skan(define_insn "*membar"
52169689Skan  [(set (match_operand:BLK 0 "" "")
53169689Skan	(unspec_volatile:BLK [(match_operand:BLK 1 "" "")
54169689Skan			      (match_operand:SI 2 "immediate_operand" "I")]
55169689Skan			      UNSPECV_MEMBAR))]
56169689Skan  "TARGET_V9"
57169689Skan  "membar\t%2"
58169689Skan  [(set_attr "type" "multi")])
59169689Skan
60169689Skan(define_expand "sync_compare_and_swap<mode>"
61169689Skan  [(match_operand:I12MODE 0 "register_operand" "")
62169689Skan   (match_operand:I12MODE 1 "memory_operand" "")
63169689Skan   (match_operand:I12MODE 2 "register_operand" "")
64169689Skan   (match_operand:I12MODE 3 "register_operand" "")]
65169689Skan  "TARGET_V9"
66169689Skan{
67169689Skan  sparc_expand_compare_and_swap_12 (operands[0], operands[1],
68169689Skan				    operands[2], operands[3]);
69169689Skan  DONE;
70169689Skan})
71169689Skan
72169689Skan(define_expand "sync_compare_and_swap<mode>"
73169689Skan  [(parallel
74169689Skan     [(set (match_operand:I48MODE 0 "register_operand" "=r")
75169689Skan	   (match_operand:I48MODE 1 "memory_operand" ""))
76169689Skan      (set (match_dup 1)
77169689Skan	   (unspec_volatile:I48MODE
78169689Skan	     [(match_operand:I48MODE 2 "register_operand" "")
79169689Skan	      (match_operand:I48MODE 3 "register_operand" "")]
80169689Skan	     UNSPECV_CAS))])]
81169689Skan  "TARGET_V9"
82169689Skan{
83169689Skan  if (! REG_P (XEXP (operands[1], 0)))
84169689Skan    {
85169689Skan      rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
86169689Skan      operands[1] = replace_equiv_address (operands[1], addr);
87169689Skan    }
88169689Skan  emit_insn (gen_memory_barrier ());
89169689Skan})
90169689Skan
91169689Skan(define_insn "*sync_compare_and_swap<mode>"
92169689Skan  [(set (match_operand:I48MODE 0 "register_operand" "=r")
93169689Skan	(match_operand:I48MODE 1 "memory_reg_operand" "+m"))
94169689Skan   (set (match_dup 1)
95169689Skan	(unspec_volatile:I48MODE
96169689Skan	  [(match_operand:I48MODE 2 "register_operand" "r")
97169689Skan	   (match_operand:I48MODE 3 "register_operand" "0")]
98169689Skan	  UNSPECV_CAS))]
99169689Skan  "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
100169689Skan  "cas<modesuffix>\t%1, %2, %0"
101169689Skan  [(set_attr "type" "multi")])
102169689Skan
103169689Skan(define_insn "*sync_compare_and_swapdi_v8plus"
104169689Skan  [(set (match_operand:DI 0 "register_operand" "=h")
105169689Skan	(match_operand:DI 1 "memory_reg_operand" "+m"))
106169689Skan   (set (match_dup 1)
107169689Skan	(unspec_volatile:DI
108169689Skan	  [(match_operand:DI 2 "register_operand" "h")
109169689Skan	   (match_operand:DI 3 "register_operand" "0")]
110169689Skan	  UNSPECV_CAS))]
111169689Skan  "TARGET_V8PLUS"
112169689Skan{
113169689Skan  if (sparc_check_64 (operands[3], insn) <= 0)
114169689Skan    output_asm_insn ("srl\t%L3, 0, %L3", operands);
115169689Skan  output_asm_insn ("sllx\t%H3, 32, %H3", operands);
116169689Skan  output_asm_insn ("or\t%L3, %H3, %L3", operands);
117169689Skan  if (sparc_check_64 (operands[2], insn) <= 0)
118169689Skan    output_asm_insn ("srl\t%L2, 0, %L2", operands);
119169689Skan  output_asm_insn ("sllx\t%H2, 32, %H3", operands);
120169689Skan  output_asm_insn ("or\t%L2, %H3, %H3", operands);
121169689Skan  output_asm_insn ("casx\t%1, %H3, %L3", operands);
122169689Skan  return "srlx\t%L3, 32, %H3";
123169689Skan}
124169689Skan  [(set_attr "type" "multi")
125169689Skan   (set_attr "length" "8")])
126169689Skan
127169689Skan(define_expand "sync_lock_test_and_set<mode>"
128169689Skan  [(match_operand:I12MODE 0 "register_operand" "")
129169689Skan   (match_operand:I12MODE 1 "memory_operand" "")
130169689Skan   (match_operand:I12MODE 2 "arith_operand" "")]
131169689Skan  "!TARGET_V9"
132169689Skan{
133169689Skan  if (operands[2] != const1_rtx)
134169689Skan    FAIL;
135169689Skan  if (TARGET_V8)
136169689Skan    emit_insn (gen_memory_barrier ());
137169689Skan  if (<MODE>mode != QImode)
138169689Skan    operands[1] = adjust_address (operands[1], QImode, 0);
139169689Skan  emit_insn (gen_ldstub<mode> (operands[0], operands[1]));
140169689Skan  DONE;
141169689Skan})
142169689Skan
143169689Skan(define_expand "sync_lock_test_and_setsi"
144169689Skan  [(parallel
145169689Skan     [(set (match_operand:SI 0 "register_operand" "")
146169689Skan	   (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
147169689Skan			       UNSPECV_SWAP))
148169689Skan      (set (match_dup 1)
149169689Skan	   (match_operand:SI 2 "arith_operand" ""))])]
150169689Skan  ""
151169689Skan{
152169689Skan  if (! TARGET_V8 && ! TARGET_V9)
153169689Skan    {
154169689Skan      if (operands[2] != const1_rtx)
155169689Skan	FAIL;
156169689Skan      operands[1] = adjust_address (operands[1], QImode, 0);
157169689Skan      emit_insn (gen_ldstubsi (operands[0], operands[1]));
158169689Skan      DONE;
159169689Skan    }
160169689Skan  emit_insn (gen_memory_barrier ());
161169689Skan  operands[2] = force_reg (SImode, operands[2]);
162169689Skan})
163169689Skan
164169689Skan(define_insn "*swapsi"
165169689Skan  [(set (match_operand:SI 0 "register_operand" "=r")
166169689Skan	(unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
167169689Skan			    UNSPECV_SWAP))
168169689Skan   (set (match_dup 1)
169169689Skan	(match_operand:SI 2 "register_operand" "0"))]
170169689Skan  "TARGET_V8 || TARGET_V9"
171169689Skan  "swap\t%1, %0"
172169689Skan  [(set_attr "type" "multi")])
173169689Skan
174169689Skan(define_expand "ldstubqi"
175169689Skan  [(parallel [(set (match_operand:QI 0 "register_operand" "")
176169689Skan		   (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
177169689Skan				       UNSPECV_LDSTUB))
178169689Skan	      (set (match_dup 1) (const_int -1))])]
179169689Skan  ""
180169689Skan  "")
181169689Skan
182169689Skan(define_expand "ldstub<mode>"
183169689Skan  [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
184169689Skan		   (zero_extend:I24MODE
185169689Skan		      (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
186169689Skan					  UNSPECV_LDSTUB)))
187169689Skan	      (set (match_dup 1) (const_int -1))])]
188169689Skan  ""
189169689Skan  "")
190169689Skan
191169689Skan(define_insn "*ldstubqi"
192169689Skan  [(set (match_operand:QI 0 "register_operand" "=r")
193169689Skan	(unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
194169689Skan			    UNSPECV_LDSTUB))
195169689Skan   (set (match_dup 1) (const_int -1))]
196169689Skan  ""
197169689Skan  "ldstub\t%1, %0"
198169689Skan  [(set_attr "type" "multi")])
199169689Skan
200169689Skan(define_insn "*ldstub<mode>"
201169689Skan  [(set (match_operand:I24MODE 0 "register_operand" "=r")
202169689Skan	(zero_extend:I24MODE
203169689Skan	  (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
204169689Skan			      UNSPECV_LDSTUB)))
205169689Skan   (set (match_dup 1) (const_int -1))]
206169689Skan  ""
207169689Skan  "ldstub\t%1, %0"
208169689Skan  [(set_attr "type" "multi")])
209