1 ;; GCC machine description for SPARC synchronization instructions.
2 ;; Copyright (C) 2005, 2007, 2009, 2010
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"
28 (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
29 "TARGET_V8 || TARGET_V9"
31 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
32 MEM_VOLATILE_P (operands[0]) = 1;
37 [(set (match_operand:BLK 0 "" "")
38 (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
41 [(set_attr "type" "multi")])
43 ;; membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad
44 (define_insn "*membar"
45 [(set (match_operand:BLK 0 "" "")
46 (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
49 [(set_attr "type" "multi")])
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" "")]
58 sparc_expand_compare_and_swap_12 (operands[0], operands[1],
59 operands[2], operands[3]);
63 (define_expand "sync_compare_and_swap<mode>"
65 [(set (match_operand:I48MODE 0 "register_operand" "")
66 (match_operand:I48MODE 1 "memory_operand" ""))
68 (unspec_volatile:I48MODE
69 [(match_operand:I48MODE 2 "register_operand" "")
70 (match_operand:I48MODE 3 "register_operand" "")]
74 if (!REG_P (XEXP (operands[1], 0)))
76 rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
77 operands[1] = replace_equiv_address (operands[1], addr);
79 emit_insn (gen_memory_barrier ());
82 (define_insn "*sync_compare_and_swap<mode>"
83 [(set (match_operand:I48MODE 0 "register_operand" "=r")
84 (mem:I48MODE (match_operand 1 "register_operand" "r")))
85 (set (mem:I48MODE (match_dup 1))
86 (unspec_volatile:I48MODE
87 [(match_operand:I48MODE 2 "register_operand" "r")
88 (match_operand:I48MODE 3 "register_operand" "0")]
90 "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
91 "cas<modesuffix>\t[%1], %2, %0"
92 [(set_attr "type" "multi")])
94 (define_insn "*sync_compare_and_swapdi_v8plus"
95 [(set (match_operand:DI 0 "register_operand" "=h")
96 (mem:DI (match_operand 1 "register_operand" "r")))
97 (set (mem:DI (match_dup 1))
99 [(match_operand:DI 2 "register_operand" "h")
100 (match_operand:DI 3 "register_operand" "0")]
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";
115 [(set_attr "type" "multi")
116 (set_attr "length" "8")])
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" "")]
124 if (operands[2] != const1_rtx)
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]));
134 (define_expand "sync_lock_test_and_setsi"
136 [(set (match_operand:SI 0 "register_operand" "")
137 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
140 (match_operand:SI 2 "arith_operand" ""))])]
143 if (! TARGET_V8 && ! TARGET_V9)
145 if (operands[2] != const1_rtx)
147 operands[1] = adjust_address (operands[1], QImode, 0);
148 emit_insn (gen_ldstubsi (operands[0], operands[1]));
151 emit_insn (gen_memory_barrier ());
152 operands[2] = force_reg (SImode, operands[2]);
155 (define_insn "*swapsi"
156 [(set (match_operand:SI 0 "register_operand" "=r")
157 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
160 (match_operand:SI 2 "register_operand" "0"))]
161 "TARGET_V8 || TARGET_V9"
163 [(set_attr "type" "multi")])
165 (define_expand "ldstubqi"
166 [(parallel [(set (match_operand:QI 0 "register_operand" "")
167 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
169 (set (match_dup 1) (const_int -1))])]
173 (define_expand "ldstub<mode>"
174 [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
176 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
178 (set (match_dup 1) (const_int -1))])]
182 (define_insn "*ldstubqi"
183 [(set (match_operand:QI 0 "register_operand" "=r")
184 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
186 (set (match_dup 1) (const_int -1))]
189 [(set_attr "type" "multi")])
191 (define_insn "*ldstub<mode>"
192 [(set (match_operand:I24MODE 0 "register_operand" "=r")
194 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
196 (set (match_dup 1) (const_int -1))]
199 [(set_attr "type" "multi")])