1 ;; GCC machine description for SPARC synchronization instructions.
2 ;; Copyright (C) 2005, 2007
3 ;; Free Software Foundation, Inc.
5 ;; This file is part of GCC.
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)
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.
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/>.
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")])
26 (define_expand "memory_barrier"
27 [(set (mem:BLK (match_dup 0))
28 (unspec_volatile:BLK [(mem:BLK (match_dup 0)) (match_dup 1)]
30 "TARGET_V8 || TARGET_V9"
32 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
33 MEM_VOLATILE_P (operands[0]) = 1;
35 /* member #StoreStore | #LoadStore | #StoreLoad | #LoadLoad */
36 operands[1] = GEN_INT (15);
39 operands[1] = GEN_INT (8);
43 [(set (match_operand:BLK 0 "" "")
44 (unspec_volatile:BLK [(match_operand:BLK 1 "" "")
45 (const_int 8)] UNSPECV_MEMBAR))]
48 [(set_attr "type" "multi")])
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")]
57 [(set_attr "type" "multi")])
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" "")]
66 sparc_expand_compare_and_swap_12 (operands[0], operands[1],
67 operands[2], operands[3]);
71 (define_expand "sync_compare_and_swap<mode>"
73 [(set (match_operand:I48MODE 0 "register_operand" "=r")
74 (match_operand:I48MODE 1 "memory_operand" ""))
76 (unspec_volatile:I48MODE
77 [(match_operand:I48MODE 2 "register_operand" "")
78 (match_operand:I48MODE 3 "register_operand" "")]
82 if (! REG_P (XEXP (operands[1], 0)))
84 rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
85 operands[1] = replace_equiv_address (operands[1], addr);
87 emit_insn (gen_memory_barrier ());
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"))
94 (unspec_volatile:I48MODE
95 [(match_operand:I48MODE 2 "register_operand" "r")
96 (match_operand:I48MODE 3 "register_operand" "0")]
98 "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
99 "cas<modesuffix>\t%1, %2, %0"
100 [(set_attr "type" "multi")])
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"))
107 [(match_operand:DI 2 "register_operand" "h")
108 (match_operand:DI 3 "register_operand" "0")]
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";
123 [(set_attr "type" "multi")
124 (set_attr "length" "8")])
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" "")]
132 if (operands[2] != const1_rtx)
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]));
142 (define_expand "sync_lock_test_and_setsi"
144 [(set (match_operand:SI 0 "register_operand" "")
145 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
148 (match_operand:SI 2 "arith_operand" ""))])]
151 if (! TARGET_V8 && ! TARGET_V9)
153 if (operands[2] != const1_rtx)
155 operands[1] = adjust_address (operands[1], QImode, 0);
156 emit_insn (gen_ldstubsi (operands[0], operands[1]));
159 emit_insn (gen_memory_barrier ());
160 operands[2] = force_reg (SImode, operands[2]);
163 (define_insn "*swapsi"
164 [(set (match_operand:SI 0 "register_operand" "=r")
165 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
168 (match_operand:SI 2 "register_operand" "0"))]
169 "TARGET_V8 || TARGET_V9"
171 [(set_attr "type" "multi")])
173 (define_expand "ldstubqi"
174 [(parallel [(set (match_operand:QI 0 "register_operand" "")
175 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
177 (set (match_dup 1) (const_int -1))])]
181 (define_expand "ldstub<mode>"
182 [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
184 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
186 (set (match_dup 1) (const_int -1))])]
190 (define_insn "*ldstubqi"
191 [(set (match_operand:QI 0 "register_operand" "=r")
192 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
194 (set (match_dup 1) (const_int -1))]
197 [(set_attr "type" "multi")])
199 (define_insn "*ldstub<mode>"
200 [(set (match_operand:I24MODE 0 "register_operand" "=r")
202 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
204 (set (match_dup 1) (const_int -1))]
207 [(set_attr "type" "multi")])