0
|
1 ;; GCC machine description for SPARC synchronization instructions.
|
|
2 ;; Copyright (C) 2005, 2007, 2009
|
|
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_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")])
|
|
25
|
|
26 (define_expand "memory_barrier"
|
|
27 [(set (match_dup 0)
|
|
28 (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
|
|
29 "TARGET_V8 || TARGET_V9"
|
|
30 {
|
|
31 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
|
|
32 MEM_VOLATILE_P (operands[0]) = 1;
|
|
33
|
|
34 })
|
|
35
|
|
36 (define_insn "*stbar"
|
|
37 [(set (match_operand:BLK 0 "" "")
|
|
38 (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
|
|
39 "TARGET_V8"
|
|
40 "stbar"
|
|
41 [(set_attr "type" "multi")])
|
|
42
|
|
43 ;; membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad
|
|
44 (define_insn "*membar"
|
|
45 [(set (match_operand:BLK 0 "" "")
|
|
46 (unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
|
|
47 "TARGET_V9"
|
|
48 "membar\t15"
|
|
49 [(set_attr "type" "multi")])
|
|
50
|
|
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" "")]
|
|
56 "TARGET_V9"
|
|
57 {
|
|
58 sparc_expand_compare_and_swap_12 (operands[0], operands[1],
|
|
59 operands[2], operands[3]);
|
|
60 DONE;
|
|
61 })
|
|
62
|
|
63 (define_expand "sync_compare_and_swap<mode>"
|
|
64 [(parallel
|
|
65 [(set (match_operand:I48MODE 0 "register_operand" "=r")
|
|
66 (match_operand:I48MODE 1 "memory_operand" ""))
|
|
67 (set (match_dup 1)
|
|
68 (unspec_volatile:I48MODE
|
|
69 [(match_operand:I48MODE 2 "register_operand" "")
|
|
70 (match_operand:I48MODE 3 "register_operand" "")]
|
|
71 UNSPECV_CAS))])]
|
|
72 "TARGET_V9"
|
|
73 {
|
|
74 if (! REG_P (XEXP (operands[1], 0)))
|
|
75 {
|
|
76 rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
|
|
77 operands[1] = replace_equiv_address (operands[1], addr);
|
|
78 }
|
|
79 emit_insn (gen_memory_barrier ());
|
|
80 })
|
|
81
|
|
82 (define_insn "*sync_compare_and_swap<mode>"
|
|
83 [(set (match_operand:I48MODE 0 "register_operand" "=r")
|
|
84 (match_operand:I48MODE 1 "memory_reg_operand" "+m"))
|
|
85 (set (match_dup 1)
|
|
86 (unspec_volatile:I48MODE
|
|
87 [(match_operand:I48MODE 2 "register_operand" "r")
|
|
88 (match_operand:I48MODE 3 "register_operand" "0")]
|
|
89 UNSPECV_CAS))]
|
|
90 "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
|
|
91 "cas<modesuffix>\t%1, %2, %0"
|
|
92 [(set_attr "type" "multi")])
|
|
93
|
|
94 (define_insn "*sync_compare_and_swapdi_v8plus"
|
|
95 [(set (match_operand:DI 0 "register_operand" "=h")
|
|
96 (match_operand:DI 1 "memory_reg_operand" "+m"))
|
|
97 (set (match_dup 1)
|
|
98 (unspec_volatile:DI
|
|
99 [(match_operand:DI 2 "register_operand" "h")
|
|
100 (match_operand:DI 3 "register_operand" "0")]
|
|
101 UNSPECV_CAS))]
|
|
102 "TARGET_V8PLUS"
|
|
103 {
|
|
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";
|
|
114 }
|
|
115 [(set_attr "type" "multi")
|
|
116 (set_attr "length" "8")])
|
|
117
|
|
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" "")]
|
|
122 "!TARGET_V9"
|
|
123 {
|
|
124 if (operands[2] != const1_rtx)
|
|
125 FAIL;
|
|
126 if (TARGET_V8)
|
|
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]));
|
|
131 DONE;
|
|
132 })
|
|
133
|
|
134 (define_expand "sync_lock_test_and_setsi"
|
|
135 [(parallel
|
|
136 [(set (match_operand:SI 0 "register_operand" "")
|
|
137 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
|
|
138 UNSPECV_SWAP))
|
|
139 (set (match_dup 1)
|
|
140 (match_operand:SI 2 "arith_operand" ""))])]
|
|
141 ""
|
|
142 {
|
|
143 if (! TARGET_V8 && ! TARGET_V9)
|
|
144 {
|
|
145 if (operands[2] != const1_rtx)
|
|
146 FAIL;
|
|
147 operands[1] = adjust_address (operands[1], QImode, 0);
|
|
148 emit_insn (gen_ldstubsi (operands[0], operands[1]));
|
|
149 DONE;
|
|
150 }
|
|
151 emit_insn (gen_memory_barrier ());
|
|
152 operands[2] = force_reg (SImode, operands[2]);
|
|
153 })
|
|
154
|
|
155 (define_insn "*swapsi"
|
|
156 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
157 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
|
|
158 UNSPECV_SWAP))
|
|
159 (set (match_dup 1)
|
|
160 (match_operand:SI 2 "register_operand" "0"))]
|
|
161 "TARGET_V8 || TARGET_V9"
|
|
162 "swap\t%1, %0"
|
|
163 [(set_attr "type" "multi")])
|
|
164
|
|
165 (define_expand "ldstubqi"
|
|
166 [(parallel [(set (match_operand:QI 0 "register_operand" "")
|
|
167 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
|
|
168 UNSPECV_LDSTUB))
|
|
169 (set (match_dup 1) (const_int -1))])]
|
|
170 ""
|
|
171 "")
|
|
172
|
|
173 (define_expand "ldstub<mode>"
|
|
174 [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
|
|
175 (zero_extend:I24MODE
|
|
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_insn "*ldstubqi"
|
|
183 [(set (match_operand:QI 0 "register_operand" "=r")
|
|
184 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
|
|
185 UNSPECV_LDSTUB))
|
|
186 (set (match_dup 1) (const_int -1))]
|
|
187 ""
|
|
188 "ldstub\t%1, %0"
|
|
189 [(set_attr "type" "multi")])
|
|
190
|
|
191 (define_insn "*ldstub<mode>"
|
|
192 [(set (match_operand:I24MODE 0 "register_operand" "=r")
|
|
193 (zero_extend:I24MODE
|
|
194 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
|
|
195 UNSPECV_LDSTUB)))
|
|
196 (set (match_dup 1) (const_int -1))]
|
|
197 ""
|
|
198 "ldstub\t%1, %0"
|
|
199 [(set_attr "type" "multi")])
|