]>
Commit | Line | Data |
---|---|---|
7a768814 | 1 | ;;- Machine description for SPARC chip for GNU C compiler |
eead6b5b | 2 | ;; Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc. |
8dffbc60 RK |
3 | ;; Contributed by Michael Tiemann (tiemann@cygnus.com) |
4 | ;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, | |
5 | ;; at Cygnus Support. | |
7a768814 RS |
6 | |
7 | ;; This file is part of GNU CC. | |
8 | ||
9 | ;; GNU CC is free software; you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation; either version 2, or (at your option) | |
12 | ;; any later version. | |
13 | ||
14 | ;; GNU CC is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU CC; see the file COPYING. If not, write to | |
3f63df56 RK |
21 | ;; the Free Software Foundation, 59 Temple Place - Suite 330, |
22 | ;; Boston, MA 02111-1307, USA. | |
7a768814 | 23 | |
7a768814 RS |
24 | ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. |
25 | ||
b6d3c4ba JW |
26 | ;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this |
27 | ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name | |
28 | ;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding | |
29 | ;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of | |
30 | ;; 'f' for all DF/TFmode values, including those that are specific to the v8. | |
c4ce6853 DE |
31 | ;; |
32 | ;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to | |
33 | ;; test TARGET_LIVE_G0 if we have TARGET_ARCH64. | |
b6d3c4ba | 34 | |
0f1f080e | 35 | ;; Attribute for cpu type. |
6cab8731 | 36 | ;; These must match the values for enum processor_type in sparc.h. |
3f79ef9b | 37 | (define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,sparclet,tsc701,v8plus,v9,ultrasparc" |
6cab8731 | 38 | (const (symbol_ref "sparc_cpu_attr"))) |
0f1f080e | 39 | |
eb582c5d DE |
40 | ;; Attribute for the instruction set. |
41 | ;; At present we only need to distinguish v9/!v9, but for clarity we | |
42 | ;; test TARGET_V8 too. | |
6d29fc41 | 43 | (define_attr "isa" "v6,v8,v9,sparclet" |
eb582c5d DE |
44 | (const |
45 | (cond [(symbol_ref "TARGET_V9") (const_string "v9") | |
6d29fc41 DE |
46 | (symbol_ref "TARGET_V8") (const_string "v8") |
47 | (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")] | |
eb582c5d DE |
48 | (const_string "v6")))) |
49 | ||
50 | ;; Architecture size. | |
c180bd1e | 51 | (define_attr "arch" "arch32bit,arch64bit" |
eb582c5d DE |
52 | (const |
53 | (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")] | |
54 | (const_string "arch32bit")))) | |
c180bd1e | 55 | |
c4ce6853 DE |
56 | ;; Whether -mlive-g0 is in effect. |
57 | (define_attr "live_g0" "no,yes" | |
58 | (const | |
59 | (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")] | |
60 | (const_string "no")))) | |
61 | ||
7a768814 RS |
62 | ;; Insn type. Used to default other attribute values. |
63 | ||
64 | ;; type "unary" insns have one input operand (1) and one output operand (0) | |
65 | ;; type "binary" insns have two input operands (1,2) and one output (0) | |
66 | ;; type "compare" insns have one or two input operands (0,1) and no output | |
67 | ;; type "call_no_delay_slot" is a call followed by an unimp instruction. | |
68 | ||
69 | (define_attr "type" | |
c180bd1e | 70 | "move,unary,binary,compare,load,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,address,imul,fpload,fpstore,fp,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc" |
7a768814 RS |
71 | (const_string "binary")) |
72 | ||
73 | ;; Set true if insn uses call-clobbered intermediate register. | |
74 | (define_attr "use_clobbered" "false,true" | |
75 | (if_then_else (and (eq_attr "type" "address") | |
76 | (match_operand 0 "clobbered_register" "")) | |
77 | (const_string "true") | |
78 | (const_string "false"))) | |
79 | ||
80 | ;; Length (in # of insns). | |
81 | (define_attr "length" "" | |
82 | (cond [(eq_attr "type" "load,fpload") | |
83 | (if_then_else (match_operand 1 "symbolic_memory_operand" "") | |
84 | (const_int 2) (const_int 1)) | |
85 | ||
86 | (eq_attr "type" "store,fpstore") | |
87 | (if_then_else (match_operand 0 "symbolic_memory_operand" "") | |
88 | (const_int 2) (const_int 1)) | |
89 | ||
90 | (eq_attr "type" "address") (const_int 2) | |
91 | ||
92 | (eq_attr "type" "binary") | |
93 | (if_then_else (ior (match_operand 2 "arith_operand" "") | |
94 | (match_operand 2 "arith_double_operand" "")) | |
95 | (const_int 1) (const_int 3)) | |
96 | ||
b4ac57ab RS |
97 | (eq_attr "type" "multi") (const_int 2) |
98 | ||
7a768814 RS |
99 | (eq_attr "type" "move,unary") |
100 | (if_then_else (ior (match_operand 1 "arith_operand" "") | |
101 | (match_operand 1 "arith_double_operand" "")) | |
102 | (const_int 1) (const_int 2))] | |
103 | ||
104 | (const_int 1))) | |
105 | ||
106 | (define_asm_attributes | |
107 | [(set_attr "length" "1") | |
108 | (set_attr "type" "multi")]) | |
109 | ||
110 | ;; Attributes for instruction and branch scheduling | |
111 | ||
112 | (define_attr "in_call_delay" "false,true" | |
e8d6096c | 113 | (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") |
7a768814 RS |
114 | (const_string "false") |
115 | (eq_attr "type" "load,fpload,store,fpstore") | |
116 | (if_then_else (eq_attr "length" "1") | |
117 | (const_string "true") | |
118 | (const_string "false")) | |
119 | (eq_attr "type" "address") | |
120 | (if_then_else (eq_attr "use_clobbered" "false") | |
121 | (const_string "true") | |
122 | (const_string "false"))] | |
123 | (if_then_else (eq_attr "length" "1") | |
124 | (const_string "true") | |
125 | (const_string "false")))) | |
126 | ||
127 | (define_delay (eq_attr "type" "call") | |
128 | [(eq_attr "in_call_delay" "true") (nil) (nil)]) | |
129 | ||
130 | ;; ??? Should implement the notion of predelay slots for floating point | |
131 | ;; branches. This would allow us to remove the nop always inserted before | |
132 | ;; a floating point branch. | |
133 | ||
cab55461 JW |
134 | ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions |
135 | ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so. | |
136 | ;; This is because doing so will add several pipeline stalls to the path | |
137 | ;; that the load/store did not come from. Unfortunately, there is no way | |
138 | ;; to prevent fill_eager_delay_slots from using load/store without completely | |
139 | ;; disabling them. For the SPEC benchmark set, this is a serious lose, | |
140 | ;; because it prevents us from moving back the final store of inner loops. | |
e8d6096c | 141 | |
7a768814 | 142 | (define_attr "in_branch_delay" "false,true" |
cab55461 | 143 | (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") |
e8d6096c JL |
144 | (eq_attr "length" "1")) |
145 | (const_string "true") | |
146 | (const_string "false"))) | |
147 | ||
148 | (define_attr "in_uncond_branch_delay" "false,true" | |
149 | (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") | |
150 | (eq_attr "length" "1")) | |
151 | (const_string "true") | |
152 | (const_string "false"))) | |
153 | ||
154 | (define_attr "in_annul_branch_delay" "false,true" | |
155 | (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") | |
7a768814 RS |
156 | (eq_attr "length" "1")) |
157 | (const_string "true") | |
158 | (const_string "false"))) | |
159 | ||
160 | (define_delay (eq_attr "type" "branch") | |
161 | [(eq_attr "in_branch_delay" "true") | |
e8d6096c | 162 | (nil) (eq_attr "in_annul_branch_delay" "true")]) |
7a768814 | 163 | |
e8d6096c JL |
164 | (define_delay (eq_attr "type" "uncond_branch") |
165 | [(eq_attr "in_uncond_branch_delay" "true") | |
166 | (nil) (nil)]) | |
167 | ||
7a768814 RS |
168 | ;; Function units of the SPARC |
169 | ||
170 | ;; (define_function_unit {name} {num-units} {n-users} {test} | |
af93f7bf | 171 | ;; {ready-delay} {issue-delay} [{conflict-list}]) |
7a768814 RS |
172 | |
173 | ;; The integer ALU. | |
174 | ;; (Noted only for documentation; units that take one cycle do not need to | |
175 | ;; be specified.) | |
176 | ||
114b9aa4 JW |
177 | ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on |
178 | ;; the inputs. | |
179 | ||
7a768814 RS |
180 | ;; (define_function_unit "alu" 1 0 |
181 | ;; (eq_attr "type" "unary,binary,move,address") 1 0) | |
182 | ||
c180bd1e | 183 | ;; ---- cypress CY7C602 scheduling: |
7a768814 | 184 | ;; Memory with load-delay of 1 (i.e., 2 cycle load). |
c180bd1e JW |
185 | (define_function_unit "memory" 1 0 |
186 | (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "cypress")) 2 2) | |
7a768814 RS |
187 | |
188 | ;; SPARC has two floating-point units: the FP ALU, | |
189 | ;; and the FP MUL/DIV/SQRT unit. | |
190 | ;; Instruction timings on the CY7C602 are as follows | |
191 | ;; FABSs 4 | |
192 | ;; FADDs/d 5/5 | |
193 | ;; FCMPs/d 4/4 | |
194 | ;; FDIVs/d 23/37 | |
195 | ;; FMOVs 4 | |
196 | ;; FMULs/d 5/7 | |
197 | ;; FNEGs 4 | |
198 | ;; FSQRTs/d 34/63 | |
199 | ;; FSUBs/d 5/5 | |
200 | ;; FdTOi/s 5/5 | |
201 | ;; FsTOi/d 5/5 | |
202 | ;; FiTOs/d 9/5 | |
203 | ||
204 | ;; The CY7C602 can only support 2 fp isnsn simultaneously. | |
ead69aea JW |
205 | ;; More insns cause the chip to stall. |
206 | ||
c180bd1e JW |
207 | (define_function_unit "fp_alu" 1 0 |
208 | (and (eq_attr "type" "fp") (eq_attr "cpu" "cypress")) 5 5) | |
209 | (define_function_unit "fp_mds" 1 0 | |
210 | (and (eq_attr "type" "fpmul") (eq_attr "cpu" "cypress")) 7 7) | |
211 | (define_function_unit "fp_mds" 1 0 | |
212 | (and (eq_attr "type" "fpdivs,fpdivd") (eq_attr "cpu" "cypress")) 37 37) | |
213 | (define_function_unit "fp_mds" 1 0 | |
214 | (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "cypress")) 63 63) | |
215 | ||
216 | ;; ----- The TMS390Z55 scheduling | |
217 | ;; The Supersparc can issue 1 - 3 insns per cycle; here we assume | |
218 | ;; three insns/cycle, and hence multiply all costs by three. | |
219 | ;; Combinations up to two integer, one ld/st, one fp. | |
220 | ;; Memory delivers its result in one cycle to IU, zero cycles to FP | |
221 | (define_function_unit "memory" 1 0 | |
222 | (and (eq_attr "type" "load") (eq_attr "cpu" "supersparc")) 3 3) | |
223 | (define_function_unit "memory" 1 0 | |
224 | (and (eq_attr "type" "fpload") (eq_attr "cpu" "supersparc")) 1 3) | |
225 | ;; at least one in three instructions can be a mem opt. | |
226 | (define_function_unit "memory" 1 0 | |
227 | (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "supersparc")) 1 3) | |
228 | ;; at least one in three instructions can be a shift op. | |
229 | (define_function_unit "shift" 1 0 | |
230 | (and (eq_attr "type" "shift") (eq_attr "cpu" "supersparc")) 1 3) | |
231 | ||
232 | ;; There are only two write ports to the integer register file | |
233 | ;; A store also uses a write port | |
234 | (define_function_unit "iwport" 2 0 | |
235 | (and (eq_attr "type" "load,store,shift,ialu") (eq_attr "cpu" "supersparc")) 1 3) | |
236 | ||
237 | ;; Timings; throughput/latency | |
238 | ;; FADD 1/3 add/sub, format conv, compar, abs, neg | |
239 | ;; FMUL 1/3 | |
240 | ;; FDIVs 4/6 | |
241 | ;; FDIVd 7/9 | |
242 | ;; FSQRTs 6/8 | |
243 | ;; FSQRTd 10/12 | |
244 | ;; IMUL 4/4 | |
245 | ||
246 | (define_function_unit "fp_alu" 1 0 | |
247 | (and (eq_attr "type" "fp,fpcmp") (eq_attr "cpu" "supersparc")) 9 3) | |
248 | (define_function_unit "fp_mds" 1 0 | |
249 | (and (eq_attr "type" "fpmul") (eq_attr "cpu" "supersparc")) 9 3) | |
250 | (define_function_unit "fp_mds" 1 0 | |
251 | (and (eq_attr "type" "fpdivs") (eq_attr "cpu" "supersparc")) 18 12) | |
252 | (define_function_unit "fp_mds" 1 0 | |
253 | (and (eq_attr "type" "fpdivd") (eq_attr "cpu" "supersparc")) 27 21) | |
254 | (define_function_unit "fp_mds" 1 0 | |
255 | (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "supersparc")) 36 30) | |
256 | (define_function_unit "fp_mds" 1 0 | |
257 | (and (eq_attr "type" "imul") (eq_attr "cpu" "supersparc")) 12 12) | |
967ba98d | 258 | |
3f79ef9b DE |
259 | ;; ----- sparclet tsc701 scheduling |
260 | ;; The tsc701 issues 1 insn per cycle. | |
967ba98d DE |
261 | ;; Results may be written back out of order. |
262 | ||
263 | ;; Loads take 2 extra cycles to complete and 4 can be buffered at a time. | |
3f79ef9b DE |
264 | (define_function_unit "tsc701_load" 4 1 |
265 | (and (eq_attr "type" "load") (eq_attr "cpu" "tsc701")) 3 1) | |
967ba98d DE |
266 | ;; Stores take 2(?) extra cycles to complete. |
267 | ;; It is desirable to not have any memory operation in the following 2 cycles. | |
268 | ;; (??? or 2 memory ops in the case of std). | |
3f79ef9b DE |
269 | (define_function_unit "tsc701_store" 1 0 |
270 | (and (eq_attr "type" "store") (eq_attr "cpu" "tsc701")) 3 3 | |
967ba98d DE |
271 | [(eq_attr "type" "load,store")]) |
272 | ;; The multiply unit has a latency of 5. | |
3f79ef9b DE |
273 | (define_function_unit "tsc701_mul" 1 0 |
274 | (and (eq_attr "type" "imul") (eq_attr "cpu" "tsc701")) 5 5) | |
770a0113 CK |
275 | |
276 | ;; ----- The UltraSPARC-1 scheduling | |
277 | ;; The Ultrasparc can issue 1 - 4 insns per cycle; here we assume | |
278 | ;; four insns/cycle, and hence multiply all costs by four. | |
279 | ||
280 | ;; Memory delivers its result in three cycles to IU, three cycles to FP | |
281 | (define_function_unit "memory" 1 0 | |
282 | (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "ultrasparc")) 12 4) | |
283 | (define_function_unit "memory" 1 0 | |
284 | (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "ultrasparc")) 4 4) | |
285 | (define_function_unit "ieu" 1 0 | |
286 | (and (eq_attr "type" "ialu") (eq_attr "cpu" "ultrasparc")) 1 2) | |
287 | (define_function_unit "ieu" 1 0 | |
288 | (and (eq_attr "type" "shift") (eq_attr "cpu" "ultrasparc")) 1 4) | |
289 | (define_function_unit "ieu" 1 0 | |
290 | (and (eq_attr "type" "cmove") (eq_attr "cpu" "ultrasparc")) 8 4) | |
291 | ||
292 | ;; Timings; throughput/latency | |
293 | ;; ?? FADD 1/3 add/sub, format conv, compar, abs, neg | |
294 | ;; ?? FMUL 1/3 | |
295 | ;; ?? FDIVs 1/12 | |
296 | ;; ?? FDIVd 1/22 | |
297 | ;; ?? FSQRTs 1/12 | |
298 | ;; ?? FSQRTd 1/22 | |
299 | ||
300 | (define_function_unit "fp" 1 0 | |
301 | (and (eq_attr "type" "fp") (eq_attr "cpu" "ultrasparc")) 12 2) | |
302 | (define_function_unit "fp" 1 0 | |
303 | (and (eq_attr "type" "fpcmp") (eq_attr "cpu" "ultrasparc")) 8 2) | |
304 | (define_function_unit "fp" 1 0 | |
305 | (and (eq_attr "type" "fpmul") (eq_attr "cpu" "ultrasparc")) 12 2) | |
306 | (define_function_unit "fp" 1 0 | |
307 | (and (eq_attr "type" "fpdivs") (eq_attr "cpu" "ultrasparc")) 48 2) | |
308 | (define_function_unit "fp" 1 0 | |
309 | (and (eq_attr "type" "fpdivd") (eq_attr "cpu" "ultrasparc")) 88 2) | |
310 | (define_function_unit "fp" 1 0 | |
311 | (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "ultrasparc")) 48 2) | |
7a768814 RS |
312 | \f |
313 | ;; Compare instructions. | |
314 | ;; This controls RTL generation and register allocation. | |
315 | ||
316 | ;; We generate RTL for comparisons and branches by having the cmpxx | |
317 | ;; patterns store away the operands. Then, the scc and bcc patterns | |
318 | ;; emit RTL for both the compare and the branch. | |
319 | ;; | |
320 | ;; We do this because we want to generate different code for an sne and | |
321 | ;; seq insn. In those cases, if the second operand of the compare is not | |
322 | ;; const0_rtx, we want to compute the xor of the two operands and test | |
323 | ;; it against zero. | |
324 | ;; | |
a8d2b752 | 325 | ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match |
7a768814 RS |
326 | ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc |
327 | ;; insns that actually require more than one machine instruction. | |
328 | ||
329 | ;; Put cmpsi first among compare insns so it matches two CONST_INT operands. | |
330 | ||
331 | (define_expand "cmpsi" | |
c4ce6853 | 332 | [(set (reg:CC 100) |
7a768814 RS |
333 | (compare:CC (match_operand:SI 0 "register_operand" "") |
334 | (match_operand:SI 1 "arith_operand" "")))] | |
335 | "" | |
336 | " | |
337 | { | |
338 | sparc_compare_op0 = operands[0]; | |
339 | sparc_compare_op1 = operands[1]; | |
340 | DONE; | |
341 | }") | |
342 | ||
a8d2b752 | 343 | (define_expand "cmpdi" |
c4ce6853 | 344 | [(set (reg:CCX 100) |
a8d2b752 DE |
345 | (compare:CCX (match_operand:DI 0 "register_operand" "") |
346 | (match_operand:DI 1 "arith_double_operand" "")))] | |
fa0f39e4 | 347 | "TARGET_ARCH64" |
a8d2b752 DE |
348 | " |
349 | { | |
350 | sparc_compare_op0 = operands[0]; | |
351 | sparc_compare_op1 = operands[1]; | |
352 | DONE; | |
353 | }") | |
354 | ||
7a768814 | 355 | (define_expand "cmpsf" |
c4ce6853 DE |
356 | ;; The 96 here isn't ever used by anyone. |
357 | [(set (reg:CCFP 96) | |
7a768814 RS |
358 | (compare:CCFP (match_operand:SF 0 "register_operand" "") |
359 | (match_operand:SF 1 "register_operand" "")))] | |
ab5519b7 | 360 | "TARGET_FPU" |
7a768814 RS |
361 | " |
362 | { | |
363 | sparc_compare_op0 = operands[0]; | |
364 | sparc_compare_op1 = operands[1]; | |
365 | DONE; | |
366 | }") | |
367 | ||
368 | (define_expand "cmpdf" | |
c4ce6853 DE |
369 | ;; The 96 here isn't ever used by anyone. |
370 | [(set (reg:CCFP 96) | |
7a768814 RS |
371 | (compare:CCFP (match_operand:DF 0 "register_operand" "") |
372 | (match_operand:DF 1 "register_operand" "")))] | |
ab5519b7 | 373 | "TARGET_FPU" |
7a768814 RS |
374 | " |
375 | { | |
376 | sparc_compare_op0 = operands[0]; | |
377 | sparc_compare_op1 = operands[1]; | |
378 | DONE; | |
379 | }") | |
380 | ||
795068a4 | 381 | (define_expand "cmptf" |
c4ce6853 DE |
382 | ;; The 96 here isn't ever used by anyone. |
383 | [(set (reg:CCFP 96) | |
795068a4 JW |
384 | (compare:CCFP (match_operand:TF 0 "register_operand" "") |
385 | (match_operand:TF 1 "register_operand" "")))] | |
ab5519b7 | 386 | "TARGET_FPU" |
795068a4 JW |
387 | " |
388 | { | |
389 | sparc_compare_op0 = operands[0]; | |
390 | sparc_compare_op1 = operands[1]; | |
391 | DONE; | |
392 | }") | |
393 | ||
967ba98d DE |
394 | ;; Now the compare DEFINE_INSNs. |
395 | ||
396 | (define_insn "*cmpsi_insn" | |
c4ce6853 | 397 | [(set (reg:CC 100) |
967ba98d DE |
398 | (compare:CC (match_operand:SI 0 "register_operand" "r") |
399 | (match_operand:SI 1 "arith_operand" "rI")))] | |
400 | "" | |
9ad2334b | 401 | "cmp %0,%1" |
967ba98d DE |
402 | [(set_attr "type" "compare")]) |
403 | ||
967ba98d | 404 | (define_insn "*cmpdi_sp64" |
c4ce6853 | 405 | [(set (reg:CCX 100) |
967ba98d DE |
406 | (compare:CCX (match_operand:DI 0 "register_operand" "r") |
407 | (match_operand:DI 1 "arith_double_operand" "rHI")))] | |
408 | "TARGET_ARCH64" | |
9ad2334b | 409 | "cmp %0,%1" |
967ba98d DE |
410 | [(set_attr "type" "compare")]) |
411 | ||
c4ce6853 DE |
412 | (define_insn "*cmpsf_fpe" |
413 | [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") | |
967ba98d DE |
414 | (compare:CCFPE (match_operand:SF 1 "register_operand" "f") |
415 | (match_operand:SF 2 "register_operand" "f")))] | |
c4ce6853 DE |
416 | "TARGET_FPU" |
417 | "* | |
418 | { | |
419 | if (TARGET_V9) | |
420 | return \"fcmpes %0,%1,%2\"; | |
421 | return \"fcmpes %1,%2\"; | |
422 | }" | |
967ba98d DE |
423 | [(set_attr "type" "fpcmp")]) |
424 | ||
c4ce6853 DE |
425 | (define_insn "*cmpdf_fpe" |
426 | [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") | |
967ba98d DE |
427 | (compare:CCFPE (match_operand:DF 1 "register_operand" "e") |
428 | (match_operand:DF 2 "register_operand" "e")))] | |
c4ce6853 DE |
429 | "TARGET_FPU" |
430 | "* | |
431 | { | |
432 | if (TARGET_V9) | |
433 | return \"fcmped %0,%1,%2\"; | |
434 | return \"fcmped %1,%2\"; | |
435 | }" | |
967ba98d DE |
436 | [(set_attr "type" "fpcmp")]) |
437 | ||
c4ce6853 DE |
438 | (define_insn "*cmptf_fpe" |
439 | [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c") | |
967ba98d DE |
440 | (compare:CCFPE (match_operand:TF 1 "register_operand" "e") |
441 | (match_operand:TF 2 "register_operand" "e")))] | |
c4ce6853 DE |
442 | "TARGET_FPU && TARGET_HARD_QUAD" |
443 | "* | |
444 | { | |
445 | if (TARGET_V9) | |
446 | return \"fcmpeq %0,%1,%2\"; | |
447 | return \"fcmpeq %1,%2\"; | |
448 | }" | |
967ba98d DE |
449 | [(set_attr "type" "fpcmp")]) |
450 | ||
c4ce6853 DE |
451 | (define_insn "*cmpsf_fp" |
452 | [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") | |
967ba98d DE |
453 | (compare:CCFP (match_operand:SF 1 "register_operand" "f") |
454 | (match_operand:SF 2 "register_operand" "f")))] | |
c4ce6853 DE |
455 | "TARGET_FPU" |
456 | "* | |
457 | { | |
458 | if (TARGET_V9) | |
459 | return \"fcmps %0,%1,%2\"; | |
460 | return \"fcmps %1,%2\"; | |
461 | }" | |
967ba98d DE |
462 | [(set_attr "type" "fpcmp")]) |
463 | ||
c4ce6853 DE |
464 | (define_insn "*cmpdf_fp" |
465 | [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") | |
967ba98d DE |
466 | (compare:CCFP (match_operand:DF 1 "register_operand" "e") |
467 | (match_operand:DF 2 "register_operand" "e")))] | |
c4ce6853 DE |
468 | "TARGET_FPU" |
469 | "* | |
470 | { | |
471 | if (TARGET_V9) | |
472 | return \"fcmpd %0,%1,%2\"; | |
473 | return \"fcmpd %1,%2\"; | |
474 | }" | |
967ba98d DE |
475 | [(set_attr "type" "fpcmp")]) |
476 | ||
c4ce6853 DE |
477 | (define_insn "*cmptf_fp" |
478 | [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c") | |
967ba98d DE |
479 | (compare:CCFP (match_operand:TF 1 "register_operand" "e") |
480 | (match_operand:TF 2 "register_operand" "e")))] | |
c4ce6853 DE |
481 | "TARGET_FPU && TARGET_HARD_QUAD" |
482 | "* | |
483 | { | |
484 | if (TARGET_V9) | |
485 | return \"fcmpq %0,%1,%2\"; | |
486 | return \"fcmpq %1,%2\"; | |
487 | }" | |
967ba98d DE |
488 | [(set_attr "type" "fpcmp")]) |
489 | \f | |
7a768814 | 490 | ;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this |
a8d2b752 DE |
491 | ;; without jumps using the addx/subx instructions. For seq/sne on v9 we use |
492 | ;; the same code as v8 (the addx/subx method has more applications). The | |
493 | ;; exception to this is "reg != 0" which can be done in one instruction on v9 | |
494 | ;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do | |
495 | ;; branches. | |
496 | ||
497 | ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they | |
7a768814 RS |
498 | ;; generate addcc/subcc instructions. |
499 | ||
a8d2b752 DE |
500 | (define_expand "seqsi_special" |
501 | [(set (match_dup 3) | |
502 | (xor:SI (match_operand:SI 1 "register_operand" "") | |
503 | (match_operand:SI 2 "register_operand" ""))) | |
7a768814 RS |
504 | (parallel [(set (match_operand:SI 0 "register_operand" "") |
505 | (eq:SI (match_dup 3) (const_int 0))) | |
c4ce6853 DE |
506 | (clobber (reg:CC 100))])] |
507 | "! TARGET_LIVE_G0" | |
7a768814 RS |
508 | "{ operands[3] = gen_reg_rtx (SImode); }") |
509 | ||
a8d2b752 DE |
510 | (define_expand "seqdi_special" |
511 | [(set (match_dup 3) | |
512 | (xor:DI (match_operand:DI 1 "register_operand" "") | |
513 | (match_operand:DI 2 "register_operand" ""))) | |
b0967cad DE |
514 | (set (match_operand:DI 0 "register_operand" "") |
515 | (eq:DI (match_dup 3) (const_int 0)))] | |
fa0f39e4 | 516 | "TARGET_ARCH64" |
a8d2b752 DE |
517 | "{ operands[3] = gen_reg_rtx (DImode); }") |
518 | ||
519 | (define_expand "snesi_special" | |
520 | [(set (match_dup 3) | |
521 | (xor:SI (match_operand:SI 1 "register_operand" "") | |
522 | (match_operand:SI 2 "register_operand" ""))) | |
7a768814 RS |
523 | (parallel [(set (match_operand:SI 0 "register_operand" "") |
524 | (ne:SI (match_dup 3) (const_int 0))) | |
c4ce6853 DE |
525 | (clobber (reg:CC 100))])] |
526 | "! TARGET_LIVE_G0" | |
7a768814 RS |
527 | "{ operands[3] = gen_reg_rtx (SImode); }") |
528 | ||
a8d2b752 DE |
529 | (define_expand "snedi_special" |
530 | [(set (match_dup 3) | |
531 | (xor:DI (match_operand:DI 1 "register_operand" "") | |
532 | (match_operand:DI 2 "register_operand" ""))) | |
b0967cad DE |
533 | (set (match_operand:DI 0 "register_operand" "") |
534 | (ne:DI (match_dup 3) (const_int 0)))] | |
fa0f39e4 | 535 | "TARGET_ARCH64" |
a8d2b752 DE |
536 | "{ operands[3] = gen_reg_rtx (DImode); }") |
537 | ||
538 | (define_expand "seqdi_special_trunc" | |
539 | [(set (match_dup 3) | |
540 | (xor:DI (match_operand:DI 1 "register_operand" "") | |
541 | (match_operand:DI 2 "register_operand" ""))) | |
b0967cad DE |
542 | (set (match_operand:SI 0 "register_operand" "") |
543 | (eq:DI (match_dup 3) (const_int 0)))] | |
fa0f39e4 | 544 | "TARGET_ARCH64" |
a8d2b752 DE |
545 | "{ operands[3] = gen_reg_rtx (DImode); }") |
546 | ||
547 | (define_expand "snedi_special_trunc" | |
548 | [(set (match_dup 3) | |
549 | (xor:DI (match_operand:DI 1 "register_operand" "") | |
550 | (match_operand:DI 2 "register_operand" ""))) | |
b0967cad DE |
551 | (set (match_operand:SI 0 "register_operand" "") |
552 | (ne:DI (match_dup 3) (const_int 0)))] | |
fa0f39e4 | 553 | "TARGET_ARCH64" |
a8d2b752 DE |
554 | "{ operands[3] = gen_reg_rtx (DImode); }") |
555 | ||
556 | (define_expand "seqsi_special_extend" | |
44965bad | 557 | [(set (match_dup 3) |
a8d2b752 DE |
558 | (xor:SI (match_operand:SI 1 "register_operand" "") |
559 | (match_operand:SI 2 "register_operand" ""))) | |
560 | (parallel [(set (match_operand:DI 0 "register_operand" "") | |
44965bad | 561 | (eq:SI (match_dup 3) (const_int 0))) |
c4ce6853 | 562 | (clobber (reg:CC 100))])] |
fa0f39e4 | 563 | "TARGET_ARCH64" |
44965bad | 564 | "{ operands[3] = gen_reg_rtx (SImode); }") |
a8d2b752 DE |
565 | |
566 | (define_expand "snesi_special_extend" | |
44965bad | 567 | [(set (match_dup 3) |
a8d2b752 DE |
568 | (xor:SI (match_operand:SI 1 "register_operand" "") |
569 | (match_operand:SI 2 "register_operand" ""))) | |
570 | (parallel [(set (match_operand:DI 0 "register_operand" "") | |
44965bad | 571 | (ne:SI (match_dup 3) (const_int 0))) |
c4ce6853 | 572 | (clobber (reg:CC 100))])] |
fa0f39e4 | 573 | "TARGET_ARCH64" |
44965bad | 574 | "{ operands[3] = gen_reg_rtx (SImode); }") |
a8d2b752 DE |
575 | |
576 | ;; ??? v9: Operand 0 needs a mode, so SImode was chosen. | |
577 | ;; However, the code handles both SImode and DImode. | |
7a768814 | 578 | (define_expand "seq" |
a8d2b752 | 579 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 580 | (eq:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 581 | "! TARGET_LIVE_G0" |
7a768814 | 582 | " |
387fd02d JW |
583 | { |
584 | if (GET_MODE (sparc_compare_op0) == SImode) | |
7a768814 | 585 | { |
a8d2b752 DE |
586 | rtx pat; |
587 | ||
588 | if (GET_MODE (operands[0]) == SImode) | |
589 | pat = gen_seqsi_special (operands[0], sparc_compare_op0, | |
590 | sparc_compare_op1); | |
fa0f39e4 | 591 | else if (! TARGET_ARCH64) |
a8d2b752 DE |
592 | FAIL; |
593 | else | |
594 | pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0, | |
595 | sparc_compare_op1); | |
596 | emit_insn (pat); | |
597 | DONE; | |
598 | } | |
599 | else if (GET_MODE (sparc_compare_op0) == DImode) | |
600 | { | |
601 | rtx pat; | |
602 | ||
fa0f39e4 DE |
603 | if (! TARGET_ARCH64) |
604 | FAIL; | |
605 | else if (GET_MODE (operands[0]) == SImode) | |
a8d2b752 DE |
606 | pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0, |
607 | sparc_compare_op1); | |
a8d2b752 DE |
608 | else |
609 | pat = gen_seqdi_special (operands[0], sparc_compare_op0, | |
610 | sparc_compare_op1); | |
611 | emit_insn (pat); | |
7a768814 RS |
612 | DONE; |
613 | } | |
387fd02d JW |
614 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) |
615 | { | |
616 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); | |
617 | emit_insn (gen_sne (operands[0])); | |
618 | DONE; | |
619 | } | |
a8d2b752 DE |
620 | else if (TARGET_V9) |
621 | { | |
622 | if (gen_v9_scc (EQ, operands)) | |
623 | DONE; | |
624 | /* fall through */ | |
625 | } | |
626 | operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); | |
7a768814 RS |
627 | }") |
628 | ||
a8d2b752 DE |
629 | ;; ??? v9: Operand 0 needs a mode, so SImode was chosen. |
630 | ;; However, the code handles both SImode and DImode. | |
7a768814 | 631 | (define_expand "sne" |
a8d2b752 | 632 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 633 | (ne:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 634 | "! TARGET_LIVE_G0" |
7a768814 | 635 | " |
387fd02d JW |
636 | { |
637 | if (GET_MODE (sparc_compare_op0) == SImode) | |
7a768814 | 638 | { |
a8d2b752 DE |
639 | rtx pat; |
640 | ||
641 | if (GET_MODE (operands[0]) == SImode) | |
642 | pat = gen_snesi_special (operands[0], sparc_compare_op0, | |
643 | sparc_compare_op1); | |
fa0f39e4 | 644 | else if (! TARGET_ARCH64) |
a8d2b752 DE |
645 | FAIL; |
646 | else | |
647 | pat = gen_snesi_special_extend (operands[0], sparc_compare_op0, | |
648 | sparc_compare_op1); | |
649 | emit_insn (pat); | |
650 | DONE; | |
651 | } | |
652 | else if (GET_MODE (sparc_compare_op0) == DImode) | |
653 | { | |
654 | rtx pat; | |
655 | ||
fa0f39e4 DE |
656 | if (! TARGET_ARCH64) |
657 | FAIL; | |
658 | else if (GET_MODE (operands[0]) == SImode) | |
a8d2b752 DE |
659 | pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0, |
660 | sparc_compare_op1); | |
a8d2b752 DE |
661 | else |
662 | pat = gen_snedi_special (operands[0], sparc_compare_op0, | |
663 | sparc_compare_op1); | |
664 | emit_insn (pat); | |
7a768814 RS |
665 | DONE; |
666 | } | |
387fd02d JW |
667 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) |
668 | { | |
669 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); | |
670 | emit_insn (gen_sne (operands[0])); | |
671 | DONE; | |
672 | } | |
a8d2b752 DE |
673 | else if (TARGET_V9) |
674 | { | |
675 | if (gen_v9_scc (NE, operands)) | |
676 | DONE; | |
677 | /* fall through */ | |
678 | } | |
679 | operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); | |
7a768814 RS |
680 | }") |
681 | ||
682 | (define_expand "sgt" | |
a8d2b752 | 683 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 684 | (gt:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 685 | "! TARGET_LIVE_G0" |
7a768814 | 686 | " |
387fd02d JW |
687 | { |
688 | if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
689 | { | |
690 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); | |
691 | emit_insn (gen_sne (operands[0])); | |
692 | DONE; | |
693 | } | |
a8d2b752 DE |
694 | else if (TARGET_V9) |
695 | { | |
696 | if (gen_v9_scc (GT, operands)) | |
697 | DONE; | |
698 | /* fall through */ | |
699 | } | |
387fd02d JW |
700 | operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); |
701 | }") | |
7a768814 RS |
702 | |
703 | (define_expand "slt" | |
a8d2b752 | 704 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 705 | (lt:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 706 | "! TARGET_LIVE_G0" |
7a768814 | 707 | " |
387fd02d JW |
708 | { |
709 | if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
710 | { | |
711 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); | |
712 | emit_insn (gen_sne (operands[0])); | |
713 | DONE; | |
714 | } | |
a8d2b752 DE |
715 | else if (TARGET_V9) |
716 | { | |
717 | if (gen_v9_scc (LT, operands)) | |
718 | DONE; | |
719 | /* fall through */ | |
720 | } | |
387fd02d JW |
721 | operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); |
722 | }") | |
7a768814 RS |
723 | |
724 | (define_expand "sge" | |
a8d2b752 | 725 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 726 | (ge:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 727 | "! TARGET_LIVE_G0" |
7a768814 | 728 | " |
387fd02d JW |
729 | { |
730 | if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
731 | { | |
732 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); | |
733 | emit_insn (gen_sne (operands[0])); | |
734 | DONE; | |
735 | } | |
a8d2b752 DE |
736 | else if (TARGET_V9) |
737 | { | |
738 | if (gen_v9_scc (GE, operands)) | |
739 | DONE; | |
740 | /* fall through */ | |
741 | } | |
387fd02d JW |
742 | operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); |
743 | }") | |
7a768814 RS |
744 | |
745 | (define_expand "sle" | |
a8d2b752 | 746 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 747 | (le:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 748 | "! TARGET_LIVE_G0" |
7a768814 | 749 | " |
387fd02d JW |
750 | { |
751 | if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
752 | { | |
753 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); | |
754 | emit_insn (gen_sne (operands[0])); | |
755 | DONE; | |
756 | } | |
a8d2b752 DE |
757 | else if (TARGET_V9) |
758 | { | |
759 | if (gen_v9_scc (LE, operands)) | |
760 | DONE; | |
761 | /* fall through */ | |
762 | } | |
387fd02d JW |
763 | operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); |
764 | }") | |
7a768814 RS |
765 | |
766 | (define_expand "sgtu" | |
a8d2b752 | 767 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 768 | (gtu:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 769 | "! TARGET_LIVE_G0" |
7a768814 RS |
770 | " |
771 | { | |
a8d2b752 | 772 | if (! TARGET_V9) |
7a768814 | 773 | { |
a8d2b752 DE |
774 | rtx tem; |
775 | ||
776 | /* We can do ltu easily, so if both operands are registers, swap them and | |
777 | do a LTU. */ | |
778 | if ((GET_CODE (sparc_compare_op0) == REG | |
779 | || GET_CODE (sparc_compare_op0) == SUBREG) | |
780 | && (GET_CODE (sparc_compare_op1) == REG | |
781 | || GET_CODE (sparc_compare_op1) == SUBREG)) | |
782 | { | |
783 | tem = sparc_compare_op0; | |
784 | sparc_compare_op0 = sparc_compare_op1; | |
785 | sparc_compare_op1 = tem; | |
786 | emit_insn (gen_sltu (operands[0])); | |
787 | DONE; | |
788 | } | |
7a768814 | 789 | } |
a8d2b752 DE |
790 | else |
791 | { | |
792 | if (gen_v9_scc (GTU, operands)) | |
793 | DONE; | |
794 | } | |
795 | operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); | |
7a768814 RS |
796 | }") |
797 | ||
798 | (define_expand "sltu" | |
a8d2b752 | 799 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 800 | (ltu:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 801 | "! TARGET_LIVE_G0" |
7a768814 | 802 | " |
a8d2b752 DE |
803 | { |
804 | if (TARGET_V9) | |
805 | { | |
806 | if (gen_v9_scc (LTU, operands)) | |
807 | DONE; | |
808 | } | |
809 | operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); | |
7a768814 RS |
810 | }") |
811 | ||
812 | (define_expand "sgeu" | |
a8d2b752 | 813 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 814 | (geu:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 815 | "! TARGET_LIVE_G0" |
7a768814 | 816 | " |
a8d2b752 DE |
817 | { |
818 | if (TARGET_V9) | |
819 | { | |
820 | if (gen_v9_scc (GEU, operands)) | |
821 | DONE; | |
822 | } | |
823 | operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); | |
7a768814 RS |
824 | }") |
825 | ||
826 | (define_expand "sleu" | |
a8d2b752 | 827 | [(set (match_operand:SI 0 "intreg_operand" "") |
7a768814 | 828 | (leu:SI (match_dup 1) (const_int 0)))] |
c4ce6853 | 829 | "! TARGET_LIVE_G0" |
7a768814 RS |
830 | " |
831 | { | |
a8d2b752 | 832 | if (! TARGET_V9) |
7a768814 | 833 | { |
a8d2b752 DE |
834 | rtx tem; |
835 | ||
836 | /* We can do geu easily, so if both operands are registers, swap them and | |
837 | do a GEU. */ | |
838 | if ((GET_CODE (sparc_compare_op0) == REG | |
839 | || GET_CODE (sparc_compare_op0) == SUBREG) | |
840 | && (GET_CODE (sparc_compare_op1) == REG | |
841 | || GET_CODE (sparc_compare_op1) == SUBREG)) | |
842 | { | |
843 | tem = sparc_compare_op0; | |
844 | sparc_compare_op0 = sparc_compare_op1; | |
845 | sparc_compare_op1 = tem; | |
846 | emit_insn (gen_sgeu (operands[0])); | |
847 | DONE; | |
848 | } | |
849 | } | |
850 | else | |
851 | { | |
852 | if (gen_v9_scc (LEU, operands)) | |
853 | DONE; | |
7a768814 | 854 | } |
7a768814 RS |
855 | operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); |
856 | }") | |
857 | ||
967ba98d | 858 | ;; Now the DEFINE_INSNs for the scc cases. |
a8d2b752 | 859 | |
7a768814 RS |
860 | ;; The SEQ and SNE patterns are special because they can be done |
861 | ;; without any branching and do not involve a COMPARE. | |
862 | ||
c8b3b7d6 | 863 | (define_insn "*snesi_zero" |
7a768814 | 864 | [(set (match_operand:SI 0 "register_operand" "=r") |
a8d2b752 DE |
865 | (ne:SI (match_operand:SI 1 "register_operand" "r") |
866 | (const_int 0))) | |
c4ce6853 DE |
867 | (clobber (reg:CC 100))] |
868 | "! TARGET_LIVE_G0" | |
7a768814 RS |
869 | "subcc %%g0,%1,%%g0\;addx %%g0,0,%0" |
870 | [(set_attr "type" "unary") | |
871 | (set_attr "length" "2")]) | |
872 | ||
c8b3b7d6 | 873 | (define_insn "*neg_snesi_zero" |
7a768814 RS |
874 | [(set (match_operand:SI 0 "register_operand" "=r") |
875 | (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r") | |
876 | (const_int 0)))) | |
c4ce6853 DE |
877 | (clobber (reg:CC 100))] |
878 | "! TARGET_LIVE_G0" | |
7a768814 RS |
879 | "subcc %%g0,%1,%%g0\;subx %%g0,0,%0" |
880 | [(set_attr "type" "unary") | |
881 | (set_attr "length" "2")]) | |
882 | ||
44965bad JW |
883 | (define_insn "*snesi_zero_extend" |
884 | [(set (match_operand:DI 0 "register_operand" "=r") | |
885 | (ne:SI (match_operand:SI 1 "register_operand" "r") | |
886 | (const_int 0))) | |
c4ce6853 | 887 | (clobber (reg:CC 100))] |
fa0f39e4 | 888 | "TARGET_ARCH64" |
44965bad JW |
889 | "subcc %%g0,%1,%%g0\;addx %%g0,0,%0" |
890 | [(set_attr "type" "unary") | |
891 | (set_attr "length" "2")]) | |
892 | ||
c8b3b7d6 | 893 | (define_insn "*snedi_zero" |
2808652a | 894 | [(set (match_operand:DI 0 "register_operand" "=&r") |
a8d2b752 | 895 | (ne:DI (match_operand:DI 1 "register_operand" "r") |
b0967cad | 896 | (const_int 0)))] |
fa0f39e4 | 897 | "TARGET_ARCH64" |
a8d2b752 DE |
898 | "mov 0,%0\;movrnz %1,1,%0" |
899 | [(set_attr "type" "unary") | |
900 | (set_attr "length" "2")]) | |
901 | ||
c8b3b7d6 | 902 | (define_insn "*neg_snedi_zero" |
2808652a | 903 | [(set (match_operand:DI 0 "register_operand" "=&r") |
a8d2b752 | 904 | (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r") |
b0967cad | 905 | (const_int 0))))] |
fa0f39e4 | 906 | "TARGET_ARCH64" |
a8d2b752 DE |
907 | "mov 0,%0\;movrnz %1,-1,%0" |
908 | [(set_attr "type" "unary") | |
909 | (set_attr "length" "2")]) | |
910 | ||
b0967cad | 911 | (define_insn "*snedi_zero_trunc" |
2808652a | 912 | [(set (match_operand:SI 0 "register_operand" "=&r") |
44965bad | 913 | (ne:DI (match_operand:DI 1 "register_operand" "r") |
b0967cad | 914 | (const_int 0)))] |
fa0f39e4 | 915 | "TARGET_ARCH64" |
44965bad JW |
916 | "mov 0,%0\;movrnz %1,1,%0" |
917 | [(set_attr "type" "unary") | |
918 | (set_attr "length" "2")]) | |
919 | ||
c8b3b7d6 | 920 | (define_insn "*seqsi_zero" |
7a768814 | 921 | [(set (match_operand:SI 0 "register_operand" "=r") |
a8d2b752 DE |
922 | (eq:SI (match_operand:SI 1 "register_operand" "r") |
923 | (const_int 0))) | |
c4ce6853 DE |
924 | (clobber (reg:CC 100))] |
925 | "! TARGET_LIVE_G0" | |
7a768814 RS |
926 | "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0" |
927 | [(set_attr "type" "unary") | |
928 | (set_attr "length" "2")]) | |
929 | ||
c8b3b7d6 | 930 | (define_insn "*neg_seqsi_zero" |
7a768814 RS |
931 | [(set (match_operand:SI 0 "register_operand" "=r") |
932 | (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r") | |
933 | (const_int 0)))) | |
c4ce6853 DE |
934 | (clobber (reg:CC 100))] |
935 | "! TARGET_LIVE_G0" | |
7a768814 RS |
936 | "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0" |
937 | [(set_attr "type" "unary") | |
938 | (set_attr "length" "2")]) | |
939 | ||
44965bad JW |
940 | (define_insn "*seqsi_zero_extend" |
941 | [(set (match_operand:DI 0 "register_operand" "=r") | |
942 | (eq:SI (match_operand:SI 1 "register_operand" "r") | |
943 | (const_int 0))) | |
c4ce6853 | 944 | (clobber (reg:CC 100))] |
fa0f39e4 | 945 | "TARGET_ARCH64" |
44965bad JW |
946 | "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0" |
947 | [(set_attr "type" "unary") | |
948 | (set_attr "length" "2")]) | |
949 | ||
c8b3b7d6 | 950 | (define_insn "*seqdi_zero" |
2808652a | 951 | [(set (match_operand:DI 0 "register_operand" "=&r") |
a8d2b752 | 952 | (eq:DI (match_operand:DI 1 "register_operand" "r") |
b0967cad | 953 | (const_int 0)))] |
fa0f39e4 | 954 | "TARGET_ARCH64" |
a8d2b752 DE |
955 | "mov 0,%0\;movrz %1,1,%0" |
956 | [(set_attr "type" "unary") | |
957 | (set_attr "length" "2")]) | |
958 | ||
c8b3b7d6 | 959 | (define_insn "*neg_seqdi_zero" |
2808652a | 960 | [(set (match_operand:DI 0 "register_operand" "=&r") |
a8d2b752 | 961 | (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r") |
b0967cad | 962 | (const_int 0))))] |
fa0f39e4 | 963 | "TARGET_ARCH64" |
a8d2b752 DE |
964 | "mov 0,%0\;movrz %1,-1,%0" |
965 | [(set_attr "type" "unary") | |
966 | (set_attr "length" "2")]) | |
967 | ||
b0967cad | 968 | (define_insn "*seqdi_zero_trunc" |
2808652a | 969 | [(set (match_operand:SI 0 "register_operand" "=&r") |
44965bad | 970 | (eq:DI (match_operand:DI 1 "register_operand" "r") |
b0967cad | 971 | (const_int 0)))] |
fa0f39e4 | 972 | "TARGET_ARCH64" |
44965bad JW |
973 | "mov 0,%0\;movrz %1,1,%0" |
974 | [(set_attr "type" "unary") | |
975 | (set_attr "length" "2")]) | |
976 | ||
7a768814 | 977 | ;; We can also do (x + (i == 0)) and related, so put them in. |
a8d2b752 DE |
978 | ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode |
979 | ;; versions for v9. | |
7a768814 | 980 | |
c8b3b7d6 | 981 | (define_insn "*x_plus_i_ne_0" |
7a768814 RS |
982 | [(set (match_operand:SI 0 "register_operand" "=r") |
983 | (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r") | |
984 | (const_int 0)) | |
985 | (match_operand:SI 2 "register_operand" "r"))) | |
c4ce6853 DE |
986 | (clobber (reg:CC 100))] |
987 | "! TARGET_LIVE_G0" | |
7a768814 RS |
988 | "subcc %%g0,%1,%%g0\;addx %2,0,%0" |
989 | [(set_attr "length" "2")]) | |
990 | ||
c8b3b7d6 | 991 | (define_insn "*x_minus_i_ne_0" |
7a768814 RS |
992 | [(set (match_operand:SI 0 "register_operand" "=r") |
993 | (minus:SI (match_operand:SI 2 "register_operand" "r") | |
994 | (ne:SI (match_operand:SI 1 "register_operand" "r") | |
995 | (const_int 0)))) | |
c4ce6853 DE |
996 | (clobber (reg:CC 100))] |
997 | "! TARGET_LIVE_G0" | |
7a768814 RS |
998 | "subcc %%g0,%1,%%g0\;subx %2,0,%0" |
999 | [(set_attr "length" "2")]) | |
1000 | ||
c8b3b7d6 | 1001 | (define_insn "*x_plus_i_eq_0" |
7a768814 RS |
1002 | [(set (match_operand:SI 0 "register_operand" "=r") |
1003 | (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r") | |
1004 | (const_int 0)) | |
1005 | (match_operand:SI 2 "register_operand" "r"))) | |
c4ce6853 DE |
1006 | (clobber (reg:CC 100))] |
1007 | "! TARGET_LIVE_G0" | |
7a768814 RS |
1008 | "subcc %%g0,%1,%%g0\;subx %2,-1,%0" |
1009 | [(set_attr "length" "2")]) | |
1010 | ||
c8b3b7d6 | 1011 | (define_insn "*x_minus_i_eq_0" |
7a768814 RS |
1012 | [(set (match_operand:SI 0 "register_operand" "=r") |
1013 | (minus:SI (match_operand:SI 2 "register_operand" "r") | |
1014 | (eq:SI (match_operand:SI 1 "register_operand" "r") | |
1015 | (const_int 0)))) | |
c4ce6853 DE |
1016 | (clobber (reg:CC 100))] |
1017 | "! TARGET_LIVE_G0" | |
7a768814 | 1018 | "subcc %%g0,%1,%%g0\;addx %2,-1,%0" |
b4ac57ab | 1019 | [(set_attr "length" "2")]) |
7a768814 | 1020 | |
a8d2b752 DE |
1021 | ;; We can also do GEU and LTU directly, but these operate after a compare. |
1022 | ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode | |
1023 | ;; versions for v9. | |
7a768814 | 1024 | |
c8b3b7d6 | 1025 | (define_insn "*sltu_insn" |
7a768814 | 1026 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 DE |
1027 | (ltu:SI (reg:CC 100) (const_int 0)))] |
1028 | "! TARGET_LIVE_G0" | |
7a768814 RS |
1029 | "addx %%g0,0,%0" |
1030 | [(set_attr "type" "misc")]) | |
1031 | ||
c8b3b7d6 | 1032 | (define_insn "*neg_sltu_insn" |
7a768814 | 1033 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 DE |
1034 | (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))] |
1035 | "! TARGET_LIVE_G0" | |
7a768814 RS |
1036 | "subx %%g0,0,%0" |
1037 | [(set_attr "type" "misc")]) | |
1038 | ||
1039 | ;; ??? Combine should canonicalize these next two to the same pattern. | |
c8b3b7d6 | 1040 | (define_insn "*neg_sltu_minus_x" |
7a768814 | 1041 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 | 1042 | (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0))) |
7a768814 | 1043 | (match_operand:SI 1 "arith_operand" "rI")))] |
c4ce6853 | 1044 | "! TARGET_LIVE_G0" |
7a768814 RS |
1045 | "subx %%g0,%1,%0" |
1046 | [(set_attr "type" "unary")]) | |
1047 | ||
c8b3b7d6 | 1048 | (define_insn "*neg_sltu_plus_x" |
7a768814 | 1049 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 | 1050 | (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) |
7a768814 | 1051 | (match_operand:SI 1 "arith_operand" "rI"))))] |
c4ce6853 | 1052 | "! TARGET_LIVE_G0" |
7a768814 RS |
1053 | "subx %%g0,%1,%0" |
1054 | [(set_attr "type" "unary")]) | |
1055 | ||
c8b3b7d6 | 1056 | (define_insn "*sgeu_insn" |
7a768814 | 1057 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 DE |
1058 | (geu:SI (reg:CC 100) (const_int 0)))] |
1059 | "! TARGET_LIVE_G0" | |
7a768814 RS |
1060 | "subx %%g0,-1,%0" |
1061 | [(set_attr "type" "misc")]) | |
1062 | ||
c8b3b7d6 | 1063 | (define_insn "*neg_sgeu_insn" |
7a768814 | 1064 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 DE |
1065 | (neg:SI (geu:SI (reg:CC 100) (const_int 0))))] |
1066 | "! TARGET_LIVE_G0" | |
7a768814 RS |
1067 | "addx %%g0,-1,%0" |
1068 | [(set_attr "type" "misc")]) | |
1069 | ||
1070 | ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in. | |
a8d2b752 DE |
1071 | ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode |
1072 | ;; versions for v9. | |
7a768814 | 1073 | |
c8b3b7d6 | 1074 | (define_insn "*sltu_plus_x" |
7a768814 | 1075 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 | 1076 | (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) |
7a768814 | 1077 | (match_operand:SI 1 "arith_operand" "rI")))] |
c4ce6853 | 1078 | "! TARGET_LIVE_G0" |
7a768814 RS |
1079 | "addx %%g0,%1,%0" |
1080 | [(set_attr "type" "unary")]) | |
1081 | ||
c8b3b7d6 | 1082 | (define_insn "*sltu_plus_x_plus_y" |
7a768814 | 1083 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 | 1084 | (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) |
7a768814 RS |
1085 | (plus:SI (match_operand:SI 1 "arith_operand" "%r") |
1086 | (match_operand:SI 2 "arith_operand" "rI"))))] | |
1087 | "" | |
b4ac57ab | 1088 | "addx %1,%2,%0") |
7a768814 | 1089 | |
c8b3b7d6 | 1090 | (define_insn "*x_minus_sltu" |
7a768814 RS |
1091 | [(set (match_operand:SI 0 "register_operand" "=r") |
1092 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
c4ce6853 | 1093 | (ltu:SI (reg:CC 100) (const_int 0))))] |
7a768814 RS |
1094 | "" |
1095 | "subx %1,0,%0" | |
1096 | [(set_attr "type" "unary")]) | |
1097 | ||
1098 | ;; ??? Combine should canonicalize these next two to the same pattern. | |
c8b3b7d6 | 1099 | (define_insn "*x_minus_y_minus_sltu" |
7a768814 RS |
1100 | [(set (match_operand:SI 0 "register_operand" "=r") |
1101 | (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") | |
1102 | (match_operand:SI 2 "arith_operand" "rI")) | |
c4ce6853 | 1103 | (ltu:SI (reg:CC 100) (const_int 0))))] |
7a768814 | 1104 | "" |
b4ac57ab | 1105 | "subx %1,%2,%0") |
7a768814 | 1106 | |
c8b3b7d6 | 1107 | (define_insn "*x_minus_sltu_plus_y" |
7a768814 RS |
1108 | [(set (match_operand:SI 0 "register_operand" "=r") |
1109 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
c4ce6853 | 1110 | (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) |
7a768814 RS |
1111 | (match_operand:SI 2 "arith_operand" "rI"))))] |
1112 | "" | |
b4ac57ab | 1113 | "subx %1,%2,%0") |
7a768814 | 1114 | |
c8b3b7d6 | 1115 | (define_insn "*sgeu_plus_x" |
7a768814 | 1116 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 | 1117 | (plus:SI (geu:SI (reg:CC 100) (const_int 0)) |
7a768814 RS |
1118 | (match_operand:SI 1 "register_operand" "r")))] |
1119 | "" | |
1120 | "subx %1,-1,%0" | |
1121 | [(set_attr "type" "unary")]) | |
1122 | ||
c8b3b7d6 | 1123 | (define_insn "*x_minus_sgeu" |
7a768814 RS |
1124 | [(set (match_operand:SI 0 "register_operand" "=r") |
1125 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
c4ce6853 | 1126 | (geu:SI (reg:CC 100) (const_int 0))))] |
7a768814 RS |
1127 | "" |
1128 | "addx %1,-1,%0" | |
1129 | [(set_attr "type" "unary")]) | |
1130 | ||
a8d2b752 DE |
1131 | ;; Now we have the generic scc insns. |
1132 | ;; !v9: These will be done using a jump. | |
1133 | ;; v9: Use conditional moves which are defined elsewhere. | |
7a768814 RS |
1134 | ;; We have to exclude the cases above, since we will not want combine to |
1135 | ;; turn something that does not require a jump into something that does. | |
a8d2b752 | 1136 | |
c8b3b7d6 | 1137 | (define_insn "*scc_si" |
7a768814 | 1138 | [(set (match_operand:SI 0 "register_operand" "=r") |
c4ce6853 DE |
1139 | (match_operator:SI 2 "noov_compare_op" |
1140 | [(match_operand 1 "icc_or_fcc_reg_operand" "") | |
1141 | (const_int 0)]))] | |
7a768814 RS |
1142 | "" |
1143 | "* return output_scc_insn (operands, insn); " | |
b4ac57ab RS |
1144 | [(set_attr "type" "multi") |
1145 | (set_attr "length" "3")]) | |
a8d2b752 | 1146 | |
c8b3b7d6 | 1147 | (define_insn "*scc_di" |
a8d2b752 | 1148 | [(set (match_operand:DI 0 "register_operand" "=r") |
c4ce6853 DE |
1149 | (match_operator:DI 2 "noov_compare_op" |
1150 | [(match_operand 1 "icc_or_fcc_reg_operand" "") | |
1151 | (const_int 0)]))] | |
fa0f39e4 | 1152 | "TARGET_ARCH64" |
a8d2b752 DE |
1153 | "* return output_scc_insn (operands, insn); " |
1154 | [(set_attr "type" "multi") | |
1155 | (set_attr "length" "3")]) | |
7a768814 RS |
1156 | \f |
1157 | ;; These control RTL generation for conditional jump insns | |
1158 | ||
ef903eca JW |
1159 | ;; The quad-word fp compare library routines all return nonzero to indicate |
1160 | ;; true, which is different from the equivalent libgcc routines, so we must | |
1161 | ;; handle them specially here. | |
1162 | ||
7a768814 RS |
1163 | (define_expand "beq" |
1164 | [(set (pc) | |
1165 | (if_then_else (eq (match_dup 1) (const_int 0)) | |
1166 | (label_ref (match_operand 0 "" "")) | |
1167 | (pc)))] | |
1168 | "" | |
1169 | " | |
ef903eca | 1170 | { |
fa0f39e4 | 1171 | if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx |
a8d2b752 DE |
1172 | && GET_CODE (sparc_compare_op0) == REG |
1173 | && GET_MODE (sparc_compare_op0) == DImode) | |
1174 | { | |
1175 | emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]); | |
1176 | DONE; | |
1177 | } | |
1178 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
ef903eca JW |
1179 | { |
1180 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); | |
a8d2b752 | 1181 | emit_jump_insn (gen_bne (operands[0])); |
ef903eca JW |
1182 | DONE; |
1183 | } | |
1184 | operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); | |
1185 | }") | |
7a768814 RS |
1186 | |
1187 | (define_expand "bne" | |
1188 | [(set (pc) | |
1189 | (if_then_else (ne (match_dup 1) (const_int 0)) | |
1190 | (label_ref (match_operand 0 "" "")) | |
1191 | (pc)))] | |
1192 | "" | |
1193 | " | |
ef903eca | 1194 | { |
fa0f39e4 | 1195 | if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx |
a8d2b752 DE |
1196 | && GET_CODE (sparc_compare_op0) == REG |
1197 | && GET_MODE (sparc_compare_op0) == DImode) | |
1198 | { | |
1199 | emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]); | |
1200 | DONE; | |
1201 | } | |
1202 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
ef903eca JW |
1203 | { |
1204 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); | |
a8d2b752 | 1205 | emit_jump_insn (gen_bne (operands[0])); |
ef903eca JW |
1206 | DONE; |
1207 | } | |
1208 | operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); | |
1209 | }") | |
7a768814 RS |
1210 | |
1211 | (define_expand "bgt" | |
1212 | [(set (pc) | |
1213 | (if_then_else (gt (match_dup 1) (const_int 0)) | |
1214 | (label_ref (match_operand 0 "" "")) | |
1215 | (pc)))] | |
1216 | "" | |
1217 | " | |
ef903eca | 1218 | { |
fa0f39e4 | 1219 | if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx |
a8d2b752 DE |
1220 | && GET_CODE (sparc_compare_op0) == REG |
1221 | && GET_MODE (sparc_compare_op0) == DImode) | |
1222 | { | |
1223 | emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]); | |
1224 | DONE; | |
1225 | } | |
1226 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
ef903eca JW |
1227 | { |
1228 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); | |
a8d2b752 | 1229 | emit_jump_insn (gen_bne (operands[0])); |
ef903eca JW |
1230 | DONE; |
1231 | } | |
1232 | operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); | |
1233 | }") | |
7a768814 RS |
1234 | |
1235 | (define_expand "bgtu" | |
1236 | [(set (pc) | |
1237 | (if_then_else (gtu (match_dup 1) (const_int 0)) | |
1238 | (label_ref (match_operand 0 "" "")) | |
1239 | (pc)))] | |
1240 | "" | |
1241 | " | |
1242 | { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1); | |
1243 | }") | |
1244 | ||
1245 | (define_expand "blt" | |
1246 | [(set (pc) | |
1247 | (if_then_else (lt (match_dup 1) (const_int 0)) | |
1248 | (label_ref (match_operand 0 "" "")) | |
1249 | (pc)))] | |
1250 | "" | |
1251 | " | |
ef903eca | 1252 | { |
fa0f39e4 | 1253 | if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx |
a8d2b752 DE |
1254 | && GET_CODE (sparc_compare_op0) == REG |
1255 | && GET_MODE (sparc_compare_op0) == DImode) | |
1256 | { | |
1257 | emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]); | |
1258 | DONE; | |
1259 | } | |
1260 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
ef903eca JW |
1261 | { |
1262 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); | |
a8d2b752 | 1263 | emit_jump_insn (gen_bne (operands[0])); |
ef903eca JW |
1264 | DONE; |
1265 | } | |
1266 | operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); | |
1267 | }") | |
7a768814 RS |
1268 | |
1269 | (define_expand "bltu" | |
1270 | [(set (pc) | |
1271 | (if_then_else (ltu (match_dup 1) (const_int 0)) | |
1272 | (label_ref (match_operand 0 "" "")) | |
1273 | (pc)))] | |
1274 | "" | |
1275 | " | |
1276 | { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1); | |
1277 | }") | |
1278 | ||
1279 | (define_expand "bge" | |
1280 | [(set (pc) | |
1281 | (if_then_else (ge (match_dup 1) (const_int 0)) | |
1282 | (label_ref (match_operand 0 "" "")) | |
1283 | (pc)))] | |
1284 | "" | |
1285 | " | |
ef903eca | 1286 | { |
fa0f39e4 | 1287 | if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx |
a8d2b752 DE |
1288 | && GET_CODE (sparc_compare_op0) == REG |
1289 | && GET_MODE (sparc_compare_op0) == DImode) | |
1290 | { | |
1291 | emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]); | |
1292 | DONE; | |
1293 | } | |
1294 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
ef903eca JW |
1295 | { |
1296 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); | |
a8d2b752 | 1297 | emit_jump_insn (gen_bne (operands[0])); |
ef903eca JW |
1298 | DONE; |
1299 | } | |
1300 | operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); | |
1301 | }") | |
7a768814 RS |
1302 | |
1303 | (define_expand "bgeu" | |
1304 | [(set (pc) | |
1305 | (if_then_else (geu (match_dup 1) (const_int 0)) | |
1306 | (label_ref (match_operand 0 "" "")) | |
1307 | (pc)))] | |
1308 | "" | |
1309 | " | |
1310 | { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1); | |
1311 | }") | |
1312 | ||
1313 | (define_expand "ble" | |
1314 | [(set (pc) | |
1315 | (if_then_else (le (match_dup 1) (const_int 0)) | |
1316 | (label_ref (match_operand 0 "" "")) | |
1317 | (pc)))] | |
1318 | "" | |
1319 | " | |
ef903eca | 1320 | { |
fa0f39e4 | 1321 | if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx |
a8d2b752 DE |
1322 | && GET_CODE (sparc_compare_op0) == REG |
1323 | && GET_MODE (sparc_compare_op0) == DImode) | |
1324 | { | |
1325 | emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]); | |
1326 | DONE; | |
1327 | } | |
1328 | else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) | |
ef903eca JW |
1329 | { |
1330 | emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); | |
a8d2b752 | 1331 | emit_jump_insn (gen_bne (operands[0])); |
ef903eca JW |
1332 | DONE; |
1333 | } | |
1334 | operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); | |
1335 | }") | |
7a768814 RS |
1336 | |
1337 | (define_expand "bleu" | |
1338 | [(set (pc) | |
1339 | (if_then_else (leu (match_dup 1) (const_int 0)) | |
1340 | (label_ref (match_operand 0 "" "")) | |
1341 | (pc)))] | |
1342 | "" | |
1343 | " | |
1344 | { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); | |
1345 | }") | |
1346 | \f | |
1347 | ;; Now match both normal and inverted jump. | |
1348 | ||
c8b3b7d6 | 1349 | (define_insn "*normal_branch" |
7a768814 RS |
1350 | [(set (pc) |
1351 | (if_then_else (match_operator 0 "noov_compare_op" | |
c4ce6853 | 1352 | [(reg 100) (const_int 0)]) |
7a768814 RS |
1353 | (label_ref (match_operand 1 "" "")) |
1354 | (pc)))] | |
1355 | "" | |
1356 | "* | |
1357 | { | |
c4ce6853 | 1358 | return output_cbranch (operands[0], 1, 0, |
7a768814 RS |
1359 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), |
1360 | ! final_sequence); | |
1361 | }" | |
1362 | [(set_attr "type" "branch")]) | |
1363 | ||
c8b3b7d6 | 1364 | (define_insn "*inverted_branch" |
7a768814 RS |
1365 | [(set (pc) |
1366 | (if_then_else (match_operator 0 "noov_compare_op" | |
c4ce6853 | 1367 | [(reg 100) (const_int 0)]) |
7a768814 RS |
1368 | (pc) |
1369 | (label_ref (match_operand 1 "" ""))))] | |
1370 | "" | |
1371 | "* | |
1372 | { | |
c4ce6853 | 1373 | return output_cbranch (operands[0], 1, 1, |
7a768814 RS |
1374 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), |
1375 | ! final_sequence); | |
1376 | }" | |
1377 | [(set_attr "type" "branch")]) | |
7a768814 | 1378 | |
c4ce6853 | 1379 | (define_insn "*normal_fp_branch" |
a8d2b752 | 1380 | [(set (pc) |
c4ce6853 DE |
1381 | (if_then_else (match_operator 1 "comparison_operator" |
1382 | [(match_operand:CCFP 0 "fcc_reg_operand" "c") | |
a8d2b752 DE |
1383 | (const_int 0)]) |
1384 | (label_ref (match_operand 2 "" "")) | |
1385 | (pc)))] | |
c4ce6853 | 1386 | "" |
a8d2b752 | 1387 | "* |
6a4bb1fa | 1388 | { |
c4ce6853 | 1389 | return output_cbranch (operands[1], 2, 0, |
a8d2b752 DE |
1390 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), |
1391 | ! final_sequence); | |
1392 | }" | |
1393 | [(set_attr "type" "branch")]) | |
6a4bb1fa | 1394 | |
c4ce6853 | 1395 | (define_insn "*inverted_fp_branch" |
a8d2b752 | 1396 | [(set (pc) |
c4ce6853 DE |
1397 | (if_then_else (match_operator 1 "comparison_operator" |
1398 | [(match_operand:CCFP 0 "fcc_reg_operand" "c") | |
a8d2b752 DE |
1399 | (const_int 0)]) |
1400 | (pc) | |
1401 | (label_ref (match_operand 2 "" ""))))] | |
c4ce6853 | 1402 | "" |
a8d2b752 DE |
1403 | "* |
1404 | { | |
c4ce6853 | 1405 | return output_cbranch (operands[1], 2, 1, |
a8d2b752 DE |
1406 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), |
1407 | ! final_sequence); | |
1408 | }" | |
1409 | [(set_attr "type" "branch")]) | |
6a4bb1fa | 1410 | |
c4ce6853 | 1411 | (define_insn "*normal_fpe_branch" |
a8d2b752 | 1412 | [(set (pc) |
c4ce6853 DE |
1413 | (if_then_else (match_operator 1 "comparison_operator" |
1414 | [(match_operand:CCFPE 0 "fcc_reg_operand" "c") | |
a8d2b752 DE |
1415 | (const_int 0)]) |
1416 | (label_ref (match_operand 2 "" "")) | |
1417 | (pc)))] | |
c4ce6853 | 1418 | "" |
a8d2b752 DE |
1419 | "* |
1420 | { | |
c4ce6853 | 1421 | return output_cbranch (operands[1], 2, 0, |
a8d2b752 DE |
1422 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), |
1423 | ! final_sequence); | |
1424 | }" | |
1425 | [(set_attr "type" "branch")]) | |
6a4bb1fa | 1426 | |
c4ce6853 | 1427 | (define_insn "*inverted_fpe_branch" |
a8d2b752 | 1428 | [(set (pc) |
c4ce6853 DE |
1429 | (if_then_else (match_operator 1 "comparison_operator" |
1430 | [(match_operand:CCFPE 0 "fcc_reg_operand" "c") | |
a8d2b752 DE |
1431 | (const_int 0)]) |
1432 | (pc) | |
1433 | (label_ref (match_operand 2 "" ""))))] | |
c4ce6853 | 1434 | "" |
a8d2b752 DE |
1435 | "* |
1436 | { | |
c4ce6853 | 1437 | return output_cbranch (operands[1], 2, 1, |
a8d2b752 DE |
1438 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), |
1439 | ! final_sequence); | |
1440 | }" | |
1441 | [(set_attr "type" "branch")]) | |
6a4bb1fa | 1442 | |
a8d2b752 DE |
1443 | ;; Sparc V9-specific jump insns. None of these are guaranteed to be |
1444 | ;; in the architecture. | |
1445 | ||
1446 | ;; There are no 32 bit brreg insns. | |
1447 | ||
c8b3b7d6 | 1448 | (define_insn "*normal_int_branch_sp64" |
a8d2b752 DE |
1449 | [(set (pc) |
1450 | (if_then_else (match_operator 0 "v9_regcmp_op" | |
1451 | [(match_operand:DI 1 "register_operand" "r") | |
1452 | (const_int 0)]) | |
1453 | (label_ref (match_operand 2 "" "")) | |
1454 | (pc)))] | |
fa0f39e4 | 1455 | "TARGET_ARCH64" |
a8d2b752 | 1456 | "* |
6a4bb1fa | 1457 | { |
a8d2b752 DE |
1458 | return output_v9branch (operands[0], 1, 2, 0, |
1459 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), | |
1460 | ! final_sequence); | |
1461 | }" | |
1462 | [(set_attr "type" "branch")]) | |
6a4bb1fa | 1463 | |
c8b3b7d6 | 1464 | (define_insn "*inverted_int_branch_sp64" |
a8d2b752 DE |
1465 | [(set (pc) |
1466 | (if_then_else (match_operator 0 "v9_regcmp_op" | |
1467 | [(match_operand:DI 1 "register_operand" "r") | |
1468 | (const_int 0)]) | |
1469 | (pc) | |
1470 | (label_ref (match_operand 2 "" ""))))] | |
fa0f39e4 | 1471 | "TARGET_ARCH64" |
a8d2b752 DE |
1472 | "* |
1473 | { | |
1474 | return output_v9branch (operands[0], 1, 2, 1, | |
1475 | final_sequence && INSN_ANNULLED_BRANCH_P (insn), | |
1476 | ! final_sequence); | |
1477 | }" | |
1478 | [(set_attr "type" "branch")]) | |
1479 | \f | |
1480 | ;; Esoteric move insns (lo_sum, high, pic). | |
6a4bb1fa | 1481 | |
c8b3b7d6 | 1482 | (define_insn "*lo_sum_si" |
a8d2b752 DE |
1483 | [(set (match_operand:SI 0 "register_operand" "=r") |
1484 | (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
1485 | (match_operand:SI 2 "immediate_operand" "in")))] | |
6a4bb1fa | 1486 | "" |
a8d2b752 DE |
1487 | ;; V9 needs "add" because of the code models. We still use "or" for v8 |
1488 | ;; so we can compare the old compiler with the new. | |
fa0f39e4 | 1489 | "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";" |
a8d2b752 DE |
1490 | ;; Need to set length for this arith insn because operand2 |
1491 | ;; is not an "arith_operand". | |
6a4bb1fa DE |
1492 | [(set_attr "length" "1")]) |
1493 | ||
a8d2b752 DE |
1494 | ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not |
1495 | ;; confuse them with real addresses. | |
95726648 | 1496 | (define_insn "pic_lo_sum_si" |
a8d2b752 DE |
1497 | [(set (match_operand:SI 0 "register_operand" "=r") |
1498 | (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
1499 | (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))] | |
95726648 | 1500 | "flag_pic" |
a8d2b752 DE |
1501 | ;; V9 needs "add" because of the code models. We still use "or" for v8 |
1502 | ;; so we can compare the old compiler with the new. | |
fa0f39e4 | 1503 | "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";" |
a8d2b752 DE |
1504 | ;; Need to set length for this arith insn because operand2 |
1505 | ;; is not an "arith_operand". | |
1506 | [(set_attr "length" "1")]) | |
7a768814 | 1507 | |
258ae59d DE |
1508 | ;; The PIC version of sethi must appear before the non-pic case so that |
1509 | ;; the unspec will not be matched as part of the operand. | |
a8d2b752 DE |
1510 | ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not |
1511 | ;; confuse them with real addresses. | |
95726648 | 1512 | (define_insn "pic_sethi_si" |
a8d2b752 DE |
1513 | [(set (match_operand:SI 0 "register_operand" "=r") |
1514 | (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] | |
95726648 | 1515 | "flag_pic && check_pic (1)" |
a8d2b752 DE |
1516 | "sethi %%hi(%a1),%0" |
1517 | [(set_attr "type" "move") | |
1518 | (set_attr "length" "1")]) | |
7a768814 | 1519 | |
7e37212e DM |
1520 | (define_insn "pic_lo_sum_di" |
1521 | [(set (match_operand:DI 0 "register_operand" "=r") | |
e9a25f70 JL |
1522 | (lo_sum:SI (match_operand:DI 1 "register_operand" "r") |
1523 | (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))] | |
7e37212e DM |
1524 | "TARGET_ARCH64 && flag_pic" |
1525 | "add %1,%%lo(%a2),%0" | |
1526 | [(set_attr "length" "1")]) | |
1527 | ||
1528 | (define_insn "pic_sethi_di" | |
1529 | [(set (match_operand:DI 0 "register_operand" "=r") | |
e9a25f70 | 1530 | (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] |
7e37212e DM |
1531 | "TARGET_ARCH64 && flag_pic && check_pic (1)" |
1532 | "sethi %%hi(%a1),%0" | |
1533 | [(set_attr "type" "move") | |
1534 | (set_attr "length" "1")]) | |
1535 | ||
5d4f5e87 | 1536 | (define_insn "get_pc_via_call" |
95726648 | 1537 | [(set (pc) (label_ref (match_operand 0 "" ""))) |
5d4f5e87 DE |
1538 | (set (reg:SI 15) (label_ref (match_operand 1 "" "")))] |
1539 | "" | |
95726648 DE |
1540 | "call %l0%#" |
1541 | [(set_attr "type" "uncond_branch")]) | |
7a768814 | 1542 | |
5d4f5e87 | 1543 | (define_insn "get_pc_via_rdpc" |
95726648 DE |
1544 | [(set (match_operand:DI 0 "register_operand" "=r") (pc))] |
1545 | "TARGET_PTR64" | |
1546 | "rd %%pc,%0" | |
1547 | [(set_attr "type" "move")]) | |
7a768814 RS |
1548 | |
1549 | ;; Special pic pattern, for loading the address of a label into a register. | |
1550 | ;; It clobbers o7 because the call puts the return address (i.e. pc value) | |
95726648 | 1551 | ;; there. The pic tablejump pattern also uses this. |
7a768814 | 1552 | |
95726648 | 1553 | (define_insn "move_pic_label_si" |
7a768814 | 1554 | [(set (match_operand:SI 0 "register_operand" "=r") |
9a46a605 DE |
1555 | ; This was previously (label_ref:SI (match_operand 1 "" "")) but that |
1556 | ; loses the volatil and other flags of the original label_ref. | |
1557 | (match_operand:SI 1 "label_ref_operand" "")) | |
7a768814 | 1558 | (set (reg:SI 15) (pc))] |
95726648 DE |
1559 | "flag_pic" |
1560 | "* | |
1561 | { | |
1562 | if (get_attr_length (insn) == 2) | |
1563 | return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\"; | |
1564 | else | |
1565 | return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\"; | |
1566 | }" | |
7a768814 | 1567 | [(set_attr "type" "multi") |
2ae508e5 | 1568 | ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs) |
95726648 | 1569 | (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc)) |
2ae508e5 | 1570 | (const_int 960)) |
95726648 DE |
1571 | (const_int 2) |
1572 | (const_int 4)))]) | |
1573 | ||
1574 | ;; Special sparc64 pattern for loading the address of a label into a register. | |
1575 | ;; The pic and non-pic cases are the same since it's the most efficient way. | |
1576 | ;; | |
1577 | ;; ??? The non-pic case doesn't need to use %o7, we could use a scratch | |
1578 | ;; instead. But the pic case doesn't need to use %o7 either. We handle them | |
1579 | ;; both here so that when this is fixed, they can both be fixed together. | |
1580 | ;; Don't forget that the pic jump table stuff uses %o7 (that will need to be | |
1581 | ;; changed too). | |
a8d2b752 | 1582 | |
95726648 | 1583 | (define_insn "move_label_di" |
a8d2b752 | 1584 | [(set (match_operand:DI 0 "register_operand" "=r") |
5ab7138b DE |
1585 | ; This was previously (label_ref:DI (match_operand 1 "" "")) but that |
1586 | ; loses the volatil and other flags of the original label_ref. | |
1587 | (match_operand:DI 1 "label_ref_operand" "")) | |
a8d2b752 | 1588 | (set (reg:DI 15) (pc))] |
fa0f39e4 | 1589 | "TARGET_ARCH64" |
95726648 DE |
1590 | "* |
1591 | { | |
1592 | if (get_attr_length (insn) == 2) | |
1593 | return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\"; | |
1594 | else | |
1595 | return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\"; | |
1596 | }" | |
a8d2b752 | 1597 | [(set_attr "type" "multi") |
2ae508e5 | 1598 | ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs) |
95726648 | 1599 | (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc)) |
2ae508e5 | 1600 | (const_int 960)) |
95726648 DE |
1601 | (const_int 2) |
1602 | (const_int 5)))]) | |
a8d2b752 | 1603 | |
200d7a32 DE |
1604 | (define_insn "*sethi_hi" |
1605 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1606 | (high:HI (match_operand 1 "" "")))] | |
1607 | "check_pic (1)" | |
1608 | "sethi %%hi(%a1),%0" | |
1609 | [(set_attr "type" "move") | |
1610 | (set_attr "length" "1")]) | |
1611 | ||
1612 | ;; This must appear after the PIC sethi so that the PIC unspec will not | |
1613 | ;; be matched as part of the operand. | |
1614 | (define_insn "*sethi_si" | |
1615 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1616 | (high:SI (match_operand 1 "" "")))] | |
1617 | "check_pic (1)" | |
1618 | "sethi %%hi(%a1),%0" | |
1619 | [(set_attr "type" "move") | |
1620 | (set_attr "length" "1")]) | |
1621 | ||
c8b3b7d6 | 1622 | (define_insn "*lo_sum_di_sp32" |
a8d2b752 DE |
1623 | [(set (match_operand:DI 0 "register_operand" "=r") |
1624 | (lo_sum:DI (match_operand:DI 1 "register_operand" "0") | |
1625 | (match_operand:DI 2 "immediate_operand" "in")))] | |
fa0f39e4 | 1626 | "! TARGET_ARCH64" |
a8d2b752 DE |
1627 | "* |
1628 | { | |
1629 | /* Don't output a 64 bit constant, since we can't trust the assembler to | |
1630 | handle it correctly. */ | |
1631 | if (GET_CODE (operands[2]) == CONST_DOUBLE) | |
5d4f5e87 DE |
1632 | operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2])); |
1633 | else if (GET_CODE (operands[2]) == CONST_INT | |
1634 | && HOST_BITS_PER_WIDE_INT > 32 | |
1635 | && INTVAL (operands[2]) > 0xffffffff) | |
1636 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff); | |
1637 | ||
103fa525 | 1638 | return \"or %L1,%%lo(%a2),%L0\"; |
a8d2b752 DE |
1639 | }" |
1640 | ;; Need to set length for this arith insn because operand2 | |
1641 | ;; is not an "arith_operand". | |
1642 | [(set_attr "length" "1")]) | |
1643 | ||
a8d2b752 DE |
1644 | ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add? |
1645 | ||
c8b3b7d6 | 1646 | (define_insn "*lo_sum_di_sp64" |
a8d2b752 DE |
1647 | [(set (match_operand:DI 0 "register_operand" "=r") |
1648 | (lo_sum:DI (match_operand:DI 1 "register_operand" "0") | |
1649 | (match_operand:DI 2 "immediate_operand" "in")))] | |
fa0f39e4 | 1650 | "TARGET_ARCH64" |
a8d2b752 DE |
1651 | "* |
1652 | { | |
1653 | /* Don't output a 64 bit constant, since we can't trust the assembler to | |
1654 | handle it correctly. */ | |
1655 | if (GET_CODE (operands[2]) == CONST_DOUBLE) | |
5d4f5e87 DE |
1656 | operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2])); |
1657 | else if (GET_CODE (operands[2]) == CONST_INT | |
1658 | && HOST_BITS_PER_WIDE_INT > 32 | |
1659 | && INTVAL (operands[2]) > 0xffffffff) | |
1660 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff); | |
1661 | ||
a8d2b752 DE |
1662 | /* Note that we use add here. This is important because Medium/Anywhere |
1663 | code model support depends on it. */ | |
1664 | return \"add %1,%%lo(%a2),%0\"; | |
1665 | }" | |
1666 | ;; Need to set length for this arith insn because operand2 | |
1667 | ;; is not an "arith_operand". | |
1668 | [(set_attr "length" "1")]) | |
1669 | ||
c8b3b7d6 | 1670 | (define_insn "*sethi_di_sp32" |
7a768814 RS |
1671 | [(set (match_operand:DI 0 "register_operand" "=r") |
1672 | (high:DI (match_operand 1 "" "")))] | |
fa0f39e4 | 1673 | "! TARGET_ARCH64 && check_pic (1)" |
7a768814 RS |
1674 | "* |
1675 | { | |
1676 | rtx op0 = operands[0]; | |
1677 | rtx op1 = operands[1]; | |
1678 | ||
1679 | if (GET_CODE (op1) == CONST_INT) | |
1680 | { | |
1681 | operands[0] = operand_subword (op0, 1, 0, DImode); | |
1682 | output_asm_insn (\"sethi %%hi(%a1),%0\", operands); | |
1683 | ||
1684 | operands[0] = operand_subword (op0, 0, 0, DImode); | |
1685 | if (INTVAL (op1) < 0) | |
80f9d7f2 | 1686 | return \"mov -1,%0\"; |
7a768814 | 1687 | else |
80f9d7f2 | 1688 | return \"mov 0,%0\"; |
7a768814 RS |
1689 | } |
1690 | else if (GET_CODE (op1) == CONST_DOUBLE) | |
1691 | { | |
1692 | operands[0] = operand_subword (op0, 1, 0, DImode); | |
5d4f5e87 | 1693 | operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1)); |
7a768814 RS |
1694 | output_asm_insn (\"sethi %%hi(%a1),%0\", operands); |
1695 | ||
1696 | operands[0] = operand_subword (op0, 0, 0, DImode); | |
5d4f5e87 | 1697 | operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1)); |
80f9d7f2 | 1698 | return singlemove_string (operands); |
7a768814 RS |
1699 | } |
1700 | else | |
1701 | abort (); | |
d3548a5b | 1702 | return \"\"; |
7a768814 RS |
1703 | }" |
1704 | [(set_attr "type" "move") | |
1705 | (set_attr "length" "2")]) | |
1706 | ||
a8d2b752 | 1707 | ;;; ??? This pattern originally clobbered a scratch register. However, this |
3826a3da | 1708 | ;;; is invalid, the movdi pattern may not use a temp register because it |
a8d2b752 DE |
1709 | ;;; may be called from reload to reload a DImode value. In that case, we |
1710 | ;;; end up with a scratch register that never gets allocated. To avoid this, | |
1711 | ;;; we use global register 1 which is never otherwise used by gcc as a temp. | |
1712 | ;;; The correct solution here might be to force DImode constants to memory, | |
1713 | ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg | |
1714 | ;;; 1 will then no longer need to be considered a fixed reg. | |
1715 | ||
95726648 DE |
1716 | (define_expand "sethi_di_sp64" |
1717 | [(parallel | |
1718 | [(set (match_operand:DI 0 "register_operand" "") | |
1719 | (high:DI (match_operand 1 "general_operand" ""))) | |
1720 | (clobber (reg:DI 1))])] | |
1721 | "TARGET_ARCH64" | |
1722 | "") | |
a8d2b752 | 1723 | |
95726648 | 1724 | (define_insn "*sethi_di_sp64_const" |
a8d2b752 DE |
1725 | [(set (match_operand:DI 0 "register_operand" "=r") |
1726 | (high:DI (match_operand 1 "const_double_operand" ""))) | |
1727 | (clobber (reg:DI 1))] | |
fa0f39e4 | 1728 | "TARGET_ARCH64 && check_pic (1)" |
a8d2b752 DE |
1729 | "* |
1730 | { | |
5d4f5e87 | 1731 | #if HOST_BITS_PER_WIDE_INT == 32 |
a8d2b752 DE |
1732 | rtx high, low; |
1733 | ||
1734 | split_double (operands[1], &high, &low); | |
1735 | ||
1736 | if (high == const0_rtx) | |
1737 | { | |
1738 | operands[1] = low; | |
1739 | output_asm_insn (\"sethi %%hi(%a1),%0\", operands); | |
1740 | } | |
1741 | else | |
1742 | { | |
1743 | operands[1] = high; | |
1744 | output_asm_insn (singlemove_string (operands), operands); | |
1745 | ||
1746 | operands[1] = low; | |
1747 | output_asm_insn (\"sllx %0,32,%0\", operands); | |
1748 | if (low != const0_rtx) | |
1749 | output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands); | |
1750 | } | |
5d4f5e87 DE |
1751 | #else |
1752 | rtx op = operands[1]; | |
1753 | ||
1754 | if (! SPARC_SETHI_P (INTVAL(op))) | |
1755 | { | |
1756 | operands[1] = GEN_INT (INTVAL (op) >> 32); | |
1757 | output_asm_insn (singlemove_string (operands), operands); | |
1758 | ||
1759 | output_asm_insn (\"sllx %0,32,%0\", operands); | |
1760 | if (INTVAL (op) & 0xffffffff) | |
1761 | { | |
1762 | operands[1] = GEN_INT (INTVAL (op) & 0xffffffff); | |
1763 | output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands); | |
1764 | } | |
1765 | } | |
1766 | else | |
1767 | { | |
1768 | output_asm_insn (\"sethi %%hi(%a1),%0\", operands); | |
1769 | } | |
1770 | #endif | |
b7d9c418 RK |
1771 | |
1772 | return \"\"; | |
a8d2b752 | 1773 | }" |
b4ac57ab | 1774 | [(set_attr "type" "move") |
a8d2b752 DE |
1775 | (set_attr "length" "5")]) |
1776 | ||
1777 | ;; Most of the required support for the various code models is here. | |
1778 | ;; We can do this because sparcs need the high insn to load the address. We | |
1779 | ;; just need to get high to do the right thing for each code model. Then each | |
a0a301fc DE |
1780 | ;; uses the same "%X+%lo(...)" in the load/store insn, though in the case of |
1781 | ;; the medium/middle code model "%lo" is written "%l44". | |
a8d2b752 | 1782 | |
a0a301fc | 1783 | ;; When TARGET_CM_MEDLOW, assume that the upper 32 bits of symbol addresses are |
a8d2b752 | 1784 | ;; always 0. |
a0a301fc DE |
1785 | ;; When TARGET_CM_MEDMID, the executable must be in the low 16 TB of memory. |
1786 | ;; This corresponds to the low 44 bits, and the %[hml]44 relocs are used. | |
1787 | ;; ??? Not implemented yet. | |
1788 | ;; When TARGET_CM_EMBMEDANY, the text and data segments have a maximum size of | |
1789 | ;; 31 bits and may be located anywhere. EMBMEDANY_BASE_REG contains the start | |
95726648 | 1790 | ;; address of the data segment, currently %g4. |
a0a301fc DE |
1791 | ;; When TARGET_CM_MEDANY, the text and data segments have a maximum size of 31 |
1792 | ;; bits and may be located anywhere. The maximum offset from any instruction | |
1793 | ;; to the label _GLOBAL_OFFSET_TABLE_ is 31 bits. | |
b4ac57ab | 1794 | |
c8b3b7d6 | 1795 | (define_insn "*sethi_di_medlow" |
a8d2b752 DE |
1796 | [(set (match_operand:DI 0 "register_operand" "=r") |
1797 | (high:DI (match_operand 1 "" ""))) | |
fa0f39e4 | 1798 | ;; The clobber is here because emit_move_sequence assumes the worst case. |
a8d2b752 | 1799 | (clobber (reg:DI 1))] |
a0a301fc | 1800 | "TARGET_CM_MEDLOW && check_pic (1)" |
7a768814 RS |
1801 | "sethi %%hi(%a1),%0" |
1802 | [(set_attr "type" "move") | |
1803 | (set_attr "length" "1")]) | |
1804 | ||
95726648 DE |
1805 | (define_insn "*sethi_di_medium_pic" |
1806 | [(set (match_operand:DI 0 "register_operand" "=r") | |
1807 | (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))] | |
a0a301fc | 1808 | "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)" |
95726648 DE |
1809 | "sethi %%hi(%a1),%0" |
1810 | [(set_attr "type" "move") | |
1811 | (set_attr "length" "1")]) | |
1812 | ||
a8d2b752 DE |
1813 | ;; WARNING: %0 gets %hi(%1)+%g4. |
1814 | ;; You cannot OR in %lo(%1), it must be added in. | |
1815 | ||
a0a301fc | 1816 | (define_insn "*sethi_di_embmedany_data" |
a8d2b752 DE |
1817 | [(set (match_operand:DI 0 "register_operand" "=r") |
1818 | (high:DI (match_operand 1 "data_segment_operand" ""))) | |
fa0f39e4 | 1819 | ;; The clobber is here because emit_move_sequence assumes the worst case. |
a8d2b752 | 1820 | (clobber (reg:DI 1))] |
a0a301fc DE |
1821 | "TARGET_CM_EMBMEDANY && check_pic (1)" |
1822 | "sethi %%hi(%a1),%0; add %0,%_,%0" | |
a8d2b752 DE |
1823 | [(set_attr "type" "move") |
1824 | (set_attr "length" "2")]) | |
1825 | ||
a0a301fc | 1826 | (define_insn "*sethi_di_embmedany_text" |
a8d2b752 DE |
1827 | [(set (match_operand:DI 0 "register_operand" "=r") |
1828 | (high:DI (match_operand 1 "text_segment_operand" ""))) | |
fa0f39e4 | 1829 | ;; The clobber is here because emit_move_sequence assumes the worst case. |
a8d2b752 | 1830 | (clobber (reg:DI 1))] |
a0a301fc | 1831 | "TARGET_CM_EMBMEDANY && check_pic (1)" |
a8d2b752 DE |
1832 | "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0" |
1833 | [(set_attr "type" "move") | |
1834 | (set_attr "length" "5")]) | |
1835 | \f | |
1836 | ;; Move instructions | |
1837 | ||
1838 | (define_expand "movqi" | |
1839 | [(set (match_operand:QI 0 "general_operand" "") | |
1840 | (match_operand:QI 1 "general_operand" ""))] | |
1841 | "" | |
1842 | " | |
1843 | { | |
1844 | if (emit_move_sequence (operands, QImode)) | |
1845 | DONE; | |
1846 | }") | |
1847 | ||
c8b3b7d6 | 1848 | (define_insn "*movqi_insn" |
a8d2b752 DE |
1849 | [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") |
1850 | (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))] | |
c4ce6853 DE |
1851 | "! TARGET_LIVE_G0 |
1852 | && (register_operand (operands[0], QImode) | |
1853 | || register_operand (operands[1], QImode) | |
1854 | || operands[1] == const0_rtx)" | |
a8d2b752 DE |
1855 | "@ |
1856 | mov %1,%0 | |
1857 | sethi %%hi(%a1),%0 | |
1858 | ldub %1,%0 | |
1859 | stb %r1,%0" | |
1860 | [(set_attr "type" "move,move,load,store") | |
04e1602e | 1861 | (set_attr "length" "1")]) |
a8d2b752 | 1862 | |
c4ce6853 DE |
1863 | (define_insn "*movqi_insn_liveg0" |
1864 | [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q") | |
1865 | (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))] | |
1866 | "TARGET_LIVE_G0 | |
1867 | && (register_operand (operands[0], QImode) | |
1868 | || register_operand (operands[1], QImode))" | |
1869 | "@ | |
1870 | mov %1,%0 | |
1871 | and %0,0,%0 | |
1872 | and %0,0,%0\;or %0,%1,%0 | |
1873 | sethi %%hi(%a1),%0 | |
1874 | ldub %1,%0 | |
1875 | stb %1,%0" | |
1876 | [(set_attr "type" "move,move,move,move,load,store") | |
1877 | (set_attr "length" "1,1,2,1,1,1")]) | |
1878 | ||
c8b3b7d6 | 1879 | (define_insn "*lo_sum_qi" |
a8d2b752 DE |
1880 | [(set (match_operand:QI 0 "register_operand" "=r") |
1881 | (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") | |
1882 | (match_operand 2 "immediate_operand" "in")) 0))] | |
1883 | "" | |
1884 | "or %1,%%lo(%a2),%0" | |
1885 | [(set_attr "length" "1")]) | |
1886 | ||
c8b3b7d6 | 1887 | (define_insn "*store_qi" |
a8d2b752 DE |
1888 | [(set (mem:QI (match_operand:SI 0 "symbolic_operand" "")) |
1889 | (match_operand:QI 1 "reg_or_0_operand" "rJ")) | |
1890 | (clobber (match_scratch:SI 2 "=&r"))] | |
c4ce6853 DE |
1891 | "(reload_completed || reload_in_progress) |
1892 | && ! TARGET_PTR64" | |
a8d2b752 DE |
1893 | "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]" |
1894 | [(set_attr "type" "store") | |
1895 | (set_attr "length" "2")]) | |
1896 | ||
1897 | (define_expand "movhi" | |
1898 | [(set (match_operand:HI 0 "general_operand" "") | |
1899 | (match_operand:HI 1 "general_operand" ""))] | |
1900 | "" | |
1901 | " | |
1902 | { | |
1903 | if (emit_move_sequence (operands, HImode)) | |
1904 | DONE; | |
1905 | }") | |
1906 | ||
c8b3b7d6 | 1907 | (define_insn "*movhi_insn" |
a8d2b752 DE |
1908 | [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") |
1909 | (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))] | |
c4ce6853 DE |
1910 | "! TARGET_LIVE_G0 |
1911 | && (register_operand (operands[0], HImode) | |
1912 | || register_operand (operands[1], HImode) | |
1913 | || operands[1] == const0_rtx)" | |
a8d2b752 DE |
1914 | "@ |
1915 | mov %1,%0 | |
1916 | sethi %%hi(%a1),%0 | |
1917 | lduh %1,%0 | |
1918 | sth %r1,%0" | |
1919 | [(set_attr "type" "move,move,load,store") | |
04e1602e | 1920 | (set_attr "length" "1")]) |
a8d2b752 | 1921 | |
c4ce6853 DE |
1922 | (define_insn "*movhi_insn_liveg0" |
1923 | [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q") | |
1924 | (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))] | |
1925 | "TARGET_LIVE_G0 | |
1926 | && (register_operand (operands[0], HImode) | |
1927 | || register_operand (operands[1], HImode))" | |
1928 | "@ | |
1929 | mov %1,%0 | |
1930 | and %0,0,%0 | |
1931 | and %0,0,%0\;or %0,%1,%0 | |
1932 | sethi %%hi(%a1),%0 | |
1933 | lduh %1,%0 | |
1934 | sth %1,%0" | |
1935 | [(set_attr "type" "move,move,move,move,load,store") | |
1936 | (set_attr "length" "1,1,2,1,1,1")]) | |
1937 | ||
c8b3b7d6 | 1938 | (define_insn "*lo_sum_hi" |
a8d2b752 DE |
1939 | [(set (match_operand:HI 0 "register_operand" "=r") |
1940 | (lo_sum:HI (match_operand:HI 1 "register_operand" "r") | |
1941 | (match_operand 2 "immediate_operand" "in")))] | |
b4ac57ab RS |
1942 | "" |
1943 | "or %1,%%lo(%a2),%0" | |
b4ac57ab RS |
1944 | [(set_attr "length" "1")]) |
1945 | ||
c8b3b7d6 | 1946 | (define_insn "*store_hi" |
a8d2b752 DE |
1947 | [(set (mem:HI (match_operand:SI 0 "symbolic_operand" "")) |
1948 | (match_operand:HI 1 "reg_or_0_operand" "rJ")) | |
1949 | (clobber (match_scratch:SI 2 "=&r"))] | |
c4ce6853 DE |
1950 | "(reload_completed || reload_in_progress) |
1951 | && ! TARGET_PTR64" | |
a8d2b752 DE |
1952 | "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]" |
1953 | [(set_attr "type" "store") | |
1954 | (set_attr "length" "2")]) | |
1955 | ||
1956 | (define_expand "movsi" | |
1957 | [(set (match_operand:SI 0 "general_operand" "") | |
1958 | (match_operand:SI 1 "general_operand" ""))] | |
7a768814 | 1959 | "" |
a8d2b752 DE |
1960 | " |
1961 | { | |
1962 | if (emit_move_sequence (operands, SImode)) | |
1963 | DONE; | |
1964 | }") | |
1965 | ||
1966 | ;; We must support both 'r' and 'f' registers here, because combine may | |
1967 | ;; convert SFmode hard registers to SImode hard registers when simplifying | |
1968 | ;; subreg sets. | |
1969 | ||
1970 | ;; We cannot combine the similar 'r' and 'f' constraints, because it causes | |
1971 | ;; problems with register allocation. Reload might try to put an integer | |
1972 | ;; in an fp register, or an fp number is an integer register. | |
1973 | ||
c8b3b7d6 | 1974 | (define_insn "*movsi_insn" |
a8d2b752 DE |
1975 | [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q") |
1976 | (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))] | |
c4ce6853 DE |
1977 | "! TARGET_LIVE_G0 |
1978 | && (register_operand (operands[0], SImode) | |
1979 | || register_operand (operands[1], SImode) | |
1980 | || operands[1] == const0_rtx)" | |
a8d2b752 DE |
1981 | "@ |
1982 | mov %1,%0 | |
1983 | fmovs %1,%0 | |
1984 | sethi %%hi(%a1),%0 | |
1985 | ld %1,%0 | |
1986 | ld %1,%0 | |
1987 | st %r1,%0 | |
04e1602e DE |
1988 | st %1,%0" |
1989 | [(set_attr "type" "move,fp,move,load,fpload,store,fpstore") | |
1990 | (set_attr "length" "1")]) | |
7a768814 | 1991 | |
c4ce6853 DE |
1992 | (define_insn "*movsi_insn_liveg0" |
1993 | [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q") | |
1994 | (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))] | |
1995 | "TARGET_LIVE_G0 | |
1996 | && (register_operand (operands[0], SImode) | |
1997 | || register_operand (operands[1], SImode))" | |
1998 | "@ | |
1999 | mov %1,%0 | |
2000 | and %0,0,%0 | |
2001 | and %0,0,%0\;or %0,%1,%0 | |
2002 | fmovs %1,%0 | |
2003 | sethi %%hi(%a1),%0 | |
2004 | ld %1,%0 | |
2005 | ld %1,%0 | |
2006 | st %1,%0 | |
2007 | st %1,%0" | |
2008 | [(set_attr "type" "move,move,move,fp,move,load,fpload,store,fpstore") | |
2009 | (set_attr "length" "1,1,2,1,1,1,1,1,1")]) | |
2010 | ||
c8b3b7d6 | 2011 | (define_insn "*store_si" |
7a768814 RS |
2012 | [(set (mem:SI (match_operand:SI 0 "symbolic_operand" "")) |
2013 | (match_operand:SI 1 "reg_or_0_operand" "rJ")) | |
2014 | (clobber (match_scratch:SI 2 "=&r"))] | |
c4ce6853 DE |
2015 | "(reload_completed || reload_in_progress) |
2016 | && ! TARGET_PTR64" | |
7a768814 RS |
2017 | "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" |
2018 | [(set_attr "type" "store") | |
2019 | (set_attr "length" "2")]) | |
2020 | ||
6a4bb1fa DE |
2021 | (define_expand "movdi" |
2022 | [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") | |
2023 | (match_operand:DI 1 "general_operand" ""))] | |
7a768814 RS |
2024 | "" |
2025 | " | |
2026 | { | |
6a4bb1fa | 2027 | if (emit_move_sequence (operands, DImode)) |
7a768814 RS |
2028 | DONE; |
2029 | }") | |
2030 | ||
c8b3b7d6 | 2031 | (define_insn "*movdi_sp32_insn" |
cb6c1cf1 JW |
2032 | [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q") |
2033 | (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))] | |
fa0f39e4 | 2034 | "! TARGET_ARCH64 |
a8d2b752 DE |
2035 | && (register_operand (operands[0], DImode) |
2036 | || register_operand (operands[1], DImode) | |
2037 | || operands[1] == const0_rtx)" | |
6a4bb1fa | 2038 | "* |
7a768814 | 2039 | { |
6a4bb1fa DE |
2040 | if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) |
2041 | return output_fp_move_double (operands); | |
2042 | return output_move_double (operands); | |
2043 | }" | |
cb6c1cf1 JW |
2044 | [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore") |
2045 | (set_attr "length" "2,1,1,3,3,3,2,3,3")]) | |
7a768814 | 2046 | |
a8d2b752 DE |
2047 | ;;; ??? The trick used below can be extended to load any negative 32 bit |
2048 | ;;; constant in two instructions. Currently the compiler will use HIGH/LO_SUM | |
2049 | ;;; for anything not matching the HIK constraints, which results in 5 | |
2050 | ;;; instructions. Positive 32 bit constants can be loaded in the obvious way | |
2051 | ;;; with sethi/ori. To extend the trick, in the xor instruction, use | |
2052 | ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0 | |
2053 | ;;; This needs the original value of operands[1], not the inverted value. | |
2054 | ||
c8b3b7d6 | 2055 | (define_insn "*movdi_sp64_insn" |
a8d2b752 DE |
2056 | [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q") |
2057 | (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))] | |
fa0f39e4 | 2058 | "TARGET_ARCH64 |
a8d2b752 DE |
2059 | && (register_operand (operands[0], DImode) |
2060 | || register_operand (operands[1], DImode) | |
2061 | || operands[1] == const0_rtx)" | |
6a4bb1fa DE |
2062 | "* |
2063 | { | |
a8d2b752 DE |
2064 | switch (which_alternative) |
2065 | { | |
2066 | case 0: | |
2067 | return \"mov %1,%0\"; | |
2068 | case 1: | |
2069 | /* Sethi does not sign extend, so we must use a little trickery | |
2070 | to use it for negative numbers. Invert the constant before | |
2071 | loading it in, then use a xor immediate to invert the loaded bits | |
2072 | (along with the upper 32 bits) to the desired constant. This | |
2073 | works because the sethi and immediate fields overlap. */ | |
2074 | ||
2075 | if ((INTVAL (operands[1]) & 0x80000000) == 0) | |
2076 | return \"sethi %%hi(%a1),%0\"; | |
2077 | else | |
2078 | { | |
5d4f5e87 | 2079 | operands[1] = GEN_INT (~INTVAL (operands[1])); |
a8d2b752 DE |
2080 | output_asm_insn (\"sethi %%hi(%a1),%0\", operands); |
2081 | /* The low 10 bits are already zero, but invert the rest. | |
2082 | Assemblers don't accept 0x1c00, so use -0x400 instead. */ | |
2083 | return \"xor %0,-0x400,%0\"; | |
2084 | } | |
2085 | case 2: | |
2086 | return \"ldx %1,%0\"; | |
2087 | case 3: | |
2088 | return \"stx %r1,%0\"; | |
2089 | case 4: | |
2090 | return \"mov %1,%0\"; | |
2091 | case 5: | |
2092 | return \"ldd %1,%0\"; | |
2093 | case 6: | |
2094 | return \"std %1,%0\"; | |
2095 | } | |
6a4bb1fa | 2096 | }" |
a8d2b752 DE |
2097 | [(set_attr "type" "move,move,load,store,fp,fpload,fpstore") |
2098 | (set_attr "length" "1,2,1,1,1,1,1")]) | |
7a768814 | 2099 | |
6a4bb1fa | 2100 | ;; ??? There's no symbolic (set (mem:DI ...) ...). |
a8d2b752 | 2101 | ;; Experimentation with v9 suggested one isn't needed. |
6a4bb1fa DE |
2102 | \f |
2103 | ;; Block move insns. | |
7a768814 | 2104 | |
9fe5bce9 JW |
2105 | ;; ??? We get better code without it. See output_block_move in sparc.c. |
2106 | ||
7a768814 RS |
2107 | ;; The definition of this insn does not really explain what it does, |
2108 | ;; but it should suffice | |
2109 | ;; that anything generated as this insn will be recognized as one | |
2110 | ;; and that it will not successfully combine with anything. | |
9fe5bce9 JW |
2111 | ;(define_expand "movstrsi" |
2112 | ; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) | |
2113 | ; (mem:BLK (match_operand:BLK 1 "general_operand" ""))) | |
2114 | ; (use (match_operand:SI 2 "nonmemory_operand" "")) | |
2115 | ; (use (match_operand:SI 3 "immediate_operand" "")) | |
2116 | ; (clobber (match_dup 0)) | |
2117 | ; (clobber (match_dup 1)) | |
2118 | ; (clobber (match_scratch:SI 4 "")) | |
c4ce6853 | 2119 | ; (clobber (reg:SI 100)) |
9fe5bce9 JW |
2120 | ; (clobber (reg:SI 1))])] |
2121 | ; "" | |
2122 | ; " | |
2123 | ;{ | |
2124 | ; /* If the size isn't known, don't emit inline code. output_block_move | |
2125 | ; would output code that's much slower than the library function. | |
2126 | ; Also don't output code for large blocks. */ | |
2127 | ; if (GET_CODE (operands[2]) != CONST_INT | |
2128 | ; || GET_CODE (operands[3]) != CONST_INT | |
2129 | ; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16) | |
2130 | ; FAIL; | |
2131 | ; | |
2132 | ; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); | |
2133 | ; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); | |
2134 | ; operands[2] = force_not_mem (operands[2]); | |
2135 | ;}") | |
2136 | ||
c8b3b7d6 | 2137 | ;(define_insn "*block_move_insn" |
9fe5bce9 JW |
2138 | ; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) |
2139 | ; (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) | |
2140 | ; (use (match_operand:SI 2 "nonmemory_operand" "rn")) | |
2141 | ; (use (match_operand:SI 3 "immediate_operand" "i")) | |
2142 | ; (clobber (match_dup 0)) | |
2143 | ; (clobber (match_dup 1)) | |
2144 | ; (clobber (match_scratch:SI 4 "=&r")) | |
c4ce6853 | 2145 | ; (clobber (reg:SI 100)) |
9fe5bce9 JW |
2146 | ; (clobber (reg:SI 1))] |
2147 | ; "" | |
2148 | ; "* return output_block_move (operands);" | |
2149 | ; [(set_attr "type" "multi") | |
2150 | ; (set_attr "length" "6")]) | |
7a768814 RS |
2151 | \f |
2152 | ;; Floating point move insns | |
2153 | ||
6a4bb1fa | 2154 | ;; This pattern forces (set (reg:SF ...) (const_double ...)) |
795068a4 | 2155 | ;; to be reloaded by putting the constant into memory. |
6a4bb1fa | 2156 | ;; It must come before the more general movsf pattern. |
c8b3b7d6 | 2157 | (define_insn "*movsf_const_insn" |
6a4bb1fa | 2158 | [(set (match_operand:SF 0 "general_operand" "=?r,f,m") |
b27a0c39 | 2159 | (match_operand:SF 1 "" "?F,m,G"))] |
d1f4474e DE |
2160 | "TARGET_FPU |
2161 | && GET_CODE (operands[1]) == CONST_DOUBLE | |
2162 | && (GET_CODE (operands[0]) == REG | |
2163 | || fp_zero_operand (operands[1]))" | |
795068a4 JW |
2164 | "* |
2165 | { | |
2166 | switch (which_alternative) | |
2167 | { | |
2168 | case 0: | |
6a4bb1fa | 2169 | return singlemove_string (operands); |
795068a4 | 2170 | case 1: |
6a4bb1fa | 2171 | return \"ld %1,%0\"; |
795068a4 | 2172 | case 2: |
6a4bb1fa | 2173 | return \"st %%g0,%0\"; |
795068a4 JW |
2174 | } |
2175 | }" | |
2176 | [(set_attr "type" "load,fpload,store") | |
6a4bb1fa | 2177 | (set_attr "length" "2,1,1")]) |
795068a4 | 2178 | |
6a4bb1fa DE |
2179 | (define_expand "movsf" |
2180 | [(set (match_operand:SF 0 "general_operand" "") | |
2181 | (match_operand:SF 1 "general_operand" ""))] | |
795068a4 JW |
2182 | "" |
2183 | " | |
2184 | { | |
6a4bb1fa | 2185 | if (emit_move_sequence (operands, SFmode)) |
795068a4 JW |
2186 | DONE; |
2187 | }") | |
2188 | ||
c8b3b7d6 | 2189 | (define_insn "*movsf_insn" |
6a4bb1fa DE |
2190 | [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q") |
2191 | (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))] | |
ab5519b7 | 2192 | "TARGET_FPU |
6a4bb1fa DE |
2193 | && (register_operand (operands[0], SFmode) |
2194 | || register_operand (operands[1], SFmode))" | |
2195 | "@ | |
2196 | fmovs %1,%0 | |
2197 | mov %1,%0 | |
2198 | ld %1,%0 | |
2199 | ld %1,%0 | |
04e1602e DE |
2200 | st %1,%0 |
2201 | st %1,%0" | |
6a4bb1fa | 2202 | [(set_attr "type" "fp,move,fpload,load,fpstore,store")]) |
795068a4 | 2203 | |
ab5519b7 JW |
2204 | ;; Exactly the same as above, except that all `f' cases are deleted. |
2205 | ;; This is necessary to prevent reload from ever trying to use a `f' reg | |
2206 | ;; when -mno-fpu. | |
2207 | ||
c8b3b7d6 | 2208 | (define_insn "*movsf_no_f_insn" |
6a4bb1fa DE |
2209 | [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") |
2210 | (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))] | |
ab5519b7 | 2211 | "! TARGET_FPU |
6a4bb1fa DE |
2212 | && (register_operand (operands[0], SFmode) |
2213 | || register_operand (operands[1], SFmode))" | |
2214 | "@ | |
2215 | mov %1,%0 | |
2216 | ld %1,%0 | |
04e1602e | 2217 | st %1,%0" |
6a4bb1fa | 2218 | [(set_attr "type" "move,load,store")]) |
ab5519b7 | 2219 | |
c8b3b7d6 | 2220 | (define_insn "*store_sf" |
6a4bb1fa DE |
2221 | [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) |
2222 | (match_operand:SF 1 "reg_or_0_operand" "rfG")) | |
2223 | (clobber (match_scratch:SI 2 "=&r"))] | |
c4ce6853 DE |
2224 | "(reload_completed || reload_in_progress) |
2225 | && ! TARGET_PTR64" | |
6a4bb1fa | 2226 | "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" |
795068a4 | 2227 | [(set_attr "type" "store") |
6a4bb1fa DE |
2228 | (set_attr "length" "2")]) |
2229 | ||
7a768814 RS |
2230 | ;; This pattern forces (set (reg:DF ...) (const_double ...)) |
2231 | ;; to be reloaded by putting the constant into memory. | |
2232 | ;; It must come before the more general movdf pattern. | |
ab5519b7 | 2233 | |
c8b3b7d6 | 2234 | (define_insn "*movdf_const_insn" |
b6d3c4ba | 2235 | [(set (match_operand:DF 0 "general_operand" "=?r,e,o") |
b27a0c39 | 2236 | (match_operand:DF 1 "" "?F,m,G"))] |
d1f4474e DE |
2237 | "TARGET_FPU |
2238 | && GET_CODE (operands[1]) == CONST_DOUBLE | |
2239 | && (GET_CODE (operands[0]) == REG | |
2240 | || fp_zero_operand (operands[1]))" | |
7a768814 RS |
2241 | "* |
2242 | { | |
2243 | switch (which_alternative) | |
2244 | { | |
2245 | case 0: | |
2246 | return output_move_double (operands); | |
2247 | case 1: | |
7a768814 | 2248 | return output_fp_move_double (operands); |
f24ec84c | 2249 | case 2: |
fa0f39e4 | 2250 | if (TARGET_ARCH64) |
a8d2b752 DE |
2251 | { |
2252 | return \"stx %%g0,%0\"; | |
2253 | } | |
2254 | else | |
2255 | { | |
2256 | operands[1] = adj_offsettable_operand (operands[0], 4); | |
2257 | return \"st %%g0,%0\;st %%g0,%1\"; | |
2258 | } | |
7a768814 RS |
2259 | } |
2260 | }" | |
f24ec84c JW |
2261 | [(set_attr "type" "load,fpload,store") |
2262 | (set_attr "length" "3,3,3")]) | |
7a768814 RS |
2263 | |
2264 | (define_expand "movdf" | |
2265 | [(set (match_operand:DF 0 "general_operand" "") | |
2266 | (match_operand:DF 1 "general_operand" ""))] | |
2267 | "" | |
2268 | " | |
2269 | { | |
d0fc7bea | 2270 | if (emit_move_sequence (operands, DFmode)) |
7a768814 RS |
2271 | DONE; |
2272 | }") | |
2273 | ||
c8b3b7d6 | 2274 | (define_insn "*movdf_insn" |
b6d3c4ba JW |
2275 | [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r") |
2276 | (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))] | |
ab5519b7 JW |
2277 | "TARGET_FPU |
2278 | && (register_operand (operands[0], DFmode) | |
2279 | || register_operand (operands[1], DFmode))" | |
7a768814 RS |
2280 | "* |
2281 | { | |
2282 | if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) | |
2283 | return output_fp_move_double (operands); | |
2284 | return output_move_double (operands); | |
2285 | }" | |
8b1d5eb7 JW |
2286 | [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load") |
2287 | (set_attr "length" "1,1,2,2,3,3,3,3")]) | |
7a768814 | 2288 | |
b6d3c4ba JW |
2289 | ;; Exactly the same as above, except that all `e' cases are deleted. |
2290 | ;; This is necessary to prevent reload from ever trying to use a `e' reg | |
ab5519b7 JW |
2291 | ;; when -mno-fpu. |
2292 | ||
c8b3b7d6 | 2293 | (define_insn "*movdf_no_e_insn" |
ab5519b7 JW |
2294 | [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r") |
2295 | (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))] | |
2296 | "! TARGET_FPU | |
2297 | && (register_operand (operands[0], DFmode) | |
2298 | || register_operand (operands[1], DFmode))" | |
114b9aa4 JW |
2299 | "* return output_move_double (operands);" |
2300 | [(set_attr "type" "store,load,move,store,load") | |
ab5519b7 JW |
2301 | (set_attr "length" "1,1,2,3,3")]) |
2302 | ||
63f7136f JW |
2303 | ;; Must handle overlapping registers here, since parameters can be unaligned |
2304 | ;; in registers. | |
9ad2334b | 2305 | |
ae0cab49 JW |
2306 | (define_split |
2307 | [(set (match_operand:DF 0 "register_operand" "") | |
2308 | (match_operand:DF 1 "register_operand" ""))] | |
9ad2334b DE |
2309 | "! TARGET_ARCH64 && reload_completed |
2310 | && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG | |
2311 | && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG" | |
ae0cab49 JW |
2312 | [(set (match_dup 2) (match_dup 3)) |
2313 | (set (match_dup 4) (match_dup 5))] | |
2314 | " | |
63f7136f JW |
2315 | { |
2316 | rtx first_set = operand_subword (operands[0], 0, 0, DFmode); | |
2317 | rtx second_use = operand_subword (operands[1], 1, 0, DFmode); | |
2318 | ||
2319 | if (REGNO (first_set) == REGNO (second_use)) | |
2320 | { | |
2321 | operands[2] = operand_subword (operands[0], 1, 0, DFmode); | |
2322 | operands[3] = second_use; | |
2323 | operands[4] = first_set; | |
2324 | operands[5] = operand_subword (operands[1], 0, 0, DFmode); | |
2325 | } | |
2326 | else | |
2327 | { | |
2328 | operands[2] = first_set; | |
2329 | operands[3] = operand_subword (operands[1], 0, 0, DFmode); | |
2330 | operands[4] = operand_subword (operands[0], 1, 0, DFmode); | |
2331 | operands[5] = second_use; | |
2332 | } | |
2333 | }") | |
ae0cab49 | 2334 | |
c8b3b7d6 | 2335 | (define_insn "*store_df" |
7a768814 | 2336 | [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i")) |
b6d3c4ba | 2337 | (match_operand:DF 1 "reg_or_0_operand" "re,G")) |
7a768814 | 2338 | (clobber (match_scratch:SI 2 "=&r,&r"))] |
c4ce6853 DE |
2339 | "(reload_completed || reload_in_progress) |
2340 | && ! TARGET_PTR64" | |
7a768814 RS |
2341 | "* |
2342 | { | |
2343 | output_asm_insn (\"sethi %%hi(%a0),%2\", operands); | |
2344 | if (which_alternative == 0) | |
2345 | return \"std %1,[%2+%%lo(%a0)]\"; | |
2346 | else | |
2347 | return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\"; | |
2348 | }" | |
2349 | [(set_attr "type" "store") | |
2350 | (set_attr "length" "3")]) | |
7a768814 | 2351 | |
6a4bb1fa | 2352 | ;; This pattern forces (set (reg:TF ...) (const_double ...)) |
2b9a9aea | 2353 | ;; to be reloaded by putting the constant into memory. |
6a4bb1fa | 2354 | ;; It must come before the more general movtf pattern. |
c8b3b7d6 | 2355 | (define_insn "*movtf_const_insn" |
b6d3c4ba | 2356 | [(set (match_operand:TF 0 "general_operand" "=?r,e,o") |
b27a0c39 | 2357 | (match_operand:TF 1 "" "?F,m,G"))] |
d1f4474e DE |
2358 | "TARGET_FPU |
2359 | && GET_CODE (operands[1]) == CONST_DOUBLE | |
2360 | && (GET_CODE (operands[0]) == REG | |
2361 | || fp_zero_operand (operands[1]))" | |
2b9a9aea JW |
2362 | "* |
2363 | { | |
2364 | switch (which_alternative) | |
2365 | { | |
2366 | case 0: | |
6a4bb1fa | 2367 | return output_move_quad (operands); |
2b9a9aea | 2368 | case 1: |
6a4bb1fa | 2369 | return output_fp_move_quad (operands); |
2b9a9aea | 2370 | case 2: |
fa0f39e4 | 2371 | if (TARGET_ARCH64) |
a8d2b752 DE |
2372 | { |
2373 | operands[1] = adj_offsettable_operand (operands[0], 8); | |
2374 | return \"stx %%g0,%0\;stx %%g0,%1\"; | |
2375 | } | |
2376 | else | |
2377 | { | |
2378 | /* ??? Do we run off the end of the array here? */ | |
2379 | operands[1] = adj_offsettable_operand (operands[0], 4); | |
2380 | operands[2] = adj_offsettable_operand (operands[0], 8); | |
2381 | operands[3] = adj_offsettable_operand (operands[0], 12); | |
2382 | return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\"; | |
2383 | } | |
2b9a9aea JW |
2384 | } |
2385 | }" | |
2386 | [(set_attr "type" "load,fpload,store") | |
6a4bb1fa | 2387 | (set_attr "length" "5,5,5")]) |
2b9a9aea | 2388 | |
6a4bb1fa DE |
2389 | (define_expand "movtf" |
2390 | [(set (match_operand:TF 0 "general_operand" "") | |
2391 | (match_operand:TF 1 "general_operand" ""))] | |
7a768814 RS |
2392 | "" |
2393 | " | |
2394 | { | |
6a4bb1fa | 2395 | if (emit_move_sequence (operands, TFmode)) |
7a768814 RS |
2396 | DONE; |
2397 | }") | |
2398 | ||
c8b3b7d6 | 2399 | (define_insn "*movtf_insn" |
b6d3c4ba JW |
2400 | [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r") |
2401 | (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))] | |
ab5519b7 | 2402 | "TARGET_FPU |
6a4bb1fa DE |
2403 | && (register_operand (operands[0], TFmode) |
2404 | || register_operand (operands[1], TFmode))" | |
2405 | "* | |
2406 | { | |
2407 | if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) | |
2408 | return output_fp_move_quad (operands); | |
2409 | return output_move_quad (operands); | |
2410 | }" | |
2411 | [(set_attr "type" "fp,move,fpstore,store,fpload,load") | |
2412 | (set_attr "length" "4,4,5,5,5,5")]) | |
7a768814 | 2413 | |
b6d3c4ba JW |
2414 | ;; Exactly the same as above, except that all `e' cases are deleted. |
2415 | ;; This is necessary to prevent reload from ever trying to use a `e' reg | |
ab5519b7 JW |
2416 | ;; when -mno-fpu. |
2417 | ||
c8b3b7d6 | 2418 | (define_insn "*movtf_no_e_insn" |
6a4bb1fa DE |
2419 | [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r") |
2420 | (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))] | |
ab5519b7 | 2421 | "! TARGET_FPU |
6a4bb1fa DE |
2422 | && (register_operand (operands[0], TFmode) |
2423 | || register_operand (operands[1], TFmode))" | |
2424 | "* | |
2425 | { | |
2426 | if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) | |
2427 | return output_fp_move_quad (operands); | |
2428 | return output_move_quad (operands); | |
2429 | }" | |
2430 | [(set_attr "type" "move,store,load") | |
2431 | (set_attr "length" "4,5,5")]) | |
ab5519b7 | 2432 | |
c2e39c12 JW |
2433 | ;; This is disabled because it does not work. Long doubles have only 8 |
2434 | ;; byte alignment. Adding an offset of 8 or 12 to an 8 byte aligned %lo may | |
2435 | ;; cause it to overflow. See also GO_IF_LEGITIMATE_ADDRESS. | |
c8b3b7d6 | 2436 | (define_insn "*store_tf" |
6a4bb1fa | 2437 | [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i")) |
b6d3c4ba | 2438 | (match_operand:TF 1 "reg_or_0_operand" "re,G")) |
6a4bb1fa | 2439 | (clobber (match_scratch:SI 2 "=&r,&r"))] |
c4ce6853 DE |
2440 | "0 && (reload_completed || reload_in_progress) |
2441 | && ! TARGET_PTR64" | |
6a4bb1fa DE |
2442 | "* |
2443 | { | |
2444 | output_asm_insn (\"sethi %%hi(%a0),%2\", operands); | |
2445 | if (which_alternative == 0) | |
2446 | return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; | |
2447 | else | |
2448 | return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\"; | |
2449 | }" | |
7a768814 | 2450 | [(set_attr "type" "store") |
6a4bb1fa | 2451 | (set_attr "length" "5")]) |
7a768814 | 2452 | \f |
a8d2b752 DE |
2453 | ;; Sparc V9 conditional move instructions. |
2454 | ||
57b7e1bf DE |
2455 | ;; We can handle larger constants here for some flavors, but for now we keep |
2456 | ;; it simple and only allow those constants supported by all flavours. | |
304b7a23 DE |
2457 | ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand |
2458 | ;; 3 contains the constant if one is present, but we handle either for | |
2459 | ;; generality (sparc.c puts a constant in operand 2). | |
2460 | ||
2461 | (define_expand "movqicc" | |
2462 | [(set (match_operand:QI 0 "register_operand" "") | |
2463 | (if_then_else:QI (match_operand 1 "comparison_operator" "") | |
2464 | (match_operand:QI 2 "arith10_operand" "") | |
2465 | (match_operand:QI 3 "arith10_operand" "")))] | |
2466 | "TARGET_V9" | |
2467 | " | |
2468 | { | |
2469 | enum rtx_code code = GET_CODE (operands[1]); | |
2470 | ||
2471 | if (GET_MODE (sparc_compare_op0) == DImode | |
2472 | && ! TARGET_ARCH64) | |
2473 | FAIL; | |
2474 | ||
2475 | if (sparc_compare_op1 == const0_rtx | |
2476 | && GET_CODE (sparc_compare_op0) == REG | |
2477 | && GET_MODE (sparc_compare_op0) == DImode | |
2478 | && v9_regcmp_p (code)) | |
2479 | { | |
2480 | operands[1] = gen_rtx (code, DImode, | |
2481 | sparc_compare_op0, sparc_compare_op1); | |
2482 | } | |
2483 | else | |
2484 | { | |
2485 | rtx cc_reg = gen_compare_reg (code, | |
2486 | sparc_compare_op0, sparc_compare_op1); | |
2487 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2488 | } | |
2489 | }") | |
2490 | ||
2491 | (define_expand "movhicc" | |
2492 | [(set (match_operand:HI 0 "register_operand" "") | |
2493 | (if_then_else:HI (match_operand 1 "comparison_operator" "") | |
2494 | (match_operand:HI 2 "arith10_operand" "") | |
2495 | (match_operand:HI 3 "arith10_operand" "")))] | |
2496 | "TARGET_V9" | |
2497 | " | |
2498 | { | |
2499 | enum rtx_code code = GET_CODE (operands[1]); | |
2500 | ||
2501 | if (GET_MODE (sparc_compare_op0) == DImode | |
2502 | && ! TARGET_ARCH64) | |
2503 | FAIL; | |
2504 | ||
2505 | if (sparc_compare_op1 == const0_rtx | |
2506 | && GET_CODE (sparc_compare_op0) == REG | |
2507 | && GET_MODE (sparc_compare_op0) == DImode | |
2508 | && v9_regcmp_p (code)) | |
2509 | { | |
2510 | operands[1] = gen_rtx (code, DImode, | |
2511 | sparc_compare_op0, sparc_compare_op1); | |
2512 | } | |
2513 | else | |
2514 | { | |
2515 | rtx cc_reg = gen_compare_reg (code, | |
2516 | sparc_compare_op0, sparc_compare_op1); | |
2517 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2518 | } | |
2519 | }") | |
cd5fb1ee DE |
2520 | |
2521 | (define_expand "movsicc" | |
2522 | [(set (match_operand:SI 0 "register_operand" "") | |
304b7a23 DE |
2523 | (if_then_else:SI (match_operand 1 "comparison_operator" "") |
2524 | (match_operand:SI 2 "arith10_operand" "") | |
2525 | (match_operand:SI 3 "arith10_operand" "")))] | |
2526 | "TARGET_V9" | |
cd5fb1ee DE |
2527 | " |
2528 | { | |
2529 | enum rtx_code code = GET_CODE (operands[1]); | |
2530 | ||
304b7a23 DE |
2531 | if (GET_MODE (sparc_compare_op0) == DImode |
2532 | && ! TARGET_ARCH64) | |
2533 | FAIL; | |
2534 | ||
cd5fb1ee DE |
2535 | if (sparc_compare_op1 == const0_rtx |
2536 | && GET_CODE (sparc_compare_op0) == REG | |
2537 | && GET_MODE (sparc_compare_op0) == DImode | |
2538 | && v9_regcmp_p (code)) | |
2539 | { | |
2540 | operands[1] = gen_rtx (code, DImode, | |
2541 | sparc_compare_op0, sparc_compare_op1); | |
2542 | } | |
2543 | else | |
2544 | { | |
2545 | rtx cc_reg = gen_compare_reg (code, | |
2546 | sparc_compare_op0, sparc_compare_op1); | |
2547 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2548 | } | |
2549 | }") | |
2550 | ||
2551 | (define_expand "movdicc" | |
2552 | [(set (match_operand:DI 0 "register_operand" "") | |
304b7a23 DE |
2553 | (if_then_else:DI (match_operand 1 "comparison_operator" "") |
2554 | (match_operand:DI 2 "arith10_double_operand" "") | |
2555 | (match_operand:DI 3 "arith10_double_operand" "")))] | |
fa0f39e4 | 2556 | "TARGET_ARCH64" |
cd5fb1ee DE |
2557 | " |
2558 | { | |
2559 | enum rtx_code code = GET_CODE (operands[1]); | |
2560 | ||
2561 | if (sparc_compare_op1 == const0_rtx | |
2562 | && GET_CODE (sparc_compare_op0) == REG | |
2563 | && GET_MODE (sparc_compare_op0) == DImode | |
2564 | && v9_regcmp_p (code)) | |
2565 | { | |
2566 | operands[1] = gen_rtx (code, DImode, | |
2567 | sparc_compare_op0, sparc_compare_op1); | |
2568 | } | |
2569 | else | |
2570 | { | |
2571 | rtx cc_reg = gen_compare_reg (code, | |
2572 | sparc_compare_op0, sparc_compare_op1); | |
2573 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2574 | } | |
2575 | }") | |
2576 | ||
2577 | (define_expand "movsfcc" | |
2578 | [(set (match_operand:SF 0 "register_operand" "") | |
304b7a23 DE |
2579 | (if_then_else:SF (match_operand 1 "comparison_operator" "") |
2580 | (match_operand:SF 2 "register_operand" "") | |
2581 | (match_operand:SF 3 "register_operand" "")))] | |
2582 | "TARGET_V9 && TARGET_FPU" | |
cd5fb1ee DE |
2583 | " |
2584 | { | |
2585 | enum rtx_code code = GET_CODE (operands[1]); | |
2586 | ||
304b7a23 DE |
2587 | if (GET_MODE (sparc_compare_op0) == DImode |
2588 | && ! TARGET_ARCH64) | |
2589 | FAIL; | |
2590 | ||
cd5fb1ee DE |
2591 | if (sparc_compare_op1 == const0_rtx |
2592 | && GET_CODE (sparc_compare_op0) == REG | |
2593 | && GET_MODE (sparc_compare_op0) == DImode | |
2594 | && v9_regcmp_p (code)) | |
2595 | { | |
2596 | operands[1] = gen_rtx (code, DImode, | |
2597 | sparc_compare_op0, sparc_compare_op1); | |
2598 | } | |
2599 | else | |
2600 | { | |
2601 | rtx cc_reg = gen_compare_reg (code, | |
2602 | sparc_compare_op0, sparc_compare_op1); | |
2603 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2604 | } | |
2605 | }") | |
2606 | ||
2607 | (define_expand "movdfcc" | |
2608 | [(set (match_operand:DF 0 "register_operand" "") | |
304b7a23 DE |
2609 | (if_then_else:DF (match_operand 1 "comparison_operator" "") |
2610 | (match_operand:DF 2 "register_operand" "") | |
2611 | (match_operand:DF 3 "register_operand" "")))] | |
2612 | "TARGET_V9 && TARGET_FPU" | |
cd5fb1ee DE |
2613 | " |
2614 | { | |
2615 | enum rtx_code code = GET_CODE (operands[1]); | |
2616 | ||
304b7a23 DE |
2617 | if (GET_MODE (sparc_compare_op0) == DImode |
2618 | && ! TARGET_ARCH64) | |
2619 | FAIL; | |
2620 | ||
cd5fb1ee DE |
2621 | if (sparc_compare_op1 == const0_rtx |
2622 | && GET_CODE (sparc_compare_op0) == REG | |
2623 | && GET_MODE (sparc_compare_op0) == DImode | |
2624 | && v9_regcmp_p (code)) | |
2625 | { | |
2626 | operands[1] = gen_rtx (code, DImode, | |
2627 | sparc_compare_op0, sparc_compare_op1); | |
2628 | } | |
2629 | else | |
2630 | { | |
2631 | rtx cc_reg = gen_compare_reg (code, | |
2632 | sparc_compare_op0, sparc_compare_op1); | |
2633 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2634 | } | |
2635 | }") | |
2636 | ||
2637 | (define_expand "movtfcc" | |
2638 | [(set (match_operand:TF 0 "register_operand" "") | |
304b7a23 DE |
2639 | (if_then_else:TF (match_operand 1 "comparison_operator" "") |
2640 | (match_operand:TF 2 "register_operand" "") | |
2641 | (match_operand:TF 3 "register_operand" "")))] | |
2642 | "TARGET_V9 && TARGET_FPU" | |
cd5fb1ee DE |
2643 | " |
2644 | { | |
2645 | enum rtx_code code = GET_CODE (operands[1]); | |
2646 | ||
304b7a23 DE |
2647 | if (GET_MODE (sparc_compare_op0) == DImode |
2648 | && ! TARGET_ARCH64) | |
2649 | FAIL; | |
2650 | ||
cd5fb1ee DE |
2651 | if (sparc_compare_op1 == const0_rtx |
2652 | && GET_CODE (sparc_compare_op0) == REG | |
2653 | && GET_MODE (sparc_compare_op0) == DImode | |
2654 | && v9_regcmp_p (code)) | |
2655 | { | |
2656 | operands[1] = gen_rtx (code, DImode, | |
2657 | sparc_compare_op0, sparc_compare_op1); | |
2658 | } | |
2659 | else | |
2660 | { | |
2661 | rtx cc_reg = gen_compare_reg (code, | |
2662 | sparc_compare_op0, sparc_compare_op1); | |
2663 | operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx); | |
2664 | } | |
2665 | }") | |
2666 | ||
304b7a23 | 2667 | ;; Conditional move define_insns. |
b1e74255 | 2668 | |
304b7a23 DE |
2669 | (define_insn "*movqi_cc_sp64" |
2670 | [(set (match_operand:QI 0 "register_operand" "=r,r") | |
2671 | (if_then_else:QI (match_operator 1 "comparison_operator" | |
2672 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
2673 | (const_int 0)]) | |
57b7e1bf DE |
2674 | (match_operand:QI 3 "arith11_operand" "rL,0") |
2675 | (match_operand:QI 4 "arith11_operand" "0,rL")))] | |
a8d2b752 | 2676 | "TARGET_V9" |
304b7a23 DE |
2677 | "@ |
2678 | mov%C1 %x2,%3,%0 | |
2679 | mov%c1 %x2,%4,%0" | |
a8d2b752 DE |
2680 | [(set_attr "type" "cmove")]) |
2681 | ||
304b7a23 DE |
2682 | (define_insn "*movhi_cc_sp64" |
2683 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
2684 | (if_then_else:HI (match_operator 1 "comparison_operator" | |
2685 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
2686 | (const_int 0)]) | |
57b7e1bf DE |
2687 | (match_operand:HI 3 "arith11_operand" "rL,0") |
2688 | (match_operand:HI 4 "arith11_operand" "0,rL")))] | |
304b7a23 DE |
2689 | "TARGET_V9" |
2690 | "@ | |
2691 | mov%C1 %x2,%3,%0 | |
2692 | mov%c1 %x2,%4,%0" | |
a8d2b752 DE |
2693 | [(set_attr "type" "cmove")]) |
2694 | ||
304b7a23 DE |
2695 | (define_insn "*movsi_cc_sp64" |
2696 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2697 | (if_then_else:SI (match_operator 1 "comparison_operator" | |
2698 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
2699 | (const_int 0)]) | |
57b7e1bf DE |
2700 | (match_operand:SI 3 "arith11_operand" "rL,0") |
2701 | (match_operand:SI 4 "arith11_operand" "0,rL")))] | |
304b7a23 DE |
2702 | "TARGET_V9" |
2703 | "@ | |
2704 | mov%C1 %x2,%3,%0 | |
2705 | mov%c1 %x2,%4,%0" | |
a8d2b752 DE |
2706 | [(set_attr "type" "cmove")]) |
2707 | ||
57b7e1bf | 2708 | ;; ??? The constraints of operands 3,4 need work. |
304b7a23 DE |
2709 | (define_insn "*movdi_cc_sp64" |
2710 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
2711 | (if_then_else:DI (match_operator 1 "comparison_operator" | |
2712 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
2713 | (const_int 0)]) | |
57b7e1bf DE |
2714 | (match_operand:DI 3 "arith11_double_operand" "rLH,0") |
2715 | (match_operand:DI 4 "arith11_double_operand" "0,rLH")))] | |
fa0f39e4 | 2716 | "TARGET_ARCH64" |
304b7a23 DE |
2717 | "@ |
2718 | mov%C1 %x2,%3,%0 | |
2719 | mov%c1 %x2,%4,%0" | |
a8d2b752 DE |
2720 | [(set_attr "type" "cmove")]) |
2721 | ||
304b7a23 DE |
2722 | (define_insn "*movsf_cc_sp64" |
2723 | [(set (match_operand:SF 0 "register_operand" "=f,f") | |
2724 | (if_then_else:SF (match_operator 1 "comparison_operator" | |
2725 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
a8d2b752 | 2726 | (const_int 0)]) |
304b7a23 DE |
2727 | (match_operand:SF 3 "register_operand" "f,0") |
2728 | (match_operand:SF 4 "register_operand" "0,f")))] | |
2729 | "TARGET_V9 && TARGET_FPU" | |
2730 | "@ | |
2731 | fmovs%C1 %x2,%3,%0 | |
2732 | fmovs%c1 %x2,%4,%0" | |
a8d2b752 DE |
2733 | [(set_attr "type" "cmove")]) |
2734 | ||
304b7a23 DE |
2735 | (define_insn "*movdf_cc_sp64" |
2736 | [(set (match_operand:DF 0 "register_operand" "=e,e") | |
2737 | (if_then_else:DF (match_operator 1 "comparison_operator" | |
2738 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
a8d2b752 | 2739 | (const_int 0)]) |
304b7a23 DE |
2740 | (match_operand:DF 3 "register_operand" "e,0") |
2741 | (match_operand:DF 4 "register_operand" "0,e")))] | |
2742 | "TARGET_V9 && TARGET_FPU" | |
2743 | "@ | |
2744 | fmovd%C1 %x2,%3,%0 | |
2745 | fmovd%c1 %x2,%4,%0" | |
a8d2b752 DE |
2746 | [(set_attr "type" "cmove")]) |
2747 | ||
304b7a23 DE |
2748 | (define_insn "*movtf_cc_sp64" |
2749 | [(set (match_operand:TF 0 "register_operand" "=e,e") | |
2750 | (if_then_else:TF (match_operator 1 "comparison_operator" | |
2751 | [(match_operand 2 "icc_or_fcc_reg_operand" "X,X") | |
a8d2b752 | 2752 | (const_int 0)]) |
304b7a23 DE |
2753 | (match_operand:TF 3 "register_operand" "e,0") |
2754 | (match_operand:TF 4 "register_operand" "0,e")))] | |
5d4f5e87 | 2755 | "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" |
304b7a23 DE |
2756 | "@ |
2757 | fmovq%C1 %x2,%3,%0 | |
2758 | fmovq%c1 %x2,%4,%0" | |
2759 | [(set_attr "type" "cmove")]) | |
2760 | ||
2761 | (define_insn "*movqi_cc_reg_sp64" | |
2762 | [(set (match_operand:QI 0 "register_operand" "=r,r") | |
2763 | (if_then_else:QI (match_operator 1 "v9_regcmp_op" | |
2764 | [(match_operand:DI 2 "register_operand" "r,r") | |
2765 | (const_int 0)]) | |
57b7e1bf DE |
2766 | (match_operand:QI 3 "arith10_operand" "rM,0") |
2767 | (match_operand:QI 4 "arith10_operand" "0,rM")))] | |
fa0f39e4 | 2768 | "TARGET_ARCH64" |
304b7a23 DE |
2769 | "@ |
2770 | movr%D1 %2,%r3,%0 | |
2771 | movr%d1 %2,%r4,%0" | |
a8d2b752 DE |
2772 | [(set_attr "type" "cmove")]) |
2773 | ||
304b7a23 DE |
2774 | (define_insn "*movhi_cc_reg_sp64" |
2775 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
2776 | (if_then_else:HI (match_operator 1 "v9_regcmp_op" | |
2777 | [(match_operand:DI 2 "register_operand" "r,r") | |
a8d2b752 | 2778 | (const_int 0)]) |
57b7e1bf DE |
2779 | (match_operand:HI 3 "arith10_operand" "rM,0") |
2780 | (match_operand:HI 4 "arith10_operand" "0,rM")))] | |
fa0f39e4 | 2781 | "TARGET_ARCH64" |
304b7a23 DE |
2782 | "@ |
2783 | movr%D1 %2,%r3,%0 | |
2784 | movr%d1 %2,%r4,%0" | |
a8d2b752 DE |
2785 | [(set_attr "type" "cmove")]) |
2786 | ||
c8b3b7d6 | 2787 | (define_insn "*movsi_cc_reg_sp64" |
304b7a23 DE |
2788 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
2789 | (if_then_else:SI (match_operator 1 "v9_regcmp_op" | |
2790 | [(match_operand:DI 2 "register_operand" "r,r") | |
a8d2b752 | 2791 | (const_int 0)]) |
57b7e1bf DE |
2792 | (match_operand:SI 3 "arith10_operand" "rM,0") |
2793 | (match_operand:SI 4 "arith10_operand" "0,rM")))] | |
fa0f39e4 | 2794 | "TARGET_ARCH64" |
304b7a23 DE |
2795 | "@ |
2796 | movr%D1 %2,%r3,%0 | |
2797 | movr%d1 %2,%r4,%0" | |
a8d2b752 DE |
2798 | [(set_attr "type" "cmove")]) |
2799 | ||
57b7e1bf | 2800 | ;; ??? The constraints of operands 3,4 need work. |
c8b3b7d6 | 2801 | (define_insn "*movdi_cc_reg_sp64" |
304b7a23 DE |
2802 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
2803 | (if_then_else:DI (match_operator 1 "v9_regcmp_op" | |
2804 | [(match_operand:DI 2 "register_operand" "r,r") | |
a8d2b752 | 2805 | (const_int 0)]) |
57b7e1bf DE |
2806 | (match_operand:DI 3 "arith10_double_operand" "rMH,0") |
2807 | (match_operand:DI 4 "arith10_double_operand" "0,rMH")))] | |
fa0f39e4 | 2808 | "TARGET_ARCH64" |
304b7a23 DE |
2809 | "@ |
2810 | movr%D1 %2,%r3,%0 | |
2811 | movr%d1 %2,%r4,%0" | |
a8d2b752 DE |
2812 | [(set_attr "type" "cmove")]) |
2813 | ||
c8b3b7d6 | 2814 | (define_insn "*movsf_cc_reg_sp64" |
304b7a23 DE |
2815 | [(set (match_operand:SF 0 "register_operand" "=f,f") |
2816 | (if_then_else:SF (match_operator 1 "v9_regcmp_op" | |
2817 | [(match_operand:DI 2 "register_operand" "r,r") | |
a8d2b752 | 2818 | (const_int 0)]) |
304b7a23 DE |
2819 | (match_operand:SF 3 "register_operand" "f,0") |
2820 | (match_operand:SF 4 "register_operand" "0,f")))] | |
fa0f39e4 | 2821 | "TARGET_ARCH64 && TARGET_FPU" |
304b7a23 DE |
2822 | "@ |
2823 | fmovrs%D1 %2,%3,%0 | |
2824 | fmovrs%d1 %2,%4,%0" | |
a8d2b752 DE |
2825 | [(set_attr "type" "cmove")]) |
2826 | ||
c8b3b7d6 | 2827 | (define_insn "*movdf_cc_reg_sp64" |
304b7a23 DE |
2828 | [(set (match_operand:DF 0 "register_operand" "=e,e") |
2829 | (if_then_else:DF (match_operator 1 "v9_regcmp_op" | |
2830 | [(match_operand:DI 2 "register_operand" "r,r") | |
a8d2b752 | 2831 | (const_int 0)]) |
304b7a23 DE |
2832 | (match_operand:DF 3 "register_operand" "e,0") |
2833 | (match_operand:DF 4 "register_operand" "0,e")))] | |
fa0f39e4 | 2834 | "TARGET_ARCH64 && TARGET_FPU" |
304b7a23 DE |
2835 | "@ |
2836 | fmovrd%D1 %2,%3,%0 | |
2837 | fmovrd%d1 %2,%4,%0" | |
a8d2b752 DE |
2838 | [(set_attr "type" "cmove")]) |
2839 | ||
c8b3b7d6 | 2840 | (define_insn "*movtf_cc_reg_sp64" |
304b7a23 DE |
2841 | [(set (match_operand:TF 0 "register_operand" "=e,e") |
2842 | (if_then_else:TF (match_operator 1 "v9_regcmp_op" | |
2843 | [(match_operand:DI 2 "register_operand" "r,r") | |
a8d2b752 | 2844 | (const_int 0)]) |
304b7a23 DE |
2845 | (match_operand:TF 3 "register_operand" "e,0") |
2846 | (match_operand:TF 4 "register_operand" "0,e")))] | |
fa0f39e4 | 2847 | "TARGET_ARCH64 && TARGET_FPU" |
304b7a23 DE |
2848 | "@ |
2849 | fmovrq%D1 %2,%3,%0 | |
2850 | fmovrq%d1 %2,%4,%0" | |
a8d2b752 DE |
2851 | [(set_attr "type" "cmove")]) |
2852 | \f | |
7a768814 RS |
2853 | ;;- zero extension instructions |
2854 | ||
2855 | ;; These patterns originally accepted general_operands, however, slightly | |
2856 | ;; better code is generated by only accepting register_operands, and then | |
2857 | ;; letting combine generate the ldu[hb] insns. | |
2858 | ||
2859 | (define_expand "zero_extendhisi2" | |
2860 | [(set (match_operand:SI 0 "register_operand" "") | |
2861 | (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
2862 | "" | |
2863 | " | |
2864 | { | |
2865 | rtx temp = gen_reg_rtx (SImode); | |
5d4f5e87 | 2866 | rtx shift_16 = GEN_INT (16); |
053e4cac | 2867 | int op1_subword = 0; |
7a768814 RS |
2868 | |
2869 | if (GET_CODE (operand1) == SUBREG) | |
053e4cac JW |
2870 | { |
2871 | op1_subword = SUBREG_WORD (operand1); | |
2872 | operand1 = XEXP (operand1, 0); | |
2873 | } | |
7a768814 | 2874 | |
053e4cac JW |
2875 | emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, |
2876 | op1_subword), | |
7a768814 RS |
2877 | shift_16)); |
2878 | emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); | |
2879 | DONE; | |
2880 | }") | |
2881 | ||
c8b3b7d6 | 2882 | (define_insn "*zero_extendhisi2_insn" |
7a768814 RS |
2883 | [(set (match_operand:SI 0 "register_operand" "=r") |
2884 | (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | |
2885 | "" | |
2886 | "lduh %1,%0" | |
2887 | [(set_attr "type" "load")]) | |
2888 | ||
2889 | (define_expand "zero_extendqihi2" | |
2890 | [(set (match_operand:HI 0 "register_operand" "") | |
2891 | (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] | |
2892 | "" | |
2893 | "") | |
2894 | ||
c8b3b7d6 | 2895 | (define_insn "*zero_extendqihi2_insn" |
b67bfdf7 JW |
2896 | [(set (match_operand:HI 0 "register_operand" "=r,r") |
2897 | (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))] | |
7a768814 RS |
2898 | "GET_CODE (operands[1]) != CONST_INT" |
2899 | "@ | |
b67bfdf7 | 2900 | and %1,0xff,%0 |
7a768814 | 2901 | ldub %1,%0" |
b67bfdf7 | 2902 | [(set_attr "type" "unary,load") |
7a768814 RS |
2903 | (set_attr "length" "1")]) |
2904 | ||
2905 | (define_expand "zero_extendqisi2" | |
2906 | [(set (match_operand:SI 0 "register_operand" "") | |
2907 | (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] | |
2908 | "" | |
2909 | "") | |
2910 | ||
c8b3b7d6 | 2911 | (define_insn "*zero_extendqisi2_insn" |
b67bfdf7 JW |
2912 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
2913 | (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))] | |
7a768814 RS |
2914 | "GET_CODE (operands[1]) != CONST_INT" |
2915 | "@ | |
2916 | and %1,0xff,%0 | |
7a768814 | 2917 | ldub %1,%0" |
b67bfdf7 | 2918 | [(set_attr "type" "unary,load") |
7a768814 RS |
2919 | (set_attr "length" "1")]) |
2920 | ||
a8d2b752 DE |
2921 | (define_expand "zero_extendqidi2" |
2922 | [(set (match_operand:DI 0 "register_operand" "") | |
2923 | (zero_extend:DI (match_operand:QI 1 "register_operand" "")))] | |
fa0f39e4 | 2924 | "TARGET_ARCH64" |
a8d2b752 DE |
2925 | "") |
2926 | ||
c8b3b7d6 | 2927 | (define_insn "*zero_extendqidi2_insn" |
a8d2b752 DE |
2928 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
2929 | (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))] | |
fa0f39e4 | 2930 | "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT" |
a8d2b752 DE |
2931 | "@ |
2932 | and %1,0xff,%0 | |
2933 | ldub %1,%0" | |
2934 | [(set_attr "type" "unary,load") | |
2935 | (set_attr "length" "1")]) | |
2936 | ||
2937 | (define_expand "zero_extendhidi2" | |
2938 | [(set (match_operand:DI 0 "register_operand" "") | |
2939 | (zero_extend:DI (match_operand:HI 1 "register_operand" "")))] | |
fa0f39e4 | 2940 | "TARGET_ARCH64" |
a8d2b752 DE |
2941 | " |
2942 | { | |
2943 | rtx temp = gen_reg_rtx (DImode); | |
5d4f5e87 | 2944 | rtx shift_48 = GEN_INT (48); |
a8d2b752 DE |
2945 | int op1_subword = 0; |
2946 | ||
2947 | if (GET_CODE (operand1) == SUBREG) | |
2948 | { | |
2949 | op1_subword = SUBREG_WORD (operand1); | |
2950 | operand1 = XEXP (operand1, 0); | |
2951 | } | |
2952 | ||
2953 | emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1, | |
2954 | op1_subword), | |
2955 | shift_48)); | |
2956 | emit_insn (gen_lshrdi3 (operand0, temp, shift_48)); | |
2957 | DONE; | |
2958 | }") | |
2959 | ||
c8b3b7d6 | 2960 | (define_insn "*zero_extendhidi2_insn" |
a8d2b752 DE |
2961 | [(set (match_operand:DI 0 "register_operand" "=r") |
2962 | (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))] | |
fa0f39e4 | 2963 | "TARGET_ARCH64" |
a8d2b752 DE |
2964 | "lduh %1,%0" |
2965 | [(set_attr "type" "load")]) | |
2966 | ||
2967 | ;; ??? Write truncdisi pattern using sra? | |
2968 | ||
2969 | (define_expand "zero_extendsidi2" | |
2970 | [(set (match_operand:DI 0 "register_operand" "") | |
2971 | (zero_extend:DI (match_operand:SI 1 "register_operand" "")))] | |
fa0f39e4 | 2972 | "TARGET_ARCH64" |
a8d2b752 DE |
2973 | "") |
2974 | ||
c8b3b7d6 | 2975 | (define_insn "*zero_extendsidi2_insn" |
a8d2b752 DE |
2976 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
2977 | (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))] | |
fa0f39e4 | 2978 | "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT" |
a8d2b752 DE |
2979 | "@ |
2980 | srl %1,0,%0 | |
2981 | lduw %1,%0" | |
2982 | [(set_attr "type" "unary,load") | |
2983 | (set_attr "length" "1")]) | |
2984 | ||
2985 | ;; Simplify comparisons of extended values. | |
2986 | ||
c8b3b7d6 | 2987 | (define_insn "*cmp_zero_extendqisi2" |
c4ce6853 | 2988 | [(set (reg:CC 100) |
7a768814 RS |
2989 | (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r")) |
2990 | (const_int 0)))] | |
2991 | "" | |
2992 | "andcc %0,0xff,%%g0" | |
2993 | [(set_attr "type" "compare")]) | |
2994 | ||
c8b3b7d6 | 2995 | (define_insn "*cmp_zero_extendqisi2_set" |
c4ce6853 | 2996 | [(set (reg:CC 100) |
7a768814 RS |
2997 | (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) |
2998 | (const_int 0))) | |
2999 | (set (match_operand:SI 0 "register_operand" "=r") | |
3000 | (zero_extend:SI (match_dup 1)))] | |
3001 | "" | |
3002 | "andcc %1,0xff,%0" | |
3003 | [(set_attr "type" "unary")]) | |
d21a353d JW |
3004 | |
3005 | ;; Similarly, handle SI->QI mode truncation followed by a compare. | |
3006 | ||
c8b3b7d6 | 3007 | (define_insn "*cmp_siqi_trunc" |
c4ce6853 | 3008 | [(set (reg:CC 100) |
d21a353d JW |
3009 | (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0) |
3010 | (const_int 0)))] | |
3011 | "" | |
3012 | "andcc %0,0xff,%%g0" | |
3013 | [(set_attr "type" "compare")]) | |
3014 | ||
c8b3b7d6 | 3015 | (define_insn "*cmp_siqi_trunc_set" |
c4ce6853 | 3016 | [(set (reg:CC 100) |
d21a353d JW |
3017 | (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0) |
3018 | (const_int 0))) | |
3019 | (set (match_operand:QI 0 "register_operand" "=r") | |
3020 | (match_dup 1))] | |
3021 | "" | |
3022 | "andcc %1,0xff,%0" | |
3023 | [(set_attr "type" "unary")]) | |
7a768814 RS |
3024 | \f |
3025 | ;;- sign extension instructions | |
3026 | ||
3027 | ;; These patterns originally accepted general_operands, however, slightly | |
3028 | ;; better code is generated by only accepting register_operands, and then | |
3029 | ;; letting combine generate the lds[hb] insns. | |
3030 | ||
3031 | (define_expand "extendhisi2" | |
3032 | [(set (match_operand:SI 0 "register_operand" "") | |
3033 | (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
3034 | "" | |
3035 | " | |
3036 | { | |
3037 | rtx temp = gen_reg_rtx (SImode); | |
5d4f5e87 | 3038 | rtx shift_16 = GEN_INT (16); |
053e4cac | 3039 | int op1_subword = 0; |
7a768814 RS |
3040 | |
3041 | if (GET_CODE (operand1) == SUBREG) | |
053e4cac JW |
3042 | { |
3043 | op1_subword = SUBREG_WORD (operand1); | |
3044 | operand1 = XEXP (operand1, 0); | |
3045 | } | |
7a768814 | 3046 | |
053e4cac JW |
3047 | emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, |
3048 | op1_subword), | |
7a768814 RS |
3049 | shift_16)); |
3050 | emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); | |
3051 | DONE; | |
3052 | }") | |
3053 | ||
c8b3b7d6 | 3054 | (define_insn "*sign_extendhisi2_insn" |
7a768814 RS |
3055 | [(set (match_operand:SI 0 "register_operand" "=r") |
3056 | (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | |
3057 | "" | |
3058 | "ldsh %1,%0" | |
3059 | [(set_attr "type" "load")]) | |
3060 | ||
a8d2b752 DE |
3061 | (define_expand "extendqihi2" |
3062 | [(set (match_operand:HI 0 "register_operand" "") | |
3063 | (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] | |
3064 | "" | |
3065 | " | |
3066 | { | |
3067 | rtx temp = gen_reg_rtx (SImode); | |
5d4f5e87 | 3068 | rtx shift_24 = GEN_INT (24); |
a8d2b752 DE |
3069 | int op1_subword = 0; |
3070 | int op0_subword = 0; | |
3071 | ||
3072 | if (GET_CODE (operand1) == SUBREG) | |
3073 | { | |
3074 | op1_subword = SUBREG_WORD (operand1); | |
3075 | operand1 = XEXP (operand1, 0); | |
3076 | } | |
3077 | if (GET_CODE (operand0) == SUBREG) | |
3078 | { | |
3079 | op0_subword = SUBREG_WORD (operand0); | |
3080 | operand0 = XEXP (operand0, 0); | |
3081 | } | |
3082 | emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, | |
3083 | op1_subword), | |
3084 | shift_24)); | |
3085 | if (GET_MODE (operand0) != SImode) | |
3086 | operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword); | |
3087 | emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); | |
3088 | DONE; | |
3089 | }") | |
3090 | ||
c8b3b7d6 | 3091 | (define_insn "*sign_extendqihi2_insn" |
a8d2b752 DE |
3092 | [(set (match_operand:HI 0 "register_operand" "=r") |
3093 | (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] | |
3094 | "" | |
3095 | "ldsb %1,%0" | |
3096 | [(set_attr "type" "load")]) | |
3097 | ||
3098 | (define_expand "extendqisi2" | |
3099 | [(set (match_operand:SI 0 "register_operand" "") | |
3100 | (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] | |
3101 | "" | |
3102 | " | |
3103 | { | |
3104 | rtx temp = gen_reg_rtx (SImode); | |
5d4f5e87 | 3105 | rtx shift_24 = GEN_INT (24); |
a8d2b752 DE |
3106 | int op1_subword = 0; |
3107 | ||
3108 | if (GET_CODE (operand1) == SUBREG) | |
3109 | { | |
3110 | op1_subword = SUBREG_WORD (operand1); | |
3111 | operand1 = XEXP (operand1, 0); | |
3112 | } | |
3113 | ||
3114 | emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, | |
3115 | op1_subword), | |
3116 | shift_24)); | |
3117 | emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); | |
3118 | DONE; | |
3119 | }") | |
3120 | ||
c8b3b7d6 | 3121 | (define_insn "*sign_extendqisi2_insn" |
a8d2b752 DE |
3122 | [(set (match_operand:SI 0 "register_operand" "=r") |
3123 | (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] | |
3124 | "" | |
3125 | "ldsb %1,%0" | |
3126 | [(set_attr "type" "load")]) | |
3127 | ||
3128 | (define_expand "extendqidi2" | |
3129 | [(set (match_operand:DI 0 "register_operand" "") | |
3130 | (sign_extend:DI (match_operand:QI 1 "register_operand" "")))] | |
fa0f39e4 | 3131 | "TARGET_ARCH64" |
7a768814 RS |
3132 | " |
3133 | { | |
a8d2b752 | 3134 | rtx temp = gen_reg_rtx (DImode); |
5d4f5e87 | 3135 | rtx shift_56 = GEN_INT (56); |
053e4cac | 3136 | int op1_subword = 0; |
7a768814 RS |
3137 | |
3138 | if (GET_CODE (operand1) == SUBREG) | |
053e4cac JW |
3139 | { |
3140 | op1_subword = SUBREG_WORD (operand1); | |
3141 | operand1 = XEXP (operand1, 0); | |
3142 | } | |
a8d2b752 DE |
3143 | |
3144 | emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1, | |
053e4cac | 3145 | op1_subword), |
a8d2b752 DE |
3146 | shift_56)); |
3147 | emit_insn (gen_ashrdi3 (operand0, temp, shift_56)); | |
7a768814 RS |
3148 | DONE; |
3149 | }") | |
3150 | ||
c8b3b7d6 | 3151 | (define_insn "*sign_extendqidi2_insn" |
a8d2b752 DE |
3152 | [(set (match_operand:DI 0 "register_operand" "=r") |
3153 | (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))] | |
fa0f39e4 | 3154 | "TARGET_ARCH64" |
7a768814 RS |
3155 | "ldsb %1,%0" |
3156 | [(set_attr "type" "load")]) | |
3157 | ||
a8d2b752 DE |
3158 | (define_expand "extendhidi2" |
3159 | [(set (match_operand:DI 0 "register_operand" "") | |
3160 | (sign_extend:DI (match_operand:HI 1 "register_operand" "")))] | |
fa0f39e4 | 3161 | "TARGET_ARCH64" |
7a768814 RS |
3162 | " |
3163 | { | |
a8d2b752 | 3164 | rtx temp = gen_reg_rtx (DImode); |
5d4f5e87 | 3165 | rtx shift_48 = GEN_INT (48); |
053e4cac | 3166 | int op1_subword = 0; |
7a768814 RS |
3167 | |
3168 | if (GET_CODE (operand1) == SUBREG) | |
053e4cac JW |
3169 | { |
3170 | op1_subword = SUBREG_WORD (operand1); | |
3171 | operand1 = XEXP (operand1, 0); | |
3172 | } | |
3173 | ||
a8d2b752 | 3174 | emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1, |
053e4cac | 3175 | op1_subword), |
a8d2b752 DE |
3176 | shift_48)); |
3177 | emit_insn (gen_ashrdi3 (operand0, temp, shift_48)); | |
7a768814 RS |
3178 | DONE; |
3179 | }") | |
3180 | ||
c8b3b7d6 | 3181 | (define_insn "*sign_extendhidi2_insn" |
a8d2b752 DE |
3182 | [(set (match_operand:DI 0 "register_operand" "=r") |
3183 | (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))] | |
fa0f39e4 | 3184 | "TARGET_ARCH64" |
a8d2b752 | 3185 | "ldsh %1,%0" |
7a768814 | 3186 | [(set_attr "type" "load")]) |
a8d2b752 DE |
3187 | |
3188 | (define_expand "extendsidi2" | |
3189 | [(set (match_operand:DI 0 "register_operand" "") | |
3190 | (sign_extend:DI (match_operand:SI 1 "register_operand" "")))] | |
fa0f39e4 | 3191 | "TARGET_ARCH64" |
a8d2b752 DE |
3192 | "") |
3193 | ||
c8b3b7d6 | 3194 | (define_insn "*sign_extendsidi2_insn" |
a8d2b752 DE |
3195 | [(set (match_operand:DI 0 "register_operand" "=r,r") |
3196 | (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))] | |
fa0f39e4 | 3197 | "TARGET_ARCH64" |
a8d2b752 DE |
3198 | "@ |
3199 | sra %1,0,%0 | |
3200 | ldsw %1,%0" | |
3201 | [(set_attr "type" "unary,load") | |
3202 | (set_attr "length" "1")]) | |
7a768814 | 3203 | \f |
b4ac57ab RS |
3204 | ;; Special pattern for optimizing bit-field compares. This is needed |
3205 | ;; because combine uses this as a canonical form. | |
3206 | ||
c8b3b7d6 | 3207 | (define_insn "*cmp_zero_extract" |
c4ce6853 | 3208 | [(set (reg:CC 100) |
b4ac57ab RS |
3209 | (compare:CC |
3210 | (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
3211 | (match_operand:SI 1 "small_int" "n") | |
3212 | (match_operand:SI 2 "small_int" "n")) | |
3213 | (const_int 0)))] | |
3214 | "INTVAL (operands[2]) > 19" | |
3215 | "* | |
3216 | { | |
3217 | int len = INTVAL (operands[1]); | |
3218 | int pos = 32 - INTVAL (operands[2]) - len; | |
3219 | unsigned mask = ((1 << len) - 1) << pos; | |
3220 | ||
5d4f5e87 | 3221 | operands[1] = GEN_INT (mask); |
b4ac57ab RS |
3222 | return \"andcc %0,%1,%%g0\"; |
3223 | }") | |
a8d2b752 | 3224 | |
c8b3b7d6 | 3225 | (define_insn "*cmp_zero_extract_sp64" |
c4ce6853 | 3226 | [(set (reg:CCX 100) |
a8d2b752 DE |
3227 | (compare:CCX |
3228 | (zero_extract:DI (match_operand:DI 0 "register_operand" "r") | |
3229 | (match_operand:SI 1 "small_int" "n") | |
3230 | (match_operand:SI 2 "small_int" "n")) | |
3231 | (const_int 0)))] | |
fa0f39e4 | 3232 | "TARGET_ARCH64 && INTVAL (operands[2]) > 51" |
a8d2b752 DE |
3233 | "* |
3234 | { | |
3235 | int len = INTVAL (operands[1]); | |
3236 | int pos = 64 - INTVAL (operands[2]) - len; | |
5d4f5e87 | 3237 | unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos; |
a8d2b752 | 3238 | |
5d4f5e87 | 3239 | operands[1] = GEN_INT (mask); |
a8d2b752 DE |
3240 | return \"andcc %0,%1,%%g0\"; |
3241 | }") | |
b4ac57ab | 3242 | \f |
795068a4 | 3243 | ;; Conversions between float, double and long double. |
7a768814 RS |
3244 | |
3245 | (define_insn "extendsfdf2" | |
b6d3c4ba | 3246 | [(set (match_operand:DF 0 "register_operand" "=e") |
7a768814 RS |
3247 | (float_extend:DF |
3248 | (match_operand:SF 1 "register_operand" "f")))] | |
ab5519b7 | 3249 | "TARGET_FPU" |
7a768814 RS |
3250 | "fstod %1,%0" |
3251 | [(set_attr "type" "fp")]) | |
3252 | ||
795068a4 | 3253 | (define_insn "extendsftf2" |
b6d3c4ba | 3254 | [(set (match_operand:TF 0 "register_operand" "=e") |
795068a4 JW |
3255 | (float_extend:TF |
3256 | (match_operand:SF 1 "register_operand" "f")))] | |
ef903eca | 3257 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
3258 | "fstoq %1,%0" |
3259 | [(set_attr "type" "fp")]) | |
3260 | ||
3261 | (define_insn "extenddftf2" | |
b6d3c4ba | 3262 | [(set (match_operand:TF 0 "register_operand" "=e") |
795068a4 | 3263 | (float_extend:TF |
b6d3c4ba | 3264 | (match_operand:DF 1 "register_operand" "e")))] |
ef903eca | 3265 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
3266 | "fdtoq %1,%0" |
3267 | [(set_attr "type" "fp")]) | |
3268 | ||
7a768814 RS |
3269 | (define_insn "truncdfsf2" |
3270 | [(set (match_operand:SF 0 "register_operand" "=f") | |
3271 | (float_truncate:SF | |
b6d3c4ba | 3272 | (match_operand:DF 1 "register_operand" "e")))] |
ab5519b7 | 3273 | "TARGET_FPU" |
7a768814 RS |
3274 | "fdtos %1,%0" |
3275 | [(set_attr "type" "fp")]) | |
795068a4 JW |
3276 | |
3277 | (define_insn "trunctfsf2" | |
3278 | [(set (match_operand:SF 0 "register_operand" "=f") | |
3279 | (float_truncate:SF | |
b6d3c4ba | 3280 | (match_operand:TF 1 "register_operand" "e")))] |
ef903eca | 3281 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
3282 | "fqtos %1,%0" |
3283 | [(set_attr "type" "fp")]) | |
3284 | ||
3285 | (define_insn "trunctfdf2" | |
b6d3c4ba | 3286 | [(set (match_operand:DF 0 "register_operand" "=e") |
795068a4 | 3287 | (float_truncate:DF |
b6d3c4ba | 3288 | (match_operand:TF 1 "register_operand" "e")))] |
ef903eca | 3289 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
3290 | "fqtod %1,%0" |
3291 | [(set_attr "type" "fp")]) | |
7a768814 RS |
3292 | \f |
3293 | ;; Conversion between fixed point and floating point. | |
3294 | ||
3295 | (define_insn "floatsisf2" | |
ec08cf0a JW |
3296 | [(set (match_operand:SF 0 "register_operand" "=f") |
3297 | (float:SF (match_operand:SI 1 "register_operand" "f")))] | |
ab5519b7 | 3298 | "TARGET_FPU" |
ec08cf0a JW |
3299 | "fitos %1,%0" |
3300 | [(set_attr "type" "fp")]) | |
7a768814 RS |
3301 | |
3302 | (define_insn "floatsidf2" | |
b6d3c4ba | 3303 | [(set (match_operand:DF 0 "register_operand" "=e") |
ec08cf0a | 3304 | (float:DF (match_operand:SI 1 "register_operand" "f")))] |
ab5519b7 | 3305 | "TARGET_FPU" |
ec08cf0a JW |
3306 | "fitod %1,%0" |
3307 | [(set_attr "type" "fp")]) | |
7a768814 | 3308 | |
795068a4 | 3309 | (define_insn "floatsitf2" |
b6d3c4ba | 3310 | [(set (match_operand:TF 0 "register_operand" "=e") |
ec08cf0a | 3311 | (float:TF (match_operand:SI 1 "register_operand" "f")))] |
ef903eca | 3312 | "TARGET_FPU && TARGET_HARD_QUAD" |
1d77b9c1 | 3313 | "fitoq %1,%0" |
ec08cf0a | 3314 | [(set_attr "type" "fp")]) |
795068a4 | 3315 | |
a8d2b752 DE |
3316 | ;; Now the same for 64 bit sources. |
3317 | ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2). | |
3318 | ||
3319 | (define_expand "floatdisf2" | |
3320 | [(parallel [(set (match_operand:SF 0 "register_operand" "") | |
3321 | (float:SF (match_operand:DI 1 "general_operand" ""))) | |
3322 | (clobber (match_dup 2)) | |
3323 | (clobber (match_dup 3))])] | |
fa0f39e4 | 3324 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3325 | " |
3326 | { | |
3327 | operands[2] = gen_reg_rtx (DFmode); | |
3328 | operands[3] = sparc64_fpconv_stack_temp (); | |
3329 | }") | |
3330 | ||
3331 | (define_expand "floatdidf2" | |
3332 | [(parallel [(set (match_operand:DF 0 "register_operand" "") | |
3333 | (float:DF (match_operand:DI 1 "general_operand" ""))) | |
3334 | (clobber (match_dup 2)) | |
3335 | (clobber (match_dup 3))])] | |
fa0f39e4 | 3336 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3337 | " |
3338 | { | |
3339 | operands[2] = gen_reg_rtx (DFmode); | |
3340 | operands[3] = sparc64_fpconv_stack_temp (); | |
3341 | }") | |
3342 | ||
3343 | (define_expand "floatditf2" | |
3344 | [(parallel [(set (match_operand:TF 0 "register_operand" "") | |
3345 | (float:TF (match_operand:DI 1 "general_operand" ""))) | |
3346 | (clobber (match_dup 2)) | |
3347 | (clobber (match_dup 3))])] | |
fa0f39e4 | 3348 | "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" |
a8d2b752 DE |
3349 | " |
3350 | { | |
3351 | operands[2] = gen_reg_rtx (DFmode); | |
3352 | operands[3] = sparc64_fpconv_stack_temp (); | |
3353 | }") | |
3354 | ||
c8b3b7d6 | 3355 | (define_insn "*floatdisf2_insn" |
a8d2b752 DE |
3356 | [(parallel [(set (match_operand:SF 0 "register_operand" "=f") |
3357 | (float:SF (match_operand:DI 1 "general_operand" "rm"))) | |
b6d3c4ba | 3358 | (clobber (match_operand:DF 2 "register_operand" "=&e")) |
a8d2b752 | 3359 | (clobber (match_operand:DI 3 "memory_operand" "m"))])] |
fa0f39e4 | 3360 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3361 | "* |
3362 | { | |
3363 | if (GET_CODE (operands[1]) == MEM) | |
3364 | output_asm_insn (\"ldd %1,%2\", operands); | |
3365 | else | |
3366 | output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands); | |
3367 | return \"fxtos %2,%0\"; | |
3368 | }" | |
3369 | [(set_attr "type" "fp") | |
3370 | (set_attr "length" "3")]) | |
3371 | ||
c8b3b7d6 | 3372 | (define_insn "*floatdidf2_insn" |
b6d3c4ba | 3373 | [(parallel [(set (match_operand:DF 0 "register_operand" "=e") |
a8d2b752 | 3374 | (float:DF (match_operand:DI 1 "general_operand" "rm"))) |
b6d3c4ba | 3375 | (clobber (match_operand:DF 2 "register_operand" "=&e")) |
a8d2b752 | 3376 | (clobber (match_operand:DI 3 "memory_operand" "m"))])] |
fa0f39e4 | 3377 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3378 | "* |
3379 | { | |
3380 | if (GET_CODE (operands[1]) == MEM) | |
3381 | output_asm_insn (\"ldd %1,%2\", operands); | |
3382 | else | |
3383 | output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands); | |
3384 | return \"fxtod %2,%0\"; | |
3385 | }" | |
3386 | [(set_attr "type" "fp") | |
3387 | (set_attr "length" "3")]) | |
3388 | ||
c8b3b7d6 | 3389 | (define_insn "*floatditf2_insn" |
b6d3c4ba | 3390 | [(parallel [(set (match_operand:TF 0 "register_operand" "=e") |
a8d2b752 | 3391 | (float:TF (match_operand:DI 1 "general_operand" "rm"))) |
b6d3c4ba | 3392 | (clobber (match_operand:DF 2 "register_operand" "=&e")) |
a8d2b752 | 3393 | (clobber (match_operand:DI 3 "memory_operand" "m"))])] |
fa0f39e4 | 3394 | "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" |
a8d2b752 DE |
3395 | "* |
3396 | { | |
3397 | if (GET_CODE (operands[1]) == MEM) | |
3398 | output_asm_insn (\"ldd %1,%2\", operands); | |
3399 | else | |
3400 | output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands); | |
3401 | return \"fxtoq %2,%0\"; | |
3402 | }" | |
3403 | [(set_attr "type" "fp") | |
3404 | (set_attr "length" "3")]) | |
3405 | ||
3406 | ;; ??? Ideally, these are what we would like to use. | |
3407 | ||
c8b3b7d6 | 3408 | (define_insn "floatdisf2_sp64" |
a8d2b752 | 3409 | [(set (match_operand:SF 0 "register_operand" "=f") |
b6d3c4ba | 3410 | (float:SF (match_operand:DI 1 "register_operand" "e")))] |
fa0f39e4 | 3411 | "0 && TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3412 | "fxtos %1,%0" |
3413 | [(set_attr "type" "fp")]) | |
3414 | ||
c8b3b7d6 | 3415 | (define_insn "floatdidf2_sp64" |
b6d3c4ba JW |
3416 | [(set (match_operand:DF 0 "register_operand" "=e") |
3417 | (float:DF (match_operand:DI 1 "register_operand" "e")))] | |
fa0f39e4 | 3418 | "0 && TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3419 | "fxtod %1,%0" |
3420 | [(set_attr "type" "fp")]) | |
3421 | ||
c8b3b7d6 | 3422 | (define_insn "floatditf2_sp64" |
b6d3c4ba JW |
3423 | [(set (match_operand:TF 0 "register_operand" "=e") |
3424 | (float:TF (match_operand:DI 1 "register_operand" "e")))] | |
fa0f39e4 | 3425 | "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" |
a8d2b752 DE |
3426 | "fxtoq %1,%0" |
3427 | [(set_attr "type" "fp")]) | |
3428 | ||
7a768814 RS |
3429 | ;; Convert a float to an actual integer. |
3430 | ;; Truncation is performed as part of the conversion. | |
3431 | ||
3432 | (define_insn "fix_truncsfsi2" | |
ec08cf0a JW |
3433 | [(set (match_operand:SI 0 "register_operand" "=f") |
3434 | (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] | |
ab5519b7 | 3435 | "TARGET_FPU" |
ec08cf0a JW |
3436 | "fstoi %1,%0" |
3437 | [(set_attr "type" "fp")]) | |
7a768814 RS |
3438 | |
3439 | (define_insn "fix_truncdfsi2" | |
ec08cf0a | 3440 | [(set (match_operand:SI 0 "register_operand" "=f") |
b6d3c4ba | 3441 | (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))] |
ab5519b7 | 3442 | "TARGET_FPU" |
ec08cf0a JW |
3443 | "fdtoi %1,%0" |
3444 | [(set_attr "type" "fp")]) | |
a3ee5899 | 3445 | |
795068a4 | 3446 | (define_insn "fix_trunctfsi2" |
ec08cf0a | 3447 | [(set (match_operand:SI 0 "register_operand" "=f") |
b6d3c4ba | 3448 | (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))] |
ef903eca | 3449 | "TARGET_FPU && TARGET_HARD_QUAD" |
ec08cf0a JW |
3450 | "fqtoi %1,%0" |
3451 | [(set_attr "type" "fp")]) | |
a8d2b752 DE |
3452 | |
3453 | ;; Now the same, for 64-bit targets | |
3454 | ;; ??? We try to work around an interesting problem. | |
3455 | ;; If gcc tries to do a subreg on the result it will get the wrong answer: | |
3456 | ;; "(subreg:SI (reg:DI M int-reg) 0)" is the same as | |
3457 | ;; "(subreg:SI (reg:DI N float-reg) 1)", but gcc does not know how to change | |
3458 | ;; the "0" to a "1". One could enhance alter_subreg but it is not clear how to | |
3459 | ;; do this cleanly. | |
3460 | ||
3461 | (define_expand "fix_truncsfdi2" | |
3462 | [(parallel [(set (match_operand:DI 0 "general_operand" "") | |
3463 | (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "")))) | |
3464 | (clobber (match_dup 2)) | |
3465 | (clobber (match_dup 3))])] | |
fa0f39e4 | 3466 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3467 | " |
3468 | { | |
3469 | operands[2] = gen_reg_rtx (DFmode); | |
3470 | operands[3] = sparc64_fpconv_stack_temp (); | |
3471 | }") | |
3472 | ||
3473 | (define_expand "fix_truncdfdi2" | |
3474 | [(parallel [(set (match_operand:DI 0 "general_operand" "") | |
3475 | (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "")))) | |
3476 | (clobber (match_dup 2)) | |
3477 | (clobber (match_dup 3))])] | |
fa0f39e4 | 3478 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3479 | " |
3480 | { | |
3481 | operands[2] = gen_reg_rtx (DFmode); | |
3482 | operands[3] = sparc64_fpconv_stack_temp (); | |
3483 | }") | |
3484 | ||
3485 | (define_expand "fix_trunctfdi2" | |
3486 | [(parallel [(set (match_operand:DI 0 "general_operand" "") | |
3487 | (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "")))) | |
3488 | (clobber (match_dup 2)) | |
3489 | (clobber (match_dup 3))])] | |
fa0f39e4 | 3490 | "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" |
a8d2b752 DE |
3491 | " |
3492 | { | |
3493 | operands[2] = gen_reg_rtx (DFmode); | |
3494 | operands[3] = sparc64_fpconv_stack_temp (); | |
3495 | }") | |
3496 | ||
c8b3b7d6 | 3497 | (define_insn "*fix_truncsfdi2_insn" |
a8d2b752 DE |
3498 | [(parallel [(set (match_operand:DI 0 "general_operand" "=rm") |
3499 | (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) | |
b6d3c4ba | 3500 | (clobber (match_operand:DF 2 "register_operand" "=&e")) |
a8d2b752 | 3501 | (clobber (match_operand:DI 3 "memory_operand" "m"))])] |
fa0f39e4 | 3502 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3503 | "* |
3504 | { | |
3505 | output_asm_insn (\"fstox %1,%2\", operands); | |
3506 | if (GET_CODE (operands[0]) == MEM) | |
3507 | return \"std %2,%0\"; | |
3508 | else | |
3509 | return \"std %2,%3\;ldx %3,%0\"; | |
3510 | }" | |
3511 | [(set_attr "type" "fp") | |
3512 | (set_attr "length" "3")]) | |
3513 | ||
c8b3b7d6 | 3514 | (define_insn "*fix_truncdfdi2_insn" |
a8d2b752 | 3515 | [(parallel [(set (match_operand:DI 0 "general_operand" "=rm") |
b6d3c4ba JW |
3516 | (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e")))) |
3517 | (clobber (match_operand:DF 2 "register_operand" "=&e")) | |
a8d2b752 | 3518 | (clobber (match_operand:DI 3 "memory_operand" "m"))])] |
fa0f39e4 | 3519 | "TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3520 | "* |
3521 | { | |
3522 | output_asm_insn (\"fdtox %1,%2\", operands); | |
3523 | if (GET_CODE (operands[0]) == MEM) | |
3524 | return \"std %2,%0\"; | |
3525 | else | |
3526 | return \"std %2,%3\;ldx %3,%0\"; | |
3527 | }" | |
3528 | [(set_attr "type" "fp") | |
3529 | (set_attr "length" "3")]) | |
3530 | ||
c8b3b7d6 | 3531 | (define_insn "*fix_trunctfdi2_insn" |
a8d2b752 | 3532 | [(parallel [(set (match_operand:DI 0 "general_operand" "=rm") |
b6d3c4ba JW |
3533 | (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e")))) |
3534 | (clobber (match_operand:DF 2 "register_operand" "=&e")) | |
a8d2b752 | 3535 | (clobber (match_operand:DI 3 "memory_operand" "m"))])] |
fa0f39e4 | 3536 | "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" |
a8d2b752 DE |
3537 | "* |
3538 | { | |
3539 | output_asm_insn (\"fqtox %1,%2\", operands); | |
3540 | if (GET_CODE (operands[0]) == MEM) | |
3541 | return \"std %2,%0\"; | |
3542 | else | |
3543 | return \"std %2,%3\;ldx %3,%0\"; | |
3544 | }" | |
3545 | [(set_attr "type" "fp") | |
3546 | (set_attr "length" "3")]) | |
3547 | ||
3548 | ;; ??? Ideally, these are what we would like to use. | |
3549 | ||
c8b3b7d6 | 3550 | (define_insn "fix_truncsfdi2_sp64" |
b6d3c4ba | 3551 | [(set (match_operand:DI 0 "register_operand" "=e") |
a8d2b752 | 3552 | (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] |
fa0f39e4 | 3553 | "0 && TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3554 | "fstox %1,%0" |
3555 | [(set_attr "type" "fp")]) | |
3556 | ||
c8b3b7d6 | 3557 | (define_insn "fix_truncdfdi2_sp64" |
b6d3c4ba JW |
3558 | [(set (match_operand:DI 0 "register_operand" "=e") |
3559 | (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))] | |
fa0f39e4 | 3560 | "0 && TARGET_ARCH64 && TARGET_FPU" |
a8d2b752 DE |
3561 | "fdtox %1,%0" |
3562 | [(set_attr "type" "fp")]) | |
3563 | ||
c8b3b7d6 | 3564 | (define_insn "fix_trunctfdi2_sp64" |
b6d3c4ba JW |
3565 | [(set (match_operand:DI 0 "register_operand" "=e") |
3566 | (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))] | |
fa0f39e4 | 3567 | "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" |
a8d2b752 DE |
3568 | "fqtox %1,%0" |
3569 | [(set_attr "type" "fp")]) | |
7a768814 RS |
3570 | \f |
3571 | ;;- arithmetic instructions | |
3572 | ||
a8d2b752 DE |
3573 | (define_expand "adddi3" |
3574 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3575 | (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
3576 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
3577 | "" | |
3578 | " | |
3579 | { | |
fa0f39e4 | 3580 | if (! TARGET_ARCH64) |
a8d2b752 DE |
3581 | { |
3582 | emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, | |
3583 | gen_rtx (SET, VOIDmode, operands[0], | |
3584 | gen_rtx (PLUS, DImode, operands[1], | |
3585 | operands[2])), | |
c4ce6853 DE |
3586 | gen_rtx (CLOBBER, VOIDmode, |
3587 | gen_rtx (REG, SImode, SPARC_ICC_REG))))); | |
a8d2b752 DE |
3588 | DONE; |
3589 | } | |
3590 | }") | |
3591 | ||
c8b3b7d6 | 3592 | (define_insn "*adddi3_sp32" |
7a768814 RS |
3593 | [(set (match_operand:DI 0 "register_operand" "=r") |
3594 | (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
3595 | (match_operand:DI 2 "arith_double_operand" "rHI"))) | |
c4ce6853 | 3596 | (clobber (reg:SI 100))] |
fa0f39e4 | 3597 | "! TARGET_ARCH64" |
7a768814 RS |
3598 | "* |
3599 | { | |
3600 | rtx op2 = operands[2]; | |
3601 | ||
103fa525 DE |
3602 | if (GET_CODE (op2) == CONST_INT |
3603 | || GET_CODE (op2) == CONST_DOUBLE) | |
7a768814 | 3604 | { |
ae526227 JW |
3605 | rtx xoperands[4]; |
3606 | xoperands[0] = operands[0]; | |
3607 | xoperands[1] = operands[1]; | |
103fa525 DE |
3608 | if (WORDS_BIG_ENDIAN) |
3609 | split_double (op2, &xoperands[2], &xoperands[3]); | |
3610 | else | |
3611 | split_double (op2, &xoperands[3], &xoperands[2]); | |
3612 | if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1]) | |
3613 | output_asm_insn (\"add %H1,%2,%H0\", xoperands); | |
ae526227 | 3614 | else |
103fa525 | 3615 | output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands); |
ae526227 | 3616 | return \"\"; |
7a768814 | 3617 | } |
103fa525 | 3618 | return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\"; |
7a768814 RS |
3619 | }" |
3620 | [(set_attr "length" "2")]) | |
3621 | ||
c8b3b7d6 | 3622 | (define_insn "*adddi3_sp64" |
a8d2b752 DE |
3623 | [(set (match_operand:DI 0 "register_operand" "=r") |
3624 | (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
3625 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 3626 | "TARGET_ARCH64" |
a8d2b752 DE |
3627 | "add %1,%2,%0") |
3628 | ||
7a768814 RS |
3629 | (define_insn "addsi3" |
3630 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3631 | (plus:SI (match_operand:SI 1 "arith_operand" "%r") | |
3632 | (match_operand:SI 2 "arith_operand" "rI")))] | |
3633 | "" | |
c180bd1e JW |
3634 | "add %1,%2,%0" |
3635 | [(set_attr "type" "ialu")]) | |
7a768814 | 3636 | |
c8b3b7d6 | 3637 | (define_insn "*cmp_cc_plus" |
c4ce6853 | 3638 | [(set (reg:CC_NOOV 100) |
7a768814 RS |
3639 | (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r") |
3640 | (match_operand:SI 1 "arith_operand" "rI")) | |
3641 | (const_int 0)))] | |
3642 | "" | |
3643 | "addcc %0,%1,%%g0" | |
3644 | [(set_attr "type" "compare")]) | |
3645 | ||
c8b3b7d6 | 3646 | (define_insn "*cmp_ccx_plus" |
c4ce6853 | 3647 | [(set (reg:CCX_NOOV 100) |
a8d2b752 DE |
3648 | (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r") |
3649 | (match_operand:DI 1 "arith_double_operand" "rHI")) | |
3650 | (const_int 0)))] | |
fa0f39e4 | 3651 | "TARGET_ARCH64" |
a8d2b752 DE |
3652 | "addcc %0,%1,%%g0" |
3653 | [(set_attr "type" "compare")]) | |
3654 | ||
c8b3b7d6 | 3655 | (define_insn "*cmp_cc_plus_set" |
c4ce6853 | 3656 | [(set (reg:CC_NOOV 100) |
7a768814 RS |
3657 | (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r") |
3658 | (match_operand:SI 2 "arith_operand" "rI")) | |
3659 | (const_int 0))) | |
3660 | (set (match_operand:SI 0 "register_operand" "=r") | |
3661 | (plus:SI (match_dup 1) (match_dup 2)))] | |
3662 | "" | |
3663 | "addcc %1,%2,%0") | |
3664 | ||
c8b3b7d6 | 3665 | (define_insn "*cmp_ccx_plus_set" |
c4ce6853 | 3666 | [(set (reg:CCX_NOOV 100) |
a8d2b752 DE |
3667 | (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") |
3668 | (match_operand:DI 2 "arith_double_operand" "rHI")) | |
3669 | (const_int 0))) | |
3670 | (set (match_operand:DI 0 "register_operand" "=r") | |
3671 | (plus:DI (match_dup 1) (match_dup 2)))] | |
fa0f39e4 | 3672 | "TARGET_ARCH64" |
a8d2b752 DE |
3673 | "addcc %1,%2,%0") |
3674 | ||
3675 | (define_expand "subdi3" | |
3676 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3677 | (minus:DI (match_operand:DI 1 "register_operand" "r") | |
3678 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
3679 | "" | |
3680 | " | |
3681 | { | |
fa0f39e4 | 3682 | if (! TARGET_ARCH64) |
a8d2b752 DE |
3683 | { |
3684 | emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, | |
3685 | gen_rtx (SET, VOIDmode, operands[0], | |
3686 | gen_rtx (MINUS, DImode, operands[1], | |
3687 | operands[2])), | |
c4ce6853 DE |
3688 | gen_rtx (CLOBBER, VOIDmode, |
3689 | gen_rtx (REG, SImode, SPARC_ICC_REG))))); | |
a8d2b752 DE |
3690 | DONE; |
3691 | } | |
3692 | }") | |
3693 | ||
c8b3b7d6 | 3694 | (define_insn "*subdi3_sp32" |
7a768814 RS |
3695 | [(set (match_operand:DI 0 "register_operand" "=r") |
3696 | (minus:DI (match_operand:DI 1 "register_operand" "r") | |
3697 | (match_operand:DI 2 "arith_double_operand" "rHI"))) | |
c4ce6853 | 3698 | (clobber (reg:SI 100))] |
fa0f39e4 | 3699 | "! TARGET_ARCH64" |
7a768814 RS |
3700 | "* |
3701 | { | |
3702 | rtx op2 = operands[2]; | |
3703 | ||
103fa525 DE |
3704 | if (GET_CODE (op2) == CONST_INT |
3705 | || GET_CODE (op2) == CONST_DOUBLE) | |
7a768814 | 3706 | { |
ae526227 JW |
3707 | rtx xoperands[4]; |
3708 | xoperands[0] = operands[0]; | |
3709 | xoperands[1] = operands[1]; | |
103fa525 DE |
3710 | if (WORDS_BIG_ENDIAN) |
3711 | split_double (op2, &xoperands[2], &xoperands[3]); | |
ae526227 | 3712 | else |
103fa525 DE |
3713 | split_double (op2, &xoperands[3], &xoperands[2]); |
3714 | if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1]) | |
3715 | output_asm_insn (\"sub %H1,%2,%H0\", xoperands); | |
3716 | else | |
3717 | output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands); | |
ae526227 | 3718 | return \"\"; |
7a768814 | 3719 | } |
103fa525 | 3720 | return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\"; |
7a768814 RS |
3721 | }" |
3722 | [(set_attr "length" "2")]) | |
3723 | ||
c8b3b7d6 | 3724 | (define_insn "*subdi3_sp64" |
a8d2b752 DE |
3725 | [(set (match_operand:DI 0 "register_operand" "=r") |
3726 | (minus:DI (match_operand:DI 1 "register_operand" "r") | |
3727 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 3728 | "TARGET_ARCH64" |
a8d2b752 DE |
3729 | "sub %1,%2,%0") |
3730 | ||
7a768814 RS |
3731 | (define_insn "subsi3" |
3732 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3733 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
3734 | (match_operand:SI 2 "arith_operand" "rI")))] | |
3735 | "" | |
c180bd1e JW |
3736 | "sub %1,%2,%0" |
3737 | [(set_attr "type" "ialu")]) | |
7a768814 | 3738 | |
c8b3b7d6 | 3739 | (define_insn "*cmp_minus_cc" |
c4ce6853 | 3740 | [(set (reg:CC_NOOV 100) |
7a768814 RS |
3741 | (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r") |
3742 | (match_operand:SI 1 "arith_operand" "rI")) | |
3743 | (const_int 0)))] | |
3744 | "" | |
3745 | "subcc %0,%1,%%g0" | |
3746 | [(set_attr "type" "compare")]) | |
3747 | ||
c8b3b7d6 | 3748 | (define_insn "*cmp_minus_ccx" |
c4ce6853 | 3749 | [(set (reg:CCX_NOOV 100) |
a8d2b752 DE |
3750 | (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r") |
3751 | (match_operand:DI 1 "arith_double_operand" "rHI")) | |
3752 | (const_int 0)))] | |
fa0f39e4 | 3753 | "TARGET_ARCH64" |
a8d2b752 DE |
3754 | "subcc %0,%1,%%g0" |
3755 | [(set_attr "type" "compare")]) | |
3756 | ||
c8b3b7d6 | 3757 | (define_insn "*cmp_minus_cc_set" |
c4ce6853 | 3758 | [(set (reg:CC_NOOV 100) |
7a768814 RS |
3759 | (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r") |
3760 | (match_operand:SI 2 "arith_operand" "rI")) | |
3761 | (const_int 0))) | |
3762 | (set (match_operand:SI 0 "register_operand" "=r") | |
3763 | (minus:SI (match_dup 1) (match_dup 2)))] | |
3764 | "" | |
3765 | "subcc %1,%2,%0") | |
3766 | ||
c8b3b7d6 | 3767 | (define_insn "*cmp_minus_ccx_set" |
c4ce6853 | 3768 | [(set (reg:CCX_NOOV 100) |
a8d2b752 DE |
3769 | (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r") |
3770 | (match_operand:DI 2 "arith_double_operand" "rHI")) | |
3771 | (const_int 0))) | |
3772 | (set (match_operand:DI 0 "register_operand" "=r") | |
3773 | (minus:DI (match_dup 1) (match_dup 2)))] | |
fa0f39e4 | 3774 | "TARGET_ARCH64" |
a8d2b752 | 3775 | "subcc %1,%2,%0") |
eb582c5d DE |
3776 | \f |
3777 | ;; Integer Multiply/Divide. | |
a8d2b752 | 3778 | |
eb582c5d DE |
3779 | ;; The 32 bit multiply/divide instructions are deprecated on v9 and shouldn't |
3780 | ;; we used. We still use them in 32 bit v9 compilers. | |
3781 | ;; The 64 bit v9 compiler will (/should) widen the args and use muldi3. | |
a8d2b752 | 3782 | |
77a02b01 JW |
3783 | (define_insn "mulsi3" |
3784 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3785 | (mult:SI (match_operand:SI 1 "arith_operand" "%r") | |
3786 | (match_operand:SI 2 "arith_operand" "rI")))] | |
967ba98d | 3787 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
c180bd1e JW |
3788 | "smul %1,%2,%0" |
3789 | [(set_attr "type" "imul")]) | |
77a02b01 | 3790 | |
a8d2b752 DE |
3791 | (define_insn "muldi3" |
3792 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3793 | (mult:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
3794 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 3795 | "TARGET_ARCH64" |
a8d2b752 DE |
3796 | "mulx %1,%2,%0") |
3797 | ||
77a02b01 JW |
3798 | ;; It is not known whether this will match. |
3799 | ||
c8b3b7d6 | 3800 | (define_insn "*cmp_mul_set" |
77a02b01 JW |
3801 | [(set (match_operand:SI 0 "register_operand" "=r") |
3802 | (mult:SI (match_operand:SI 1 "arith_operand" "%r") | |
3803 | (match_operand:SI 2 "arith_operand" "rI"))) | |
c4ce6853 | 3804 | (set (reg:CC_NOOV 100) |
77a02b01 JW |
3805 | (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2)) |
3806 | (const_int 0)))] | |
eb582c5d | 3807 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS" |
c180bd1e JW |
3808 | "smulcc %1,%2,%0" |
3809 | [(set_attr "type" "imul")]) | |
77a02b01 | 3810 | |
ab5519b7 JW |
3811 | (define_expand "mulsidi3" |
3812 | [(set (match_operand:DI 0 "register_operand" "") | |
3813 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) | |
3814 | (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))] | |
967ba98d | 3815 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
ab5519b7 JW |
3816 | " |
3817 | { | |
3818 | if (CONSTANT_P (operands[2])) | |
3819 | { | |
3820 | emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2])); | |
3821 | DONE; | |
3822 | } | |
3823 | }") | |
3824 | ||
c8b3b7d6 | 3825 | (define_insn "*mulsidi3_sp32" |
77a02b01 | 3826 | [(set (match_operand:DI 0 "register_operand" "=r") |
ab5519b7 JW |
3827 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) |
3828 | (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] | |
967ba98d | 3829 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
6d29fc41 DE |
3830 | "* |
3831 | { | |
103fa525 | 3832 | return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\"; |
6d29fc41 DE |
3833 | }" |
3834 | [(set (attr "length") | |
3835 | (if_then_else (eq_attr "isa" "sparclet") | |
3836 | (const_int 1) (const_int 2)))]) | |
77a02b01 | 3837 | |
3826a3da | 3838 | ;; Extra pattern, because sign_extend of a constant isn't valid. |
ab5519b7 JW |
3839 | |
3840 | (define_insn "const_mulsidi3" | |
77a02b01 | 3841 | [(set (match_operand:DI 0 "register_operand" "=r") |
ab5519b7 JW |
3842 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) |
3843 | (match_operand:SI 2 "small_int" "I")))] | |
967ba98d | 3844 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
6d29fc41 DE |
3845 | "* |
3846 | { | |
103fa525 | 3847 | return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\"; |
6d29fc41 DE |
3848 | }" |
3849 | [(set (attr "length") | |
3850 | (if_then_else (eq_attr "isa" "sparclet") | |
3851 | (const_int 1) (const_int 2)))]) | |
ab5519b7 | 3852 | |
e783e4c2 JW |
3853 | (define_expand "smulsi3_highpart" |
3854 | [(set (match_operand:SI 0 "register_operand" "") | |
3855 | (truncate:SI | |
3856 | (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) | |
3857 | (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))) | |
3858 | (const_int 32))))] | |
967ba98d | 3859 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
e783e4c2 JW |
3860 | " |
3861 | { | |
3862 | if (CONSTANT_P (operands[2])) | |
3863 | { | |
3864 | emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2])); | |
3865 | DONE; | |
3866 | } | |
3867 | }") | |
3868 | ||
c8b3b7d6 | 3869 | (define_insn "*smulsidi3_highpart_sp32" |
e783e4c2 JW |
3870 | [(set (match_operand:SI 0 "register_operand" "=r") |
3871 | (truncate:SI | |
3872 | (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
3873 | (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) | |
3874 | (const_int 32))))] | |
967ba98d | 3875 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
e783e4c2 JW |
3876 | "smul %1,%2,%%g0\;rd %%y,%0" |
3877 | [(set_attr "length" "2")]) | |
3878 | ||
3879 | (define_insn "const_smulsi3_highpart" | |
3880 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3881 | (truncate:SI | |
3882 | (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
3883 | (match_operand:SI 2 "register_operand" "r")) | |
3884 | (const_int 32))))] | |
967ba98d | 3885 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
e783e4c2 JW |
3886 | "smul %1,%2,%%g0\;rd %%y,%0" |
3887 | [(set_attr "length" "2")]) | |
3888 | ||
ab5519b7 JW |
3889 | (define_expand "umulsidi3" |
3890 | [(set (match_operand:DI 0 "register_operand" "") | |
3891 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) | |
13a7eb33 | 3892 | (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))] |
967ba98d | 3893 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
ab5519b7 JW |
3894 | " |
3895 | { | |
3896 | if (CONSTANT_P (operands[2])) | |
3897 | { | |
3898 | emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2])); | |
3899 | DONE; | |
3900 | } | |
3901 | }") | |
3902 | ||
c8b3b7d6 | 3903 | (define_insn "*umulsidi3_sp32" |
ab5519b7 JW |
3904 | [(set (match_operand:DI 0 "register_operand" "=r") |
3905 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
3906 | (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] | |
967ba98d | 3907 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
6d29fc41 DE |
3908 | "* |
3909 | { | |
103fa525 | 3910 | return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\"; |
6d29fc41 DE |
3911 | }" |
3912 | [(set (attr "length") | |
3913 | (if_then_else (eq_attr "isa" "sparclet") | |
3914 | (const_int 1) (const_int 2)))]) | |
ab5519b7 | 3915 | |
3826a3da | 3916 | ;; Extra pattern, because sign_extend of a constant isn't valid. |
ab5519b7 JW |
3917 | |
3918 | (define_insn "const_umulsidi3" | |
3919 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3920 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
13a7eb33 | 3921 | (match_operand:SI 2 "uns_small_int" "")))] |
967ba98d | 3922 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
6d29fc41 DE |
3923 | "* |
3924 | { | |
103fa525 | 3925 | return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\"; |
6d29fc41 DE |
3926 | }" |
3927 | [(set (attr "length") | |
3928 | (if_then_else (eq_attr "isa" "sparclet") | |
3929 | (const_int 1) (const_int 2)))]) | |
77a02b01 | 3930 | |
e783e4c2 JW |
3931 | (define_expand "umulsi3_highpart" |
3932 | [(set (match_operand:SI 0 "register_operand" "") | |
3933 | (truncate:SI | |
3934 | (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) | |
3935 | (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))) | |
3936 | (const_int 32))))] | |
967ba98d | 3937 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
e783e4c2 JW |
3938 | " |
3939 | { | |
3940 | if (CONSTANT_P (operands[2])) | |
3941 | { | |
3942 | emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2])); | |
3943 | DONE; | |
3944 | } | |
3945 | }") | |
3946 | ||
c8b3b7d6 | 3947 | (define_insn "*umulsidi3_highpart_sp32" |
e783e4c2 JW |
3948 | [(set (match_operand:SI 0 "register_operand" "=r") |
3949 | (truncate:SI | |
3950 | (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
3951 | (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))) | |
3952 | (const_int 32))))] | |
967ba98d | 3953 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
e783e4c2 JW |
3954 | "umul %1,%2,%%g0\;rd %%y,%0" |
3955 | [(set_attr "length" "2")]) | |
3956 | ||
3957 | (define_insn "const_umulsi3_highpart" | |
3958 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3959 | (truncate:SI | |
3960 | (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) | |
3961 | (match_operand:SI 2 "uns_small_int" "")) | |
3962 | (const_int 32))))] | |
967ba98d | 3963 | "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS" |
e783e4c2 JW |
3964 | "umul %1,%2,%%g0\;rd %%y,%0" |
3965 | [(set_attr "length" "2")]) | |
3966 | ||
eb582c5d | 3967 | ;; The v8 architecture specifies that there must be 3 instructions between |
77a02b01 JW |
3968 | ;; a y register write and a use of it for correct results. |
3969 | ||
3970 | (define_insn "divsi3" | |
3971 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3972 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
3973 | (match_operand:SI 2 "arith_operand" "rI"))) | |
3974 | (clobber (match_scratch:SI 3 "=&r"))] | |
eb582c5d DE |
3975 | "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" |
3976 | "* | |
3977 | { | |
3978 | if (TARGET_V9) | |
3979 | return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\"; | |
3980 | else | |
3981 | return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\"; | |
3982 | }" | |
3983 | [(set (attr "length") | |
3984 | (if_then_else (eq_attr "isa" "v9") | |
3985 | (const_int 3) (const_int 6)))]) | |
77a02b01 | 3986 | |
a8d2b752 DE |
3987 | (define_insn "divdi3" |
3988 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3989 | (div:DI (match_operand:DI 1 "register_operand" "r") | |
3990 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 3991 | "TARGET_ARCH64" |
a8d2b752 DE |
3992 | "sdivx %1,%2,%0") |
3993 | ||
77a02b01 JW |
3994 | ;; It is not known whether this will match. |
3995 | ||
c8b3b7d6 | 3996 | (define_insn "*cmp_sdiv_cc_set" |
77a02b01 JW |
3997 | [(set (match_operand:SI 0 "register_operand" "=r") |
3998 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
3999 | (match_operand:SI 2 "arith_operand" "rI"))) | |
c4ce6853 | 4000 | (set (reg:CC 100) |
77a02b01 JW |
4001 | (compare:CC (div:SI (match_dup 1) (match_dup 2)) |
4002 | (const_int 0))) | |
4003 | (clobber (match_scratch:SI 3 "=&r"))] | |
eb582c5d DE |
4004 | "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" |
4005 | "* | |
4006 | { | |
4007 | if (TARGET_V9) | |
4008 | return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdivcc %1,%2,%0\"; | |
4009 | else | |
4010 | return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0\"; | |
4011 | }" | |
4012 | [(set (attr "length") | |
4013 | (if_then_else (eq_attr "isa" "v9") | |
4014 | (const_int 3) (const_int 6)))]) | |
77a02b01 JW |
4015 | |
4016 | (define_insn "udivsi3" | |
4017 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4018 | (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
eb582c5d DE |
4019 | (match_operand:SI 2 "arith_operand" "rI")))] |
4020 | "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" | |
4021 | "* | |
4022 | { | |
4023 | if (TARGET_V9) | |
4024 | return \"wr %%g0,%%g0,%%y\;udiv %1,%2,%0\"; | |
4025 | else | |
4026 | return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0\"; | |
4027 | }" | |
4028 | [(set (attr "length") | |
4029 | (if_then_else (eq_attr "isa" "v9") | |
4030 | (const_int 2) (const_int 5)))]) | |
77a02b01 | 4031 | |
a8d2b752 DE |
4032 | (define_insn "udivdi3" |
4033 | [(set (match_operand:DI 0 "register_operand" "=r") | |
4034 | (udiv:DI (match_operand:DI 1 "register_operand" "r") | |
4035 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4036 | "TARGET_ARCH64" |
a8d2b752 DE |
4037 | "udivx %1,%2,%0") |
4038 | ||
77a02b01 JW |
4039 | ;; It is not known whether this will match. |
4040 | ||
c8b3b7d6 | 4041 | (define_insn "*cmp_udiv_cc_set" |
77a02b01 JW |
4042 | [(set (match_operand:SI 0 "register_operand" "=r") |
4043 | (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
4044 | (match_operand:SI 2 "arith_operand" "rI"))) | |
c4ce6853 | 4045 | (set (reg:CC 100) |
77a02b01 JW |
4046 | (compare:CC (udiv:SI (match_dup 1) (match_dup 2)) |
4047 | (const_int 0)))] | |
eb582c5d DE |
4048 | "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" |
4049 | "* | |
4050 | { | |
4051 | if (TARGET_V9) | |
4052 | return \"wr %%g0,%%g0,%%y\;udivcc %1,%2,%0\"; | |
4053 | else | |
4054 | return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0\"; | |
4055 | }" | |
4056 | [(set (attr "length") | |
4057 | (if_then_else (eq_attr "isa" "v9") | |
4058 | (const_int 2) (const_int 5)))]) | |
967ba98d DE |
4059 | |
4060 | ; sparclet multiply/accumulate insns | |
4061 | ||
4062 | (define_insn "*smacsi" | |
637166fe | 4063 | [(set (match_operand:SI 0 "register_operand" "=r") |
967ba98d DE |
4064 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r") |
4065 | (match_operand:SI 2 "arith_operand" "rI")) | |
6d29fc41 | 4066 | (match_operand:SI 3 "register_operand" "0")))] |
967ba98d DE |
4067 | "TARGET_SPARCLET" |
4068 | "smac %1,%2,%0" | |
4069 | [(set_attr "type" "imul")]) | |
4070 | ||
4071 | (define_insn "*smacdi" | |
637166fe | 4072 | [(set (match_operand:DI 0 "register_operand" "=r") |
967ba98d DE |
4073 | (plus:DI (mult:DI (sign_extend:DI |
4074 | (match_operand:SI 1 "register_operand" "%r")) | |
4075 | (sign_extend:DI | |
4076 | (match_operand:SI 2 "register_operand" "r"))) | |
6d29fc41 | 4077 | (match_operand:DI 3 "register_operand" "0")))] |
967ba98d | 4078 | "TARGET_SPARCLET" |
103fa525 | 4079 | "smacd %1,%2,%L0" |
967ba98d DE |
4080 | [(set_attr "type" "imul")]) |
4081 | ||
4082 | (define_insn "*umacdi" | |
637166fe | 4083 | [(set (match_operand:DI 0 "register_operand" "=r") |
967ba98d DE |
4084 | (plus:DI (mult:DI (zero_extend:DI |
4085 | (match_operand:SI 1 "register_operand" "%r")) | |
4086 | (zero_extend:DI | |
4087 | (match_operand:SI 2 "register_operand" "r"))) | |
6d29fc41 | 4088 | (match_operand:DI 3 "register_operand" "0")))] |
967ba98d | 4089 | "TARGET_SPARCLET" |
103fa525 | 4090 | "umacd %1,%2,%L0" |
967ba98d | 4091 | [(set_attr "type" "imul")]) |
6a4bb1fa DE |
4092 | \f |
4093 | ;;- Boolean instructions | |
967ba98d DE |
4094 | ;; We define DImode `and' so with DImode `not' we can get |
4095 | ;; DImode `andn'. Other combinations are possible. | |
7a768814 RS |
4096 | |
4097 | (define_expand "anddi3" | |
4098 | [(set (match_operand:DI 0 "register_operand" "") | |
4099 | (and:DI (match_operand:DI 1 "arith_double_operand" "") | |
4100 | (match_operand:DI 2 "arith_double_operand" "")))] | |
4101 | "" | |
4102 | "") | |
4103 | ||
c8b3b7d6 | 4104 | (define_insn "*anddi3_sp32" |
7a768814 RS |
4105 | [(set (match_operand:DI 0 "register_operand" "=r") |
4106 | (and:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
4107 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4108 | "! TARGET_ARCH64" |
7a768814 RS |
4109 | "* |
4110 | { | |
4111 | rtx op2 = operands[2]; | |
4112 | ||
103fa525 DE |
4113 | if (GET_CODE (op2) == CONST_INT |
4114 | || GET_CODE (op2) == CONST_DOUBLE) | |
7a768814 | 4115 | { |
ae526227 JW |
4116 | rtx xoperands[4]; |
4117 | xoperands[0] = operands[0]; | |
4118 | xoperands[1] = operands[1]; | |
103fa525 DE |
4119 | if (WORDS_BIG_ENDIAN) |
4120 | split_double (op2, &xoperands[2], &xoperands[3]); | |
4121 | else | |
4122 | split_double (op2, &xoperands[3], &xoperands[2]); | |
4123 | output_asm_insn (\"and %L1,%3,%L0\;and %H1,%2,%H0\", xoperands); | |
ae526227 | 4124 | return \"\"; |
7a768814 RS |
4125 | } |
4126 | return \"and %1,%2,%0\;and %R1,%R2,%R0\"; | |
4127 | }" | |
4128 | [(set_attr "length" "2")]) | |
4129 | ||
c8b3b7d6 | 4130 | (define_insn "*anddi3_sp64" |
a8d2b752 DE |
4131 | [(set (match_operand:DI 0 "register_operand" "=r") |
4132 | (and:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
4133 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4134 | "TARGET_ARCH64" |
a8d2b752 DE |
4135 | "and %1,%2,%0") |
4136 | ||
7a768814 RS |
4137 | (define_insn "andsi3" |
4138 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4139 | (and:SI (match_operand:SI 1 "arith_operand" "%r") | |
4140 | (match_operand:SI 2 "arith_operand" "rI")))] | |
4141 | "" | |
c180bd1e JW |
4142 | "and %1,%2,%0" |
4143 | [(set_attr "type" "ialu")]) | |
7a768814 | 4144 | |
95edfef2 JW |
4145 | (define_split |
4146 | [(set (match_operand:SI 0 "register_operand" "") | |
4147 | (and:SI (match_operand:SI 1 "register_operand" "") | |
5584677e JW |
4148 | (match_operand:SI 2 "" ""))) |
4149 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
95edfef2 JW |
4150 | "GET_CODE (operands[2]) == CONST_INT |
4151 | && !SMALL_INT (operands[2]) | |
4152 | && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" | |
5584677e JW |
4153 | [(set (match_dup 3) (match_dup 4)) |
4154 | (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))] | |
95edfef2 JW |
4155 | " |
4156 | { | |
5d4f5e87 | 4157 | operands[4] = GEN_INT (~INTVAL (operands[2])); |
95edfef2 JW |
4158 | }") |
4159 | ||
c8b3b7d6 | 4160 | (define_insn "*and_not_di_sp32" |
7a768814 RS |
4161 | [(set (match_operand:DI 0 "register_operand" "=r") |
4162 | (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) | |
4163 | (match_operand:DI 2 "register_operand" "r")))] | |
fa0f39e4 | 4164 | "! TARGET_ARCH64" |
7a768814 RS |
4165 | "andn %2,%1,%0\;andn %R2,%R1,%R0" |
4166 | [(set_attr "length" "2")]) | |
4167 | ||
c8b3b7d6 | 4168 | (define_insn "*and_not_di_sp64" |
a8d2b752 DE |
4169 | [(set (match_operand:DI 0 "register_operand" "=r") |
4170 | (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) | |
4171 | (match_operand:DI 2 "register_operand" "r")))] | |
fa0f39e4 | 4172 | "TARGET_ARCH64" |
a8d2b752 DE |
4173 | "andn %2,%1,%0") |
4174 | ||
c8b3b7d6 | 4175 | (define_insn "*and_not_si" |
7a768814 RS |
4176 | [(set (match_operand:SI 0 "register_operand" "=r") |
4177 | (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) | |
4178 | (match_operand:SI 2 "register_operand" "r")))] | |
4179 | "" | |
c180bd1e JW |
4180 | "andn %2,%1,%0" |
4181 | [(set_attr "type" "ialu")]) | |
7a768814 RS |
4182 | |
4183 | (define_expand "iordi3" | |
4184 | [(set (match_operand:DI 0 "register_operand" "") | |
4185 | (ior:DI (match_operand:DI 1 "arith_double_operand" "") | |
4186 | (match_operand:DI 2 "arith_double_operand" "")))] | |
4187 | "" | |
4188 | "") | |
4189 | ||
c8b3b7d6 | 4190 | (define_insn "*iordi3_sp32" |
7a768814 RS |
4191 | [(set (match_operand:DI 0 "register_operand" "=r") |
4192 | (ior:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
4193 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4194 | "! TARGET_ARCH64" |
7a768814 RS |
4195 | "* |
4196 | { | |
4197 | rtx op2 = operands[2]; | |
4198 | ||
103fa525 DE |
4199 | if (GET_CODE (op2) == CONST_INT |
4200 | || GET_CODE (op2) == CONST_DOUBLE) | |
7a768814 | 4201 | { |
ae526227 JW |
4202 | rtx xoperands[4]; |
4203 | xoperands[0] = operands[0]; | |
4204 | xoperands[1] = operands[1]; | |
103fa525 DE |
4205 | if (WORDS_BIG_ENDIAN) |
4206 | split_double (op2, &xoperands[2], &xoperands[3]); | |
4207 | else | |
4208 | split_double (op2, &xoperands[3], &xoperands[2]); | |
4209 | output_asm_insn (\"or %L1,%3,%L0\;or %H1,%2,%H0\", xoperands); | |
ae526227 | 4210 | return \"\"; |
7a768814 RS |
4211 | } |
4212 | return \"or %1,%2,%0\;or %R1,%R2,%R0\"; | |
4213 | }" | |
4214 | [(set_attr "length" "2")]) | |
4215 | ||
c8b3b7d6 | 4216 | (define_insn "*iordi3_sp64" |
a8d2b752 DE |
4217 | [(set (match_operand:DI 0 "register_operand" "=r") |
4218 | (ior:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
4219 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4220 | "TARGET_ARCH64" |
a8d2b752 DE |
4221 | "or %1,%2,%0") |
4222 | ||
7a768814 RS |
4223 | (define_insn "iorsi3" |
4224 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4225 | (ior:SI (match_operand:SI 1 "arith_operand" "%r") | |
4226 | (match_operand:SI 2 "arith_operand" "rI")))] | |
4227 | "" | |
c180bd1e JW |
4228 | "or %1,%2,%0" |
4229 | [(set_attr "type" "ialu")]) | |
7a768814 | 4230 | |
95edfef2 JW |
4231 | (define_split |
4232 | [(set (match_operand:SI 0 "register_operand" "") | |
4233 | (ior:SI (match_operand:SI 1 "register_operand" "") | |
5584677e JW |
4234 | (match_operand:SI 2 "" ""))) |
4235 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
95edfef2 JW |
4236 | "GET_CODE (operands[2]) == CONST_INT |
4237 | && !SMALL_INT (operands[2]) | |
4238 | && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" | |
5584677e JW |
4239 | [(set (match_dup 3) (match_dup 4)) |
4240 | (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))] | |
95edfef2 JW |
4241 | " |
4242 | { | |
5d4f5e87 | 4243 | operands[4] = GEN_INT (~INTVAL (operands[2])); |
95edfef2 JW |
4244 | }") |
4245 | ||
c8b3b7d6 | 4246 | (define_insn "*or_not_di_sp32" |
7a768814 RS |
4247 | [(set (match_operand:DI 0 "register_operand" "=r") |
4248 | (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) | |
4249 | (match_operand:DI 2 "register_operand" "r")))] | |
fa0f39e4 | 4250 | "! TARGET_ARCH64" |
7a768814 RS |
4251 | "orn %2,%1,%0\;orn %R2,%R1,%R0" |
4252 | [(set_attr "length" "2")]) | |
4253 | ||
c8b3b7d6 | 4254 | (define_insn "*or_not_di_sp64" |
a8d2b752 DE |
4255 | [(set (match_operand:DI 0 "register_operand" "=r") |
4256 | (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) | |
4257 | (match_operand:DI 2 "register_operand" "r")))] | |
fa0f39e4 | 4258 | "TARGET_ARCH64" |
a8d2b752 DE |
4259 | "orn %2,%1,%0") |
4260 | ||
c8b3b7d6 | 4261 | (define_insn "*or_not_si" |
7a768814 RS |
4262 | [(set (match_operand:SI 0 "register_operand" "=r") |
4263 | (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r")) | |
4264 | (match_operand:SI 2 "register_operand" "r")))] | |
4265 | "" | |
c180bd1e JW |
4266 | "orn %2,%1,%0" |
4267 | [(set_attr "type" "ialu")]) | |
7a768814 RS |
4268 | |
4269 | (define_expand "xordi3" | |
4270 | [(set (match_operand:DI 0 "register_operand" "") | |
4271 | (xor:DI (match_operand:DI 1 "arith_double_operand" "") | |
4272 | (match_operand:DI 2 "arith_double_operand" "")))] | |
4273 | "" | |
4274 | "") | |
4275 | ||
c8b3b7d6 | 4276 | (define_insn "*xorsi3_sp32" |
7a768814 RS |
4277 | [(set (match_operand:DI 0 "register_operand" "=r") |
4278 | (xor:DI (match_operand:DI 1 "arith_double_operand" "%r") | |
4279 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4280 | "! TARGET_ARCH64" |
7a768814 RS |
4281 | "* |
4282 | { | |
4283 | rtx op2 = operands[2]; | |
4284 | ||
103fa525 DE |
4285 | if (GET_CODE (op2) == CONST_INT |
4286 | || GET_CODE (op2) == CONST_DOUBLE) | |
7a768814 | 4287 | { |
ae526227 JW |
4288 | rtx xoperands[4]; |
4289 | xoperands[0] = operands[0]; | |
4290 | xoperands[1] = operands[1]; | |
103fa525 DE |
4291 | if (WORDS_BIG_ENDIAN) |
4292 | split_double (op2, &xoperands[2], &xoperands[3]); | |
4293 | else | |
4294 | split_double (op2, &xoperands[3], &xoperands[2]); | |
4295 | output_asm_insn (\"xor %L1,%3,%L0\;xor %H1,%2,%H0\", xoperands); | |
ae526227 | 4296 | return \"\"; |
7a768814 RS |
4297 | } |
4298 | return \"xor %1,%2,%0\;xor %R1,%R2,%R0\"; | |
4299 | }" | |
4300 | [(set_attr "length" "2")]) | |
4301 | ||
c8b3b7d6 | 4302 | (define_insn "*xordi3_sp64" |
a8d2b752 DE |
4303 | [(set (match_operand:DI 0 "register_operand" "=r") |
4304 | (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ") | |
4305 | (match_operand:DI 2 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4306 | "TARGET_ARCH64" |
a8d2b752 DE |
4307 | "xor %r1,%2,%0") |
4308 | ||
7a768814 RS |
4309 | (define_insn "xorsi3" |
4310 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4311 | (xor:SI (match_operand:SI 1 "arith_operand" "%rJ") | |
4312 | (match_operand:SI 2 "arith_operand" "rI")))] | |
4313 | "" | |
c180bd1e JW |
4314 | "xor %r1,%2,%0" |
4315 | [(set_attr "type" "ialu")]) | |
7a768814 | 4316 | |
95edfef2 JW |
4317 | (define_split |
4318 | [(set (match_operand:SI 0 "register_operand" "") | |
4319 | (xor:SI (match_operand:SI 1 "register_operand" "") | |
5584677e JW |
4320 | (match_operand:SI 2 "" ""))) |
4321 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
95edfef2 JW |
4322 | "GET_CODE (operands[2]) == CONST_INT |
4323 | && !SMALL_INT (operands[2]) | |
4324 | && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" | |
5584677e JW |
4325 | [(set (match_dup 3) (match_dup 4)) |
4326 | (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))] | |
95edfef2 JW |
4327 | " |
4328 | { | |
5d4f5e87 | 4329 | operands[4] = GEN_INT (~INTVAL (operands[2])); |
95edfef2 JW |
4330 | }") |
4331 | ||
4332 | (define_split | |
4333 | [(set (match_operand:SI 0 "register_operand" "") | |
4334 | (not:SI (xor:SI (match_operand:SI 1 "register_operand" "") | |
5584677e JW |
4335 | (match_operand:SI 2 "" "")))) |
4336 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
95edfef2 JW |
4337 | "GET_CODE (operands[2]) == CONST_INT |
4338 | && !SMALL_INT (operands[2]) | |
4339 | && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" | |
5584677e JW |
4340 | [(set (match_dup 3) (match_dup 4)) |
4341 | (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))] | |
95edfef2 JW |
4342 | " |
4343 | { | |
5d4f5e87 | 4344 | operands[4] = GEN_INT (~INTVAL (operands[2])); |
95edfef2 JW |
4345 | }") |
4346 | ||
7a768814 RS |
4347 | ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b). |
4348 | ;; Combine now canonicalizes to the rightmost expression. | |
c8b3b7d6 | 4349 | (define_insn "*xor_not_di_sp32" |
7a768814 RS |
4350 | [(set (match_operand:DI 0 "register_operand" "=r") |
4351 | (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r") | |
4352 | (match_operand:DI 2 "register_operand" "r"))))] | |
fa0f39e4 | 4353 | "! TARGET_ARCH64" |
7a768814 RS |
4354 | "xnor %1,%2,%0\;xnor %R1,%R2,%R0" |
4355 | [(set_attr "length" "2")]) | |
4356 | ||
c8b3b7d6 | 4357 | (define_insn "*xor_not_di_sp64" |
a8d2b752 DE |
4358 | [(set (match_operand:DI 0 "register_operand" "=r") |
4359 | (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") | |
4360 | (match_operand:DI 2 "arith_double_operand" "rHI"))))] | |
fa0f39e4 | 4361 | "TARGET_ARCH64" |
a8d2b752 DE |
4362 | "xnor %r1,%2,%0") |
4363 | ||
c8b3b7d6 | 4364 | (define_insn "*xor_not_si" |
7a768814 RS |
4365 | [(set (match_operand:SI 0 "register_operand" "=r") |
4366 | (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") | |
4367 | (match_operand:SI 2 "arith_operand" "rI"))))] | |
4368 | "" | |
c180bd1e JW |
4369 | "xnor %r1,%2,%0" |
4370 | [(set_attr "type" "ialu")]) | |
7a768814 RS |
4371 | |
4372 | ;; These correspond to the above in the case where we also (or only) | |
4373 | ;; want to set the condition code. | |
4374 | ||
c8b3b7d6 | 4375 | (define_insn "*cmp_cc_arith_op" |
c4ce6853 | 4376 | [(set (reg:CC 100) |
7a768814 RS |
4377 | (compare:CC |
4378 | (match_operator:SI 2 "cc_arithop" | |
4379 | [(match_operand:SI 0 "arith_operand" "%r") | |
4380 | (match_operand:SI 1 "arith_operand" "rI")]) | |
4381 | (const_int 0)))] | |
4382 | "" | |
4383 | "%A2cc %0,%1,%%g0" | |
4384 | [(set_attr "type" "compare")]) | |
4385 | ||
c8b3b7d6 | 4386 | (define_insn "*cmp_ccx_arith_op" |
c4ce6853 | 4387 | [(set (reg:CCX 100) |
a8d2b752 DE |
4388 | (compare:CCX |
4389 | (match_operator:DI 2 "cc_arithop" | |
4390 | [(match_operand:DI 0 "arith_double_operand" "%r") | |
4391 | (match_operand:DI 1 "arith_double_operand" "rHI")]) | |
4392 | (const_int 0)))] | |
fa0f39e4 | 4393 | "TARGET_ARCH64" |
a8d2b752 DE |
4394 | "%A2cc %0,%1,%%g0" |
4395 | [(set_attr "type" "compare")]) | |
4396 | ||
c8b3b7d6 | 4397 | (define_insn "*cmp_cc_arith_op_set" |
c4ce6853 | 4398 | [(set (reg:CC 100) |
7a768814 RS |
4399 | (compare:CC |
4400 | (match_operator:SI 3 "cc_arithop" | |
4401 | [(match_operand:SI 1 "arith_operand" "%r") | |
4402 | (match_operand:SI 2 "arith_operand" "rI")]) | |
4403 | (const_int 0))) | |
4404 | (set (match_operand:SI 0 "register_operand" "=r") | |
4405 | (match_dup 3))] | |
a8d2b752 DE |
4406 | "" |
4407 | "%A3cc %1,%2,%0") | |
4408 | ||
c8b3b7d6 | 4409 | (define_insn "*cmp_ccx_arith_op_set" |
c4ce6853 | 4410 | [(set (reg:CCX 100) |
a8d2b752 DE |
4411 | (compare:CCX |
4412 | (match_operator:DI 3 "cc_arithop" | |
4413 | [(match_operand:DI 1 "arith_double_operand" "%r") | |
4414 | (match_operand:DI 2 "arith_double_operand" "rHI")]) | |
4415 | (const_int 0))) | |
4416 | (set (match_operand:DI 0 "register_operand" "=r") | |
4417 | (match_dup 3))] | |
fa0f39e4 | 4418 | "TARGET_ARCH64" |
7a768814 RS |
4419 | "%A3cc %1,%2,%0") |
4420 | ||
c8b3b7d6 | 4421 | (define_insn "*cmp_cc_xor_not" |
c4ce6853 | 4422 | [(set (reg:CC 100) |
7a768814 RS |
4423 | (compare:CC |
4424 | (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ") | |
4425 | (match_operand:SI 1 "arith_operand" "rI"))) | |
4426 | (const_int 0)))] | |
4427 | "" | |
4428 | "xnorcc %r0,%1,%%g0" | |
4429 | [(set_attr "type" "compare")]) | |
4430 | ||
c8b3b7d6 | 4431 | (define_insn "*cmp_ccx_xor_not" |
c4ce6853 | 4432 | [(set (reg:CCX 100) |
a8d2b752 DE |
4433 | (compare:CCX |
4434 | (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ") | |
4435 | (match_operand:DI 1 "arith_double_operand" "rHI"))) | |
4436 | (const_int 0)))] | |
fa0f39e4 | 4437 | "TARGET_ARCH64" |
a8d2b752 DE |
4438 | "xnorcc %r0,%1,%%g0" |
4439 | [(set_attr "type" "compare")]) | |
4440 | ||
c8b3b7d6 | 4441 | (define_insn "*cmp_cc_xor_not_set" |
c4ce6853 | 4442 | [(set (reg:CC 100) |
7a768814 RS |
4443 | (compare:CC |
4444 | (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") | |
4445 | (match_operand:SI 2 "arith_operand" "rI"))) | |
4446 | (const_int 0))) | |
4447 | (set (match_operand:SI 0 "register_operand" "=r") | |
4448 | (not:SI (xor:SI (match_dup 1) (match_dup 2))))] | |
4449 | "" | |
4450 | "xnorcc %r1,%2,%0") | |
4451 | ||
c8b3b7d6 | 4452 | (define_insn "*cmp_ccx_xor_not_set" |
c4ce6853 | 4453 | [(set (reg:CCX 100) |
a8d2b752 DE |
4454 | (compare:CCX |
4455 | (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") | |
4456 | (match_operand:DI 2 "arith_double_operand" "rHI"))) | |
4457 | (const_int 0))) | |
4458 | (set (match_operand:DI 0 "register_operand" "=r") | |
4459 | (not:DI (xor:DI (match_dup 1) (match_dup 2))))] | |
fa0f39e4 | 4460 | "TARGET_ARCH64" |
a8d2b752 DE |
4461 | "xnorcc %r1,%2,%0") |
4462 | ||
c8b3b7d6 | 4463 | (define_insn "*cmp_cc_arith_op_not" |
c4ce6853 | 4464 | [(set (reg:CC 100) |
7a768814 RS |
4465 | (compare:CC |
4466 | (match_operator:SI 2 "cc_arithopn" | |
4467 | [(not:SI (match_operand:SI 0 "arith_operand" "rI")) | |
4468 | (match_operand:SI 1 "reg_or_0_operand" "rJ")]) | |
4469 | (const_int 0)))] | |
4470 | "" | |
4471 | "%B2cc %r1,%0,%%g0" | |
4472 | [(set_attr "type" "compare")]) | |
4473 | ||
c8b3b7d6 | 4474 | (define_insn "*cmp_ccx_arith_op_not" |
c4ce6853 | 4475 | [(set (reg:CCX 100) |
a8d2b752 DE |
4476 | (compare:CCX |
4477 | (match_operator:DI 2 "cc_arithopn" | |
4478 | [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI")) | |
4479 | (match_operand:DI 1 "reg_or_0_operand" "rJ")]) | |
4480 | (const_int 0)))] | |
fa0f39e4 | 4481 | "TARGET_ARCH64" |
a8d2b752 DE |
4482 | "%B2cc %r1,%0,%%g0" |
4483 | [(set_attr "type" "compare")]) | |
4484 | ||
c8b3b7d6 | 4485 | (define_insn "*cmp_cc_arith_op_not_set" |
c4ce6853 | 4486 | [(set (reg:CC 100) |
7a768814 RS |
4487 | (compare:CC |
4488 | (match_operator:SI 3 "cc_arithopn" | |
4489 | [(not:SI (match_operand:SI 1 "arith_operand" "rI")) | |
4490 | (match_operand:SI 2 "reg_or_0_operand" "rJ")]) | |
4491 | (const_int 0))) | |
4492 | (set (match_operand:SI 0 "register_operand" "=r") | |
4493 | (match_dup 3))] | |
4494 | "" | |
4495 | "%B3cc %r2,%1,%0") | |
4496 | ||
c8b3b7d6 | 4497 | (define_insn "*cmp_ccx_arith_op_not_set" |
c4ce6853 | 4498 | [(set (reg:CCX 100) |
a8d2b752 DE |
4499 | (compare:CCX |
4500 | (match_operator:DI 3 "cc_arithopn" | |
4501 | [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI")) | |
4502 | (match_operand:DI 2 "reg_or_0_operand" "rJ")]) | |
4503 | (const_int 0))) | |
4504 | (set (match_operand:DI 0 "register_operand" "=r") | |
4505 | (match_dup 3))] | |
fa0f39e4 | 4506 | "TARGET_ARCH64" |
a8d2b752 DE |
4507 | "%B3cc %r2,%1,%0") |
4508 | ||
7a768814 RS |
4509 | ;; We cannot use the "neg" pseudo insn because the Sun assembler |
4510 | ;; does not know how to make it work for constants. | |
4511 | ||
a8d2b752 DE |
4512 | (define_expand "negdi2" |
4513 | [(set (match_operand:DI 0 "register_operand" "=r") | |
4514 | (neg:DI (match_operand:DI 1 "register_operand" "r")))] | |
4515 | "" | |
4516 | " | |
4517 | { | |
fa0f39e4 | 4518 | if (! TARGET_ARCH64) |
a8d2b752 DE |
4519 | { |
4520 | emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, | |
4521 | gen_rtx (SET, VOIDmode, operand0, | |
4522 | gen_rtx (NEG, DImode, operand1)), | |
c4ce6853 DE |
4523 | gen_rtx (CLOBBER, VOIDmode, |
4524 | gen_rtx (REG, SImode, SPARC_ICC_REG))))); | |
a8d2b752 DE |
4525 | DONE; |
4526 | } | |
4527 | }") | |
4528 | ||
c8b3b7d6 | 4529 | (define_insn "*negdi2_sp32" |
7a768814 RS |
4530 | [(set (match_operand:DI 0 "register_operand" "=r") |
4531 | (neg:DI (match_operand:DI 1 "register_operand" "r"))) | |
c4ce6853 | 4532 | (clobber (reg:SI 100))] |
fa0f39e4 | 4533 | "! TARGET_ARCH64" |
c4ce6853 DE |
4534 | "* |
4535 | { | |
4536 | if (TARGET_LIVE_G0) | |
4537 | output_asm_insn (\"and %%g0,0,%%g0\", operands); | |
103fa525 | 4538 | return \"subcc %%g0,%L1,%L0\;subx %%g0,%H1,%H0\"; |
c4ce6853 | 4539 | }" |
7a768814 | 4540 | [(set_attr "type" "unary") |
c4ce6853 | 4541 | ;; ??? This is wrong for TARGET_LIVE_G0 but it's not critical. |
7a768814 RS |
4542 | (set_attr "length" "2")]) |
4543 | ||
c8b3b7d6 | 4544 | (define_insn "*negdi2_sp64" |
a8d2b752 DE |
4545 | [(set (match_operand:DI 0 "register_operand" "=r") |
4546 | (neg:DI (match_operand:DI 1 "register_operand" "r")))] | |
fa0f39e4 | 4547 | "TARGET_ARCH64" |
a8d2b752 DE |
4548 | "sub %%g0,%1,%0" |
4549 | [(set_attr "type" "unary") | |
4550 | (set_attr "length" "1")]) | |
4551 | ||
7a768814 | 4552 | (define_insn "negsi2" |
516422ef | 4553 | [(set (match_operand:SI 0 "register_operand" "=r") |
7a768814 RS |
4554 | (neg:SI (match_operand:SI 1 "arith_operand" "rI")))] |
4555 | "" | |
c4ce6853 DE |
4556 | "* |
4557 | { | |
4558 | if (TARGET_LIVE_G0) | |
4559 | return \"and %%g0,0,%%g0\;sub %%g0,%1,%0\"; | |
4560 | return \"sub %%g0,%1,%0\"; | |
4561 | }" | |
4562 | [(set_attr "type" "unary") | |
4563 | (set (attr "length") | |
4564 | (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1)))]) | |
7a768814 | 4565 | |
c8b3b7d6 | 4566 | (define_insn "*cmp_cc_neg" |
c4ce6853 | 4567 | [(set (reg:CC_NOOV 100) |
7a768814 RS |
4568 | (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI")) |
4569 | (const_int 0)))] | |
c4ce6853 | 4570 | "! TARGET_LIVE_G0" |
7a768814 RS |
4571 | "subcc %%g0,%0,%%g0" |
4572 | [(set_attr "type" "compare")]) | |
4573 | ||
c8b3b7d6 | 4574 | (define_insn "*cmp_ccx_neg" |
c4ce6853 | 4575 | [(set (reg:CCX_NOOV 100) |
a8d2b752 DE |
4576 | (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI")) |
4577 | (const_int 0)))] | |
fa0f39e4 | 4578 | "TARGET_ARCH64" |
a8d2b752 DE |
4579 | "subcc %%g0,%0,%%g0" |
4580 | [(set_attr "type" "compare")]) | |
4581 | ||
c8b3b7d6 | 4582 | (define_insn "*cmp_cc_set_neg" |
c4ce6853 | 4583 | [(set (reg:CC_NOOV 100) |
7a768814 RS |
4584 | (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI")) |
4585 | (const_int 0))) | |
4586 | (set (match_operand:SI 0 "register_operand" "=r") | |
4587 | (neg:SI (match_dup 1)))] | |
c4ce6853 | 4588 | "! TARGET_LIVE_G0" |
7a768814 RS |
4589 | "subcc %%g0,%1,%0" |
4590 | [(set_attr "type" "unary")]) | |
4591 | ||
c8b3b7d6 | 4592 | (define_insn "*cmp_ccx_set_neg" |
c4ce6853 | 4593 | [(set (reg:CCX_NOOV 100) |
a8d2b752 DE |
4594 | (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI")) |
4595 | (const_int 0))) | |
4596 | (set (match_operand:DI 0 "register_operand" "=r") | |
4597 | (neg:DI (match_dup 1)))] | |
fa0f39e4 | 4598 | "TARGET_ARCH64" |
a8d2b752 DE |
4599 | "subcc %%g0,%1,%0" |
4600 | [(set_attr "type" "unary")]) | |
4601 | ||
7a768814 RS |
4602 | ;; We cannot use the "not" pseudo insn because the Sun assembler |
4603 | ;; does not know how to make it work for constants. | |
4604 | (define_expand "one_cmpldi2" | |
ae526227 JW |
4605 | [(set (match_operand:DI 0 "register_operand" "") |
4606 | (not:DI (match_operand:DI 1 "register_operand" "")))] | |
7a768814 RS |
4607 | "" |
4608 | "") | |
4609 | ||
c8b3b7d6 | 4610 | (define_insn "*one_cmpldi2_sp32" |
7a768814 | 4611 | [(set (match_operand:DI 0 "register_operand" "=r") |
ae526227 | 4612 | (not:DI (match_operand:DI 1 "register_operand" "r")))] |
fa0f39e4 | 4613 | "! TARGET_ARCH64" |
c4ce6853 | 4614 | "xnor %1,0,%0\;xnor %R1,0,%R0" |
7a768814 RS |
4615 | [(set_attr "type" "unary") |
4616 | (set_attr "length" "2")]) | |
4617 | ||
c8b3b7d6 | 4618 | (define_insn "*one_cmpldi2_sp64" |
a8d2b752 DE |
4619 | [(set (match_operand:DI 0 "register_operand" "=r") |
4620 | (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))] | |
fa0f39e4 | 4621 | "TARGET_ARCH64" |
c4ce6853 | 4622 | "xnor %1,0,%0" |
a8d2b752 DE |
4623 | [(set_attr "type" "unary")]) |
4624 | ||
7a768814 | 4625 | (define_insn "one_cmplsi2" |
c4ce6853 DE |
4626 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
4627 | (not:SI (match_operand:SI 1 "arith_operand" "r,I")))] | |
7a768814 | 4628 | "" |
c4ce6853 DE |
4629 | "* |
4630 | { | |
4631 | if (which_alternative == 0) | |
4632 | return \"xnor %1,0,%0\"; | |
4633 | if (TARGET_LIVE_G0) | |
4634 | output_asm_insn (\"and %%g0,0,%%g0\", operands); | |
4635 | return \"xnor %%g0,%1,%0\"; | |
4636 | }" | |
4637 | [(set_attr "type" "unary") | |
4638 | (set_attr_alternative "length" | |
4639 | [(const_int 1) | |
4640 | (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1))])]) | |
7a768814 | 4641 | |
c8b3b7d6 | 4642 | (define_insn "*cmp_cc_not" |
c4ce6853 | 4643 | [(set (reg:CC 100) |
7a768814 RS |
4644 | (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI")) |
4645 | (const_int 0)))] | |
c4ce6853 | 4646 | "! TARGET_LIVE_G0" |
7a768814 RS |
4647 | "xnorcc %%g0,%0,%%g0" |
4648 | [(set_attr "type" "compare")]) | |
4649 | ||
c8b3b7d6 | 4650 | (define_insn "*cmp_ccx_not" |
c4ce6853 | 4651 | [(set (reg:CCX 100) |
a8d2b752 DE |
4652 | (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI")) |
4653 | (const_int 0)))] | |
fa0f39e4 | 4654 | "TARGET_ARCH64" |
a8d2b752 DE |
4655 | "xnorcc %%g0,%0,%%g0" |
4656 | [(set_attr "type" "compare")]) | |
4657 | ||
c8b3b7d6 | 4658 | (define_insn "*cmp_cc_set_not" |
c4ce6853 | 4659 | [(set (reg:CC 100) |
7a768814 RS |
4660 | (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI")) |
4661 | (const_int 0))) | |
4662 | (set (match_operand:SI 0 "register_operand" "=r") | |
4663 | (not:SI (match_dup 1)))] | |
c4ce6853 | 4664 | "! TARGET_LIVE_G0" |
7a768814 RS |
4665 | "xnorcc %%g0,%1,%0" |
4666 | [(set_attr "type" "unary")]) | |
a8d2b752 | 4667 | |
c8b3b7d6 | 4668 | (define_insn "*cmp_ccx_set_not" |
c4ce6853 | 4669 | [(set (reg:CCX 100) |
a8d2b752 DE |
4670 | (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")) |
4671 | (const_int 0))) | |
4672 | (set (match_operand:DI 0 "register_operand" "=r") | |
4673 | (not:DI (match_dup 1)))] | |
fa0f39e4 | 4674 | "TARGET_ARCH64" |
a8d2b752 DE |
4675 | "xnorcc %%g0,%1,%0" |
4676 | [(set_attr "type" "unary")]) | |
7a768814 RS |
4677 | \f |
4678 | ;; Floating point arithmetic instructions. | |
4679 | ||
795068a4 | 4680 | (define_insn "addtf3" |
b6d3c4ba JW |
4681 | [(set (match_operand:TF 0 "register_operand" "=e") |
4682 | (plus:TF (match_operand:TF 1 "register_operand" "e") | |
4683 | (match_operand:TF 2 "register_operand" "e")))] | |
ef903eca | 4684 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
4685 | "faddq %1,%2,%0" |
4686 | [(set_attr "type" "fp")]) | |
4687 | ||
7a768814 | 4688 | (define_insn "adddf3" |
b6d3c4ba JW |
4689 | [(set (match_operand:DF 0 "register_operand" "=e") |
4690 | (plus:DF (match_operand:DF 1 "register_operand" "e") | |
4691 | (match_operand:DF 2 "register_operand" "e")))] | |
ab5519b7 | 4692 | "TARGET_FPU" |
7a768814 RS |
4693 | "faddd %1,%2,%0" |
4694 | [(set_attr "type" "fp")]) | |
4695 | ||
4696 | (define_insn "addsf3" | |
4697 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4698 | (plus:SF (match_operand:SF 1 "register_operand" "f") | |
4699 | (match_operand:SF 2 "register_operand" "f")))] | |
ab5519b7 | 4700 | "TARGET_FPU" |
7a768814 RS |
4701 | "fadds %1,%2,%0" |
4702 | [(set_attr "type" "fp")]) | |
4703 | ||
795068a4 | 4704 | (define_insn "subtf3" |
b6d3c4ba JW |
4705 | [(set (match_operand:TF 0 "register_operand" "=e") |
4706 | (minus:TF (match_operand:TF 1 "register_operand" "e") | |
4707 | (match_operand:TF 2 "register_operand" "e")))] | |
ef903eca | 4708 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
4709 | "fsubq %1,%2,%0" |
4710 | [(set_attr "type" "fp")]) | |
4711 | ||
7a768814 | 4712 | (define_insn "subdf3" |
b6d3c4ba JW |
4713 | [(set (match_operand:DF 0 "register_operand" "=e") |
4714 | (minus:DF (match_operand:DF 1 "register_operand" "e") | |
4715 | (match_operand:DF 2 "register_operand" "e")))] | |
ab5519b7 | 4716 | "TARGET_FPU" |
7a768814 RS |
4717 | "fsubd %1,%2,%0" |
4718 | [(set_attr "type" "fp")]) | |
4719 | ||
4720 | (define_insn "subsf3" | |
4721 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4722 | (minus:SF (match_operand:SF 1 "register_operand" "f") | |
4723 | (match_operand:SF 2 "register_operand" "f")))] | |
ab5519b7 | 4724 | "TARGET_FPU" |
7a768814 RS |
4725 | "fsubs %1,%2,%0" |
4726 | [(set_attr "type" "fp")]) | |
4727 | ||
795068a4 | 4728 | (define_insn "multf3" |
b6d3c4ba JW |
4729 | [(set (match_operand:TF 0 "register_operand" "=e") |
4730 | (mult:TF (match_operand:TF 1 "register_operand" "e") | |
4731 | (match_operand:TF 2 "register_operand" "e")))] | |
ef903eca | 4732 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
4733 | "fmulq %1,%2,%0" |
4734 | [(set_attr "type" "fpmul")]) | |
4735 | ||
7a768814 | 4736 | (define_insn "muldf3" |
b6d3c4ba JW |
4737 | [(set (match_operand:DF 0 "register_operand" "=e") |
4738 | (mult:DF (match_operand:DF 1 "register_operand" "e") | |
4739 | (match_operand:DF 2 "register_operand" "e")))] | |
ab5519b7 | 4740 | "TARGET_FPU" |
7a768814 RS |
4741 | "fmuld %1,%2,%0" |
4742 | [(set_attr "type" "fpmul")]) | |
4743 | ||
4744 | (define_insn "mulsf3" | |
4745 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4746 | (mult:SF (match_operand:SF 1 "register_operand" "f") | |
4747 | (match_operand:SF 2 "register_operand" "f")))] | |
ab5519b7 | 4748 | "TARGET_FPU" |
7a768814 RS |
4749 | "fmuls %1,%2,%0" |
4750 | [(set_attr "type" "fpmul")]) | |
4751 | ||
c8b3b7d6 | 4752 | (define_insn "*muldf3_extend" |
b6d3c4ba | 4753 | [(set (match_operand:DF 0 "register_operand" "=e") |
8d2f4374 JW |
4754 | (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f")) |
4755 | (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))] | |
a8d2b752 | 4756 | "(TARGET_V8 || TARGET_V9) && TARGET_FPU" |
8d2f4374 JW |
4757 | "fsmuld %1,%2,%0" |
4758 | [(set_attr "type" "fpmul")]) | |
4759 | ||
c8b3b7d6 | 4760 | (define_insn "*multf3_extend" |
b6d3c4ba JW |
4761 | [(set (match_operand:TF 0 "register_operand" "=e") |
4762 | (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e")) | |
4763 | (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))] | |
fa0f39e4 | 4764 | "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD" |
8d2f4374 JW |
4765 | "fdmulq %1,%2,%0" |
4766 | [(set_attr "type" "fpmul")]) | |
4767 | ||
c180bd1e | 4768 | ;; don't have timing for quad-prec. divide. |
795068a4 | 4769 | (define_insn "divtf3" |
b6d3c4ba JW |
4770 | [(set (match_operand:TF 0 "register_operand" "=e") |
4771 | (div:TF (match_operand:TF 1 "register_operand" "e") | |
4772 | (match_operand:TF 2 "register_operand" "e")))] | |
ef903eca | 4773 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 | 4774 | "fdivq %1,%2,%0" |
c180bd1e | 4775 | [(set_attr "type" "fpdivd")]) |
795068a4 | 4776 | |
7a768814 | 4777 | (define_insn "divdf3" |
b6d3c4ba JW |
4778 | [(set (match_operand:DF 0 "register_operand" "=e") |
4779 | (div:DF (match_operand:DF 1 "register_operand" "e") | |
4780 | (match_operand:DF 2 "register_operand" "e")))] | |
ab5519b7 | 4781 | "TARGET_FPU" |
7a768814 | 4782 | "fdivd %1,%2,%0" |
c180bd1e | 4783 | [(set_attr "type" "fpdivd")]) |
7a768814 RS |
4784 | |
4785 | (define_insn "divsf3" | |
4786 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4787 | (div:SF (match_operand:SF 1 "register_operand" "f") | |
4788 | (match_operand:SF 2 "register_operand" "f")))] | |
ab5519b7 | 4789 | "TARGET_FPU" |
7a768814 | 4790 | "fdivs %1,%2,%0" |
c180bd1e | 4791 | [(set_attr "type" "fpdivs")]) |
7a768814 | 4792 | |
795068a4 | 4793 | (define_insn "negtf2" |
b6d3c4ba JW |
4794 | [(set (match_operand:TF 0 "register_operand" "=e,e") |
4795 | (neg:TF (match_operand:TF 1 "register_operand" "0,e")))] | |
49a7ec10 | 4796 | ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD. |
ab5519b7 | 4797 | "TARGET_FPU" |
a8d2b752 DE |
4798 | "* |
4799 | { | |
49a7ec10 DE |
4800 | /* v9: can't use fnegs, won't work with upper regs. */ |
4801 | if (which_alternative == 0) | |
4802 | return TARGET_V9 ? \"fnegd %0,%0\" : \"fnegs %0,%0\"; | |
a8d2b752 | 4803 | else |
49a7ec10 DE |
4804 | return TARGET_V9 ? \"fnegd %1,%0\;fmovd %S1,%S0\" |
4805 | : \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\"; | |
a8d2b752 | 4806 | }" |
795068a4 | 4807 | [(set_attr "type" "fp") |
a8d2b752 DE |
4808 | (set_attr_alternative "length" |
4809 | [(const_int 1) | |
49a7ec10 | 4810 | (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])]) |
795068a4 | 4811 | |
7a768814 | 4812 | (define_insn "negdf2" |
b6d3c4ba JW |
4813 | [(set (match_operand:DF 0 "register_operand" "=e,e") |
4814 | (neg:DF (match_operand:DF 1 "register_operand" "0,e")))] | |
ab5519b7 | 4815 | "TARGET_FPU" |
a8d2b752 DE |
4816 | "* |
4817 | { | |
4818 | if (TARGET_V9) | |
4819 | return \"fnegd %1,%0\"; | |
4820 | else if (which_alternative == 0) | |
4821 | return \"fnegs %0,%0\"; | |
4822 | else | |
4823 | return \"fnegs %1,%0\;fmovs %R1,%R0\"; | |
4824 | }" | |
7a768814 | 4825 | [(set_attr "type" "fp") |
a8d2b752 DE |
4826 | (set_attr_alternative "length" |
4827 | [(const_int 1) | |
0f1f080e | 4828 | (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])]) |
7a768814 | 4829 | |
7a768814 RS |
4830 | (define_insn "negsf2" |
4831 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4832 | (neg:SF (match_operand:SF 1 "register_operand" "f")))] | |
ab5519b7 | 4833 | "TARGET_FPU" |
7a768814 RS |
4834 | "fnegs %1,%0" |
4835 | [(set_attr "type" "fp")]) | |
4836 | ||
795068a4 | 4837 | (define_insn "abstf2" |
b6d3c4ba JW |
4838 | [(set (match_operand:TF 0 "register_operand" "=e,e") |
4839 | (abs:TF (match_operand:TF 1 "register_operand" "0,e")))] | |
49a7ec10 | 4840 | ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD. |
ab5519b7 | 4841 | "TARGET_FPU" |
a8d2b752 DE |
4842 | "* |
4843 | { | |
49a7ec10 DE |
4844 | /* v9: can't use fabss, won't work with upper regs. */ |
4845 | if (which_alternative == 0) | |
4846 | return TARGET_V9 ? \"fabsd %0,%0\" : \"fabss %0,%0\"; | |
a8d2b752 | 4847 | else |
49a7ec10 DE |
4848 | return TARGET_V9 ? \"fabsd %1,%0\;fmovd %S1,%S0\" |
4849 | : \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\"; | |
a8d2b752 | 4850 | }" |
795068a4 | 4851 | [(set_attr "type" "fp") |
a8d2b752 DE |
4852 | (set_attr_alternative "length" |
4853 | [(const_int 1) | |
49a7ec10 | 4854 | (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])]) |
795068a4 | 4855 | |
7a768814 | 4856 | (define_insn "absdf2" |
b6d3c4ba JW |
4857 | [(set (match_operand:DF 0 "register_operand" "=e,e") |
4858 | (abs:DF (match_operand:DF 1 "register_operand" "0,e")))] | |
ab5519b7 | 4859 | "TARGET_FPU" |
a8d2b752 DE |
4860 | "* |
4861 | { | |
4862 | if (TARGET_V9) | |
4863 | return \"fabsd %1,%0\"; | |
4864 | else if (which_alternative == 0) | |
4865 | return \"fabss %0,%0\"; | |
4866 | else | |
4867 | return \"fabss %1,%0\;fmovs %R1,%R0\"; | |
4868 | }" | |
7a768814 | 4869 | [(set_attr "type" "fp") |
a8d2b752 DE |
4870 | (set_attr_alternative "length" |
4871 | [(const_int 1) | |
0f1f080e | 4872 | (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])]) |
7a768814 RS |
4873 | |
4874 | (define_insn "abssf2" | |
4875 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4876 | (abs:SF (match_operand:SF 1 "register_operand" "f")))] | |
ab5519b7 | 4877 | "TARGET_FPU" |
7a768814 RS |
4878 | "fabss %1,%0" |
4879 | [(set_attr "type" "fp")]) | |
4880 | ||
795068a4 | 4881 | (define_insn "sqrttf2" |
b6d3c4ba JW |
4882 | [(set (match_operand:TF 0 "register_operand" "=e") |
4883 | (sqrt:TF (match_operand:TF 1 "register_operand" "e")))] | |
ef903eca | 4884 | "TARGET_FPU && TARGET_HARD_QUAD" |
795068a4 JW |
4885 | "fsqrtq %1,%0" |
4886 | [(set_attr "type" "fpsqrt")]) | |
4887 | ||
7a768814 | 4888 | (define_insn "sqrtdf2" |
b6d3c4ba JW |
4889 | [(set (match_operand:DF 0 "register_operand" "=e") |
4890 | (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] | |
ab5519b7 | 4891 | "TARGET_FPU" |
7a768814 RS |
4892 | "fsqrtd %1,%0" |
4893 | [(set_attr "type" "fpsqrt")]) | |
4894 | ||
4895 | (define_insn "sqrtsf2" | |
4896 | [(set (match_operand:SF 0 "register_operand" "=f") | |
4897 | (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] | |
ab5519b7 | 4898 | "TARGET_FPU" |
7a768814 RS |
4899 | "fsqrts %1,%0" |
4900 | [(set_attr "type" "fpsqrt")]) | |
4901 | \f | |
4902 | ;;- arithmetic shift instructions | |
4903 | ||
7a768814 RS |
4904 | (define_insn "ashlsi3" |
4905 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4906 | (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
0088e8ba | 4907 | (match_operand:SI 2 "arith_operand" "rI")))] |
7a768814 | 4908 | "" |
0088e8ba RK |
4909 | "* |
4910 | { | |
4911 | if (GET_CODE (operands[2]) == CONST_INT | |
5d4f5e87 | 4912 | && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) |
0088e8ba RK |
4913 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
4914 | ||
4915 | return \"sll %1,%2,%0\"; | |
c180bd1e JW |
4916 | }" |
4917 | [(set_attr "type" "shift")]) | |
7a768814 | 4918 | |
a8d2b752 DE |
4919 | (define_insn "ashldi3" |
4920 | [(set (match_operand:DI 0 "register_operand" "=r") | |
4921 | (ashift:DI (match_operand:DI 1 "register_operand" "r") | |
4922 | (match_operand:SI 2 "arith_operand" "rI")))] | |
fa0f39e4 | 4923 | "TARGET_ARCH64" |
a8d2b752 DE |
4924 | "* |
4925 | { | |
4926 | if (GET_CODE (operands[2]) == CONST_INT | |
5d4f5e87 | 4927 | && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) |
a8d2b752 DE |
4928 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); |
4929 | ||
4930 | return \"sllx %1,%2,%0\"; | |
4931 | }") | |
4932 | ||
c8b3b7d6 | 4933 | (define_insn "*cmp_cc_ashift_1" |
c4ce6853 | 4934 | [(set (reg:CC_NOOV 100) |
13a7eb33 JW |
4935 | (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r") |
4936 | (const_int 1)) | |
4937 | (const_int 0)))] | |
4938 | "" | |
4939 | "addcc %0,%0,%%g0" | |
4940 | [(set_attr "type" "compare")]) | |
4941 | ||
c8b3b7d6 | 4942 | (define_insn "*cmp_cc_set_ashift_1" |
c4ce6853 | 4943 | [(set (reg:CC_NOOV 100) |
13a7eb33 JW |
4944 | (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r") |
4945 | (const_int 1)) | |
4946 | (const_int 0))) | |
4947 | (set (match_operand:SI 0 "register_operand" "=r") | |
4948 | (ashift:SI (match_dup 1) (const_int 1)))] | |
4949 | "" | |
4950 | "addcc %1,%1,%0") | |
4951 | ||
7a768814 RS |
4952 | (define_insn "ashrsi3" |
4953 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4954 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
0088e8ba | 4955 | (match_operand:SI 2 "arith_operand" "rI")))] |
7a768814 | 4956 | "" |
0088e8ba RK |
4957 | "* |
4958 | { | |
4959 | if (GET_CODE (operands[2]) == CONST_INT | |
5d4f5e87 | 4960 | && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) |
0088e8ba RK |
4961 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
4962 | ||
4963 | return \"sra %1,%2,%0\"; | |
c180bd1e JW |
4964 | }" |
4965 | [(set_attr "type" "shift")]) | |
7a768814 | 4966 | |
a8d2b752 DE |
4967 | (define_insn "ashrdi3" |
4968 | [(set (match_operand:DI 0 "register_operand" "=r") | |
4969 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") | |
4970 | (match_operand:SI 2 "arith_operand" "rI")))] | |
fa0f39e4 | 4971 | "TARGET_ARCH64" |
a8d2b752 DE |
4972 | "* |
4973 | { | |
4974 | if (GET_CODE (operands[2]) == CONST_INT | |
5d4f5e87 | 4975 | && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63) |
a8d2b752 DE |
4976 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); |
4977 | ||
4978 | return \"srax %1,%2,%0\"; | |
4979 | }") | |
4980 | ||
7a768814 RS |
4981 | (define_insn "lshrsi3" |
4982 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4983 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
0088e8ba | 4984 | (match_operand:SI 2 "arith_operand" "rI")))] |
7a768814 | 4985 | "" |
0088e8ba RK |
4986 | "* |
4987 | { | |
4988 | if (GET_CODE (operands[2]) == CONST_INT | |
5d4f5e87 | 4989 | && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31) |
0088e8ba RK |
4990 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
4991 | ||
4992 | return \"srl %1,%2,%0\"; | |
c180bd1e JW |
4993 | }" |
4994 | [(set_attr "type" "shift")]) | |
a8d2b752 DE |
4995 | |
4996 | (define_insn "lshrdi3" | |
4997 | [(set (match_operand:DI 0 "register_operand" "=r") | |
4998 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") | |
4999 | (match_operand:SI 2 "arith_operand" "rI")))] | |
fa0f39e4 | 5000 | "TARGET_ARCH64" |
a8d2b752 DE |
5001 | "* |
5002 | { | |
5003 | if (GET_CODE (operands[2]) == CONST_INT | |
5d4f5e87 | 5004 | && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63) |
a8d2b752 DE |
5005 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); |
5006 | ||
5007 | return \"srlx %1,%2,%0\"; | |
5008 | }") | |
7a768814 RS |
5009 | \f |
5010 | ;; Unconditional and other jump instructions | |
c5791d70 JW |
5011 | ;; On the Sparc, by setting the annul bit on an unconditional branch, the |
5012 | ;; following insn is never executed. This saves us a nop. Dbx does not | |
5013 | ;; handle such branches though, so we only use them when optimizing. | |
7a768814 RS |
5014 | (define_insn "jump" |
5015 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
5016 | "" | |
8dcb5295 RH |
5017 | "* |
5018 | { | |
5019 | /* Some implementations are reported to have problems with | |
5020 | foo: b,a foo | |
5021 | i.e. an empty loop with the annul bit set. The workaround is to use | |
5022 | foo: b foo; nop | |
5023 | instead. */ | |
5024 | ||
5025 | if (flag_delayed_branch | |
5026 | && (insn_addresses[INSN_UID (operands[0])] | |
5027 | == insn_addresses[INSN_UID (insn)])) | |
5028 | return \"b %l0%#\"; | |
5029 | else | |
5030 | return \"b%* %l0%(\"; | |
5031 | }" | |
e8d6096c | 5032 | [(set_attr "type" "uncond_branch")]) |
7a768814 RS |
5033 | |
5034 | (define_expand "tablejump" | |
a8d2b752 | 5035 | [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) |
7a768814 | 5036 | (use (label_ref (match_operand 1 "" "")))])] |
95726648 | 5037 | "" |
7a768814 RS |
5038 | " |
5039 | { | |
a8d2b752 DE |
5040 | if (GET_MODE (operands[0]) != Pmode) |
5041 | abort (); | |
5042 | ||
7a768814 RS |
5043 | /* We need to use the PC value in %o7 that was set up when the address |
5044 | of the label was loaded into a register, so we need different RTL. */ | |
5045 | if (flag_pic) | |
5046 | { | |
a8d2b752 DE |
5047 | if (!TARGET_PTR64) |
5048 | emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1])); | |
5049 | else | |
5050 | emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1])); | |
7a768814 RS |
5051 | DONE; |
5052 | } | |
5053 | }") | |
5054 | ||
a8d2b752 | 5055 | (define_insn "pic_tablejump_32" |
7a768814 RS |
5056 | [(set (pc) (match_operand:SI 0 "register_operand" "r")) |
5057 | (use (label_ref (match_operand 1 "" ""))) | |
5058 | (use (reg:SI 15))] | |
a8d2b752 DE |
5059 | "! TARGET_PTR64" |
5060 | "jmp %%o7+%0%#" | |
5061 | [(set_attr "type" "uncond_branch")]) | |
5062 | ||
5063 | (define_insn "pic_tablejump_64" | |
5064 | [(set (pc) (match_operand:DI 0 "register_operand" "r")) | |
5065 | (use (label_ref (match_operand 1 "" ""))) | |
5066 | (use (reg:DI 15))] | |
5067 | "TARGET_PTR64" | |
7a768814 | 5068 | "jmp %%o7+%0%#" |
e8d6096c | 5069 | [(set_attr "type" "uncond_branch")]) |
7a768814 | 5070 | |
c8b3b7d6 | 5071 | (define_insn "*tablejump_sp32" |
7a768814 RS |
5072 | [(set (pc) (match_operand:SI 0 "address_operand" "p")) |
5073 | (use (label_ref (match_operand 1 "" "")))] | |
a8d2b752 DE |
5074 | "! TARGET_PTR64" |
5075 | "jmp %a0%#" | |
5076 | [(set_attr "type" "uncond_branch")]) | |
5077 | ||
c8b3b7d6 | 5078 | (define_insn "*tablejump_sp64" |
a8d2b752 DE |
5079 | [(set (pc) (match_operand:DI 0 "address_operand" "p")) |
5080 | (use (label_ref (match_operand 1 "" "")))] | |
5081 | "TARGET_PTR64" | |
7a768814 | 5082 | "jmp %a0%#" |
e8d6096c | 5083 | [(set_attr "type" "uncond_branch")]) |
7a768814 | 5084 | |
7a768814 RS |
5085 | ;; This pattern recognizes the "instruction" that appears in |
5086 | ;; a function call that wants a structure value, | |
5087 | ;; to inform the called function if compiled with Sun CC. | |
c8b3b7d6 | 5088 | ;(define_insn "*unimp_insn" |
7a768814 RS |
5089 | ; [(match_operand:SI 0 "immediate_operand" "")] |
5090 | ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0" | |
5091 | ; "unimp %0" | |
5092 | ; [(set_attr "type" "marker")]) | |
5093 | ||
5094 | ;;- jump to subroutine | |
5095 | (define_expand "call" | |
5096 | ;; Note that this expression is not used for generating RTL. | |
5097 | ;; All the RTL is generated explicitly below. | |
a8d2b752 | 5098 | [(call (match_operand 0 "call_operand" "") |
7a768814 RS |
5099 | (match_operand 3 "" "i"))] |
5100 | ;; operands[2] is next_arg_register | |
5101 | ;; operands[3] is struct_value_size_rtx. | |
5102 | "" | |
5103 | " | |
5104 | { | |
5105 | rtx fn_rtx, nregs_rtx; | |
5106 | ||
a8d2b752 DE |
5107 | if (GET_MODE (operands[0]) != FUNCTION_MODE) |
5108 | abort (); | |
5109 | ||
60801f0b | 5110 | if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF) |
7a768814 RS |
5111 | { |
5112 | /* This is really a PIC sequence. We want to represent | |
5113 | it as a funny jump so it's delay slots can be filled. | |
5114 | ||
5115 | ??? But if this really *is* a CALL, will not it clobber the | |
5116 | call-clobbered registers? We lose this if it is a JUMP_INSN. | |
5117 | Why cannot we have delay slots filled if it were a CALL? */ | |
5118 | ||
fa0f39e4 | 5119 | if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0) |
60801f0b RK |
5120 | emit_jump_insn |
5121 | (gen_rtx (PARALLEL, VOIDmode, | |
5122 | gen_rtvec (3, | |
5123 | gen_rtx (SET, VOIDmode, pc_rtx, | |
5124 | XEXP (operands[0], 0)), | |
5125 | GEN_INT (INTVAL (operands[3]) & 0xfff), | |
5126 | gen_rtx (CLOBBER, VOIDmode, | |
5127 | gen_rtx (REG, Pmode, 15))))); | |
7a768814 | 5128 | else |
60801f0b RK |
5129 | emit_jump_insn |
5130 | (gen_rtx (PARALLEL, VOIDmode, | |
5131 | gen_rtvec (2, | |
5132 | gen_rtx (SET, VOIDmode, pc_rtx, | |
5133 | XEXP (operands[0], 0)), | |
5134 | gen_rtx (CLOBBER, VOIDmode, | |
5135 | gen_rtx (REG, Pmode, 15))))); | |
7a768814 RS |
5136 | goto finish_call; |
5137 | } | |
5138 | ||
5139 | fn_rtx = operands[0]; | |
5140 | ||
5141 | /* Count the number of parameter registers being used by this call. | |
5142 | if that argument is NULL, it means we are using them all, which | |
5143 | means 6 on the sparc. */ | |
5144 | #if 0 | |
5145 | if (operands[2]) | |
5d4f5e87 | 5146 | nregs_rtx = GEN_INT (REGNO (operands[2]) - 8); |
7a768814 | 5147 | else |
5d4f5e87 | 5148 | nregs_rtx = GEN_INT (6); |
7a768814 RS |
5149 | #else |
5150 | nregs_rtx = const0_rtx; | |
5151 | #endif | |
5152 | ||
fa0f39e4 | 5153 | if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0) |
60801f0b RK |
5154 | emit_call_insn |
5155 | (gen_rtx (PARALLEL, VOIDmode, | |
5156 | gen_rtvec (3, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), | |
5157 | GEN_INT (INTVAL (operands[3]) & 0xfff), | |
5158 | gen_rtx (CLOBBER, VOIDmode, | |
5159 | gen_rtx (REG, Pmode, 15))))); | |
7a768814 | 5160 | else |
60801f0b RK |
5161 | emit_call_insn |
5162 | (gen_rtx (PARALLEL, VOIDmode, | |
5163 | gen_rtvec (2, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx), | |
5164 | gen_rtx (CLOBBER, VOIDmode, | |
5165 | gen_rtx (REG, Pmode, 15))))); | |
7a768814 RS |
5166 | |
5167 | finish_call: | |
5168 | #if 0 | |
5169 | /* If this call wants a structure value, | |
5170 | emit an unimp insn to let the called function know about this. */ | |
fa0f39e4 | 5171 | if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0) |
7a768814 RS |
5172 | { |
5173 | rtx insn = emit_insn (operands[3]); | |
5174 | SCHED_GROUP_P (insn) = 1; | |
5175 | } | |
5176 | #endif | |
5177 | ||
5178 | DONE; | |
5179 | }") | |
5180 | ||
bf97b967 JW |
5181 | ;; We can't use the same pattern for these two insns, because then registers |
5182 | ;; in the address may not be properly reloaded. | |
5183 | ||
c8b3b7d6 | 5184 | (define_insn "*call_address_sp32" |
bf97b967 JW |
5185 | [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) |
5186 | (match_operand 1 "" "")) | |
5187 | (clobber (reg:SI 15))] | |
5188 | ;;- Do not use operand 1 for most machines. | |
a8d2b752 | 5189 | "! TARGET_PTR64" |
d0511997 | 5190 | "call %a0,%1%#" |
bf97b967 JW |
5191 | [(set_attr "type" "call")]) |
5192 | ||
c8b3b7d6 | 5193 | (define_insn "*call_symbolic_sp32" |
2c435002 | 5194 | [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) |
7a768814 RS |
5195 | (match_operand 1 "" "")) |
5196 | (clobber (reg:SI 15))] | |
5197 | ;;- Do not use operand 1 for most machines. | |
a8d2b752 | 5198 | "! TARGET_PTR64" |
d0511997 | 5199 | "call %a0,%1%#" |
a8d2b752 DE |
5200 | [(set_attr "type" "call")]) |
5201 | ||
c8b3b7d6 | 5202 | (define_insn "*call_address_sp64" |
a8d2b752 DE |
5203 | [(call (mem:SI (match_operand:DI 0 "address_operand" "p")) |
5204 | (match_operand 1 "" "")) | |
5205 | (clobber (reg:DI 15))] | |
5206 | ;;- Do not use operand 1 for most machines. | |
5207 | "TARGET_PTR64" | |
d0511997 | 5208 | "call %a0,%1%#" |
a8d2b752 DE |
5209 | [(set_attr "type" "call")]) |
5210 | ||
c8b3b7d6 | 5211 | (define_insn "*call_symbolic_sp64" |
2c435002 | 5212 | [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s")) |
a8d2b752 DE |
5213 | (match_operand 1 "" "")) |
5214 | (clobber (reg:DI 15))] | |
5215 | ;;- Do not use operand 1 for most machines. | |
5216 | "TARGET_PTR64" | |
d0511997 | 5217 | "call %a0,%1%#" |
7a768814 RS |
5218 | [(set_attr "type" "call")]) |
5219 | ||
5220 | ;; This is a call that wants a structure value. | |
a8d2b752 | 5221 | ;; There is no such critter for v9 (??? we may need one anyway). |
c8b3b7d6 | 5222 | (define_insn "*call_address_struct_value_sp32" |
bf97b967 JW |
5223 | [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) |
5224 | (match_operand 1 "" "")) | |
5225 | (match_operand 2 "immediate_operand" "") | |
5226 | (clobber (reg:SI 15))] | |
5227 | ;;- Do not use operand 1 for most machines. | |
7d49f59f | 5228 | "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0" |
d0511997 | 5229 | "call %a0,%1\;nop\;unimp %2" |
bf97b967 JW |
5230 | [(set_attr "type" "call_no_delay_slot")]) |
5231 | ||
5232 | ;; This is a call that wants a structure value. | |
a8d2b752 | 5233 | ;; There is no such critter for v9 (??? we may need one anyway). |
c8b3b7d6 | 5234 | (define_insn "*call_symbolic_struct_value_sp32" |
2c435002 | 5235 | [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) |
7a768814 RS |
5236 | (match_operand 1 "" "")) |
5237 | (match_operand 2 "immediate_operand" "") | |
5238 | (clobber (reg:SI 15))] | |
5239 | ;;- Do not use operand 1 for most machines. | |
7d49f59f | 5240 | "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0" |
d0511997 | 5241 | "call %a0,%1\;nop\;unimp %2" |
7a768814 RS |
5242 | [(set_attr "type" "call_no_delay_slot")]) |
5243 | ||
d18d5ca2 JW |
5244 | ;; This is a call that may want a structure value. This is used for |
5245 | ;; untyped_calls. | |
c8b3b7d6 | 5246 | (define_insn "*call_address_untyped_struct_value_sp32" |
d18d5ca2 JW |
5247 | [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) |
5248 | (match_operand 1 "" "")) | |
5249 | (match_operand 2 "immediate_operand" "") | |
5250 | (clobber (reg:SI 15))] | |
5251 | ;;- Do not use operand 1 for most machines. | |
fa0f39e4 | 5252 | "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0" |
d0511997 | 5253 | "call %a0,%1\;nop\;nop" |
d18d5ca2 JW |
5254 | [(set_attr "type" "call_no_delay_slot")]) |
5255 | ||
5256 | ;; This is a call that wants a structure value. | |
c8b3b7d6 | 5257 | (define_insn "*call_symbolic_untyped_struct_value_sp32" |
d18d5ca2 JW |
5258 | [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s")) |
5259 | (match_operand 1 "" "")) | |
5260 | (match_operand 2 "immediate_operand" "") | |
5261 | (clobber (reg:SI 15))] | |
5262 | ;;- Do not use operand 1 for most machines. | |
fa0f39e4 | 5263 | "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0" |
d0511997 | 5264 | "call %a0,%1\;nop\;nop" |
d18d5ca2 JW |
5265 | [(set_attr "type" "call_no_delay_slot")]) |
5266 | ||
7a768814 | 5267 | (define_expand "call_value" |
a8d2b752 DE |
5268 | ;; Note that this expression is not used for generating RTL. |
5269 | ;; All the RTL is generated explicitly below. | |
7a768814 RS |
5270 | [(set (match_operand 0 "register_operand" "=rf") |
5271 | (call (match_operand:SI 1 "" "") | |
5272 | (match_operand 4 "" "")))] | |
a8d2b752 | 5273 | ;; operand 2 is stack_size_rtx |
7a768814 RS |
5274 | ;; operand 3 is next_arg_register |
5275 | "" | |
5276 | " | |
5277 | { | |
5278 | rtx fn_rtx, nregs_rtx; | |
5279 | rtvec vec; | |
5280 | ||
a8d2b752 DE |
5281 | if (GET_MODE (operands[1]) != FUNCTION_MODE) |
5282 | abort (); | |
5283 | ||
7a768814 RS |
5284 | fn_rtx = operands[1]; |
5285 | ||
5286 | #if 0 | |
5287 | if (operands[3]) | |
5288 | nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8); | |
5289 | else | |
5290 | nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6); | |
5291 | #else | |
5292 | nregs_rtx = const0_rtx; | |
5293 | #endif | |
5294 | ||
5295 | vec = gen_rtvec (2, | |
5296 | gen_rtx (SET, VOIDmode, operands[0], | |
5297 | gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)), | |
a8d2b752 | 5298 | gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 15))); |
7a768814 RS |
5299 | |
5300 | emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec)); | |
5301 | ||
5302 | DONE; | |
5303 | }") | |
5304 | ||
c8b3b7d6 | 5305 | (define_insn "*call_value_address_sp32" |
7a768814 | 5306 | [(set (match_operand 0 "" "=rf") |
bf97b967 JW |
5307 | (call (mem:SI (match_operand:SI 1 "address_operand" "p")) |
5308 | (match_operand 2 "" ""))) | |
5309 | (clobber (reg:SI 15))] | |
5310 | ;;- Do not use operand 2 for most machines. | |
a8d2b752 | 5311 | "! TARGET_PTR64" |
d0511997 | 5312 | "call %a1,%2%#" |
bf97b967 JW |
5313 | [(set_attr "type" "call")]) |
5314 | ||
c8b3b7d6 | 5315 | (define_insn "*call_value_symbolic_sp32" |
bf97b967 | 5316 | [(set (match_operand 0 "" "=rf") |
2c435002 | 5317 | (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s")) |
7a768814 RS |
5318 | (match_operand 2 "" ""))) |
5319 | (clobber (reg:SI 15))] | |
5320 | ;;- Do not use operand 2 for most machines. | |
a8d2b752 | 5321 | "! TARGET_PTR64" |
d0511997 | 5322 | "call %a1,%2%#" |
a8d2b752 DE |
5323 | [(set_attr "type" "call")]) |
5324 | ||
c8b3b7d6 | 5325 | (define_insn "*call_value_address_sp64" |
a8d2b752 DE |
5326 | [(set (match_operand 0 "" "=rf") |
5327 | (call (mem:SI (match_operand:DI 1 "address_operand" "p")) | |
5328 | (match_operand 2 "" ""))) | |
5329 | (clobber (reg:DI 15))] | |
5330 | ;;- Do not use operand 2 for most machines. | |
5331 | "TARGET_PTR64" | |
d0511997 | 5332 | "call %a1,%2%#" |
a8d2b752 DE |
5333 | [(set_attr "type" "call")]) |
5334 | ||
c8b3b7d6 | 5335 | (define_insn "*call_value_symbolic_sp64" |
a8d2b752 | 5336 | [(set (match_operand 0 "" "=rf") |
2c435002 | 5337 | (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s")) |
a8d2b752 DE |
5338 | (match_operand 2 "" ""))) |
5339 | (clobber (reg:DI 15))] | |
5340 | ;;- Do not use operand 2 for most machines. | |
5341 | "TARGET_PTR64" | |
d0511997 | 5342 | "call %a1,%2%#" |
7a768814 | 5343 | [(set_attr "type" "call")]) |
576182a3 TW |
5344 | |
5345 | (define_expand "untyped_call" | |
d18d5ca2 | 5346 | [(parallel [(call (match_operand 0 "" "") |
576182a3 | 5347 | (const_int 0)) |
d18d5ca2 JW |
5348 | (match_operand 1 "" "") |
5349 | (match_operand 2 "" "")])] | |
576182a3 TW |
5350 | "" |
5351 | " | |
5352 | { | |
d18d5ca2 | 5353 | int i; |
576182a3 | 5354 | |
d18d5ca2 JW |
5355 | /* Pass constm1 to indicate that it may expect a structure value, but |
5356 | we don't know what size it is. */ | |
5357 | emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx)); | |
bf97b967 | 5358 | |
d18d5ca2 JW |
5359 | for (i = 0; i < XVECLEN (operands[2], 0); i++) |
5360 | { | |
5361 | rtx set = XVECEXP (operands[2], 0, i); | |
5362 | emit_move_insn (SET_DEST (set), SET_SRC (set)); | |
5363 | } | |
bf97b967 | 5364 | |
d18d5ca2 JW |
5365 | /* The optimizer does not know that the call sets the function value |
5366 | registers we stored in the result block. We avoid problems by | |
5367 | claiming that all hard registers are used and clobbered at this | |
5368 | point. */ | |
5369 | emit_insn (gen_blockage ()); | |
576182a3 | 5370 | |
d18d5ca2 JW |
5371 | DONE; |
5372 | }") | |
a8d2b752 | 5373 | |
d18d5ca2 JW |
5374 | ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and |
5375 | ;; all of memory. This blocks insns from being moved across this point. | |
a8d2b752 | 5376 | |
d18d5ca2 JW |
5377 | (define_insn "blockage" |
5378 | [(unspec_volatile [(const_int 0)] 0)] | |
5379 | "" | |
5380 | "") | |
a8d2b752 | 5381 | |
576182a3 TW |
5382 | ;; Prepare to return any type including a structure value. |
5383 | ||
5384 | (define_expand "untyped_return" | |
5385 | [(match_operand:BLK 0 "memory_operand" "") | |
5386 | (match_operand 1 "" "")] | |
5387 | "" | |
5388 | " | |
5389 | { | |
5390 | rtx valreg1 = gen_rtx (REG, DImode, 24); | |
fa0f39e4 | 5391 | rtx valreg2 = gen_rtx (REG, TARGET_ARCH64 ? TFmode : DFmode, 32); |
576182a3 | 5392 | rtx result = operands[0]; |
576182a3 | 5393 | |
fa0f39e4 | 5394 | if (! TARGET_ARCH64) |
a8d2b752 DE |
5395 | { |
5396 | rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31)); | |
5397 | rtx value = gen_reg_rtx (SImode); | |
5398 | ||
5399 | /* Fetch the instruction where we will return to and see if it's an unimp | |
5400 | instruction (the most significant 10 bits will be zero). If so, | |
5401 | update the return address to skip the unimp instruction. */ | |
5402 | emit_move_insn (value, | |
5403 | gen_rtx (MEM, SImode, plus_constant (rtnreg, 8))); | |
5404 | emit_insn (gen_lshrsi3 (value, value, GEN_INT (22))); | |
5405 | emit_insn (gen_update_return (rtnreg, value)); | |
5406 | } | |
576182a3 TW |
5407 | |
5408 | /* Reload the function value registers. */ | |
5409 | emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0))); | |
5410 | emit_move_insn (valreg2, | |
fa0f39e4 | 5411 | change_address (result, TARGET_ARCH64 ? TFmode : DFmode, |
576182a3 TW |
5412 | plus_constant (XEXP (result, 0), 8))); |
5413 | ||
5414 | /* Put USE insns before the return. */ | |
5415 | emit_insn (gen_rtx (USE, VOIDmode, valreg1)); | |
5416 | emit_insn (gen_rtx (USE, VOIDmode, valreg2)); | |
5417 | ||
5418 | /* Construct the return. */ | |
5419 | expand_null_return (); | |
5420 | ||
5421 | DONE; | |
5422 | }") | |
5423 | ||
5424 | ;; This is a bit of a hack. We're incrementing a fixed register (%i7), | |
5425 | ;; and parts of the compiler don't want to believe that the add is needed. | |
5426 | ||
5427 | (define_insn "update_return" | |
5428 | [(unspec:SI [(match_operand:SI 0 "register_operand" "r") | |
5429 | (match_operand:SI 1 "register_operand" "r")] 0)] | |
fa0f39e4 | 5430 | "! TARGET_ARCH64" |
576182a3 TW |
5431 | "cmp %1,0\;be,a .+8\;add %0,4,%0" |
5432 | [(set_attr "type" "multi")]) | |
7a768814 RS |
5433 | \f |
5434 | (define_insn "return" | |
9704efe6 MS |
5435 | [(return) |
5436 | (use (reg:SI 31))] | |
7a768814 RS |
5437 | "! TARGET_EPILOGUE" |
5438 | "* return output_return (operands);" | |
5439 | [(set_attr "type" "multi")]) | |
5440 | ||
5441 | (define_insn "nop" | |
5442 | [(const_int 0)] | |
5443 | "" | |
5444 | "nop") | |
5445 | ||
a8d2b752 DE |
5446 | (define_expand "indirect_jump" |
5447 | [(set (pc) (match_operand 0 "address_operand" "p"))] | |
7a768814 | 5448 | "" |
a8d2b752 DE |
5449 | "") |
5450 | ||
c8b3b7d6 | 5451 | (define_insn "*branch_sp32" |
a8d2b752 DE |
5452 | [(set (pc) (match_operand:SI 0 "address_operand" "p"))] |
5453 | "! TARGET_PTR64" | |
7a768814 | 5454 | "jmp %a0%#" |
e8d6096c | 5455 | [(set_attr "type" "uncond_branch")]) |
7a768814 | 5456 | |
c8b3b7d6 | 5457 | (define_insn "*branch_sp64" |
a8d2b752 DE |
5458 | [(set (pc) (match_operand:DI 0 "address_operand" "p"))] |
5459 | "TARGET_PTR64" | |
5460 | "jmp %a0%#" | |
5461 | [(set_attr "type" "uncond_branch")]) | |
5462 | ||
d9d0de41 | 5463 | ;; ??? Doesn't work with -mflat. |
7a768814 RS |
5464 | (define_expand "nonlocal_goto" |
5465 | [(match_operand:SI 0 "general_operand" "") | |
5466 | (match_operand:SI 1 "general_operand" "") | |
5467 | (match_operand:SI 2 "general_operand" "") | |
5468 | (match_operand:SI 3 "" "")] | |
5469 | "" | |
5470 | " | |
5471 | { | |
b6d3c4ba | 5472 | /* Trap instruction to flush all the register windows. */ |
4893584c | 5473 | emit_insn (gen_flush_register_windows ()); |
7a768814 | 5474 | /* Load the fp value for the containing fn into %fp. |
1f9844c4 JW |
5475 | This is needed because operands[2] refers to %fp. |
5476 | Virtual register instantiation fails if the virtual %fp isn't set from a | |
5477 | register. Thus we must copy operands[0] into a register if it isn't | |
5478 | already one. */ | |
5479 | if (GET_CODE (operands[0]) != REG) | |
d9d0de41 | 5480 | operands[0] = force_reg (Pmode, operands[0]); |
7a768814 RS |
5481 | emit_move_insn (virtual_stack_vars_rtx, operands[0]); |
5482 | /* Find the containing function's current nonlocal goto handler, | |
5483 | which will do any cleanups and then jump to the label. */ | |
d9d0de41 | 5484 | emit_move_insn (gen_rtx (REG, Pmode, 8), operands[1]); |
7a768814 RS |
5485 | /* Restore %fp from stack pointer value for containing function. |
5486 | The restore insn that follows will move this to %sp, | |
5487 | and reload the appropriate value into %fp. */ | |
5488 | emit_move_insn (frame_pointer_rtx, operands[2]); | |
5489 | /* Put in the static chain register the nonlocal label address. */ | |
5490 | emit_move_insn (static_chain_rtx, operands[3]); | |
5491 | /* USE of frame_pointer_rtx added for consistency; not clear if | |
5492 | really needed. */ | |
5493 | emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx)); | |
5494 | emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); | |
5495 | emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx)); | |
7a768814 | 5496 | /* Return, restoring reg window and jumping to goto handler. */ |
4893584c | 5497 | emit_insn (gen_goto_handler_and_restore ()); |
bf1b20da | 5498 | emit_barrier (); |
7a768814 RS |
5499 | DONE; |
5500 | }") | |
5501 | ||
5502 | ;; Special trap insn to flush register windows. | |
4893584c | 5503 | (define_insn "flush_register_windows" |
d18d5ca2 | 5504 | [(unspec_volatile [(const_int 0)] 1)] |
7a768814 | 5505 | "" |
fa0f39e4 DE |
5506 | ;; ??? Use TARGET_V9 instead? |
5507 | "* return TARGET_ARCH64 ? \"flushw\" : \"ta 3\";" | |
b4ac57ab | 5508 | [(set_attr "type" "misc")]) |
7a768814 | 5509 | |
4893584c | 5510 | (define_insn "goto_handler_and_restore" |
f6a048b9 RK |
5511 | [(unspec_volatile [(const_int 0)] 2) |
5512 | (use (reg:SI 8))] | |
7a768814 | 5513 | "" |
b4ac57ab RS |
5514 | "jmp %%o0+0\;restore" |
5515 | [(set_attr "type" "misc") | |
5516 | (set_attr "length" "2")]) | |
94698f4d | 5517 | |
bf1b20da RK |
5518 | ;; Pattern for use after a setjmp to store FP and the return register |
5519 | ;; into the stack area. | |
5520 | ||
5521 | (define_expand "setjmp" | |
5522 | [(const_int 0)] | |
5523 | "" | |
5524 | " | |
5525 | { | |
5526 | if (TARGET_ARCH64) | |
5527 | emit_insn (gen_setjmp_64 ()); | |
5528 | else | |
5529 | emit_insn (gen_setjmp_32 ()); | |
5530 | ||
5531 | DONE; | |
5532 | }") | |
5533 | ||
5534 | (define_expand "setjmp_32" | |
5535 | [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0)) | |
5536 | (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))] | |
5537 | "" | |
5538 | " | |
5539 | { operands[0] = frame_pointer_rtx; }") | |
5540 | ||
5541 | (define_expand "setjmp_64" | |
5542 | [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0)) | |
5543 | (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))] | |
5544 | "" | |
5545 | " | |
5546 | { operands[0] = frame_pointer_rtx; }") | |
5547 | ||
94698f4d RS |
5548 | ;; Special pattern for the FLUSH instruction. |
5549 | ||
5550 | (define_insn "flush" | |
8dffbc60 | 5551 | [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)] |
94698f4d | 5552 | "" |
8dffbc60 | 5553 | "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";" |
94698f4d | 5554 | [(set_attr "type" "misc")]) |
7a768814 | 5555 | \f |
114b9aa4 JW |
5556 | ;; find first set. |
5557 | ||
5558 | ;; The scan instruction searches from the most significant bit while ffs | |
5559 | ;; searches from the least significant bit. The bit index and treatment of | |
5560 | ;; zero also differ. It takes at least 7 instructions to get the proper | |
ddd5a7c1 | 5561 | ;; result. Here is an obvious 8 instruction sequence. |
114b9aa4 JW |
5562 | |
5563 | (define_insn "ffssi2" | |
5564 | [(set (match_operand:SI 0 "register_operand" "=&r") | |
5565 | (ffs:SI (match_operand:SI 1 "register_operand" "r"))) | |
5566 | (clobber (match_scratch:SI 2 "=&r"))] | |
967ba98d | 5567 | "TARGET_SPARCLITE || TARGET_SPARCLET" |
c4ce6853 DE |
5568 | "* |
5569 | { | |
5570 | if (TARGET_LIVE_G0) | |
5571 | output_asm_insn (\"and %%g0,0,%%g0\", operands); | |
5572 | return \"sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0\"; | |
5573 | }" | |
114b9aa4 JW |
5574 | [(set_attr "type" "multi") |
5575 | (set_attr "length" "8")]) | |
a8d2b752 DE |
5576 | |
5577 | ;; ??? This should be a define expand, so that the extra instruction have | |
5578 | ;; a chance of being optimized away. | |
5579 | ||
5580 | (define_insn "ffsdi2" | |
5581 | [(set (match_operand:DI 0 "register_operand" "=&r") | |
5582 | (ffs:DI (match_operand:DI 1 "register_operand" "r"))) | |
5583 | (clobber (match_scratch:DI 2 "=&r"))] | |
fa0f39e4 | 5584 | "TARGET_ARCH64" |
c4ce6853 | 5585 | "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,0,%0" |
a8d2b752 DE |
5586 | [(set_attr "type" "multi") |
5587 | (set_attr "length" "5")]) | |
114b9aa4 | 5588 | \f |
7a768814 RS |
5589 | ;; Split up troublesome insns for better scheduling. */ |
5590 | ||
5591 | ;; The following patterns are straightforward. They can be applied | |
5592 | ;; either before or after register allocation. | |
5593 | ||
5594 | (define_split | |
d750d0de DE |
5595 | [(set (match_operand 0 "splittable_symbolic_memory_operand" "") |
5596 | (match_operand 1 "reg_or_0_operand" "")) | |
5597 | (clobber (match_operand:SI 2 "register_operand" ""))] | |
7a768814 | 5598 | "! flag_pic" |
d750d0de DE |
5599 | [(set (match_dup 2) (high:SI (match_dup 3))) |
5600 | (set (match_dup 4) (match_dup 1))] | |
5601 | " | |
5602 | { | |
5603 | operands[3] = XEXP (operands[0], 0); | |
5604 | operands[4] = gen_rtx (MEM, GET_MODE (operands[0]), | |
5605 | gen_rtx (LO_SUM, SImode, operands[2], operands[3])); | |
5606 | MEM_IN_STRUCT_P (operands[4]) = MEM_IN_STRUCT_P (operands[0]); | |
5607 | MEM_VOLATILE_P (operands[4]) = MEM_VOLATILE_P (operands[0]); | |
5608 | RTX_UNCHANGING_P (operands[4]) = RTX_UNCHANGING_P (operands[0]); | |
5609 | }") | |
7a768814 RS |
5610 | |
5611 | (define_split | |
d750d0de DE |
5612 | [(set (match_operand 0 "splittable_immediate_memory_operand" "") |
5613 | (match_operand 1 "general_operand" "")) | |
5614 | (clobber (match_operand:SI 2 "register_operand" ""))] | |
7a768814 | 5615 | "flag_pic" |
d750d0de | 5616 | [(set (match_dup 3) (match_dup 1))] |
7a768814 RS |
5617 | " |
5618 | { | |
d750d0de DE |
5619 | rtx addr = legitimize_pic_address (XEXP (operands[0], 0), |
5620 | GET_MODE (operands[0]), | |
5621 | operands[2]); | |
5622 | operands[3] = gen_rtx (MEM, GET_MODE (operands[0]), addr); | |
5623 | MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[0]); | |
5624 | MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[0]); | |
5625 | RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[0]); | |
7a768814 RS |
5626 | }") |
5627 | ||
5628 | (define_split | |
5629 | [(set (match_operand 0 "register_operand" "") | |
d750d0de | 5630 | (match_operand 1 "splittable_immediate_memory_operand" ""))] |
7a768814 | 5631 | "flag_pic" |
d750d0de | 5632 | [(set (match_dup 0) (match_dup 2))] |
7a768814 RS |
5633 | " |
5634 | { | |
d750d0de DE |
5635 | rtx addr = legitimize_pic_address (XEXP (operands[1], 0), |
5636 | GET_MODE (operands[1]), | |
5637 | operands[0]); | |
5638 | operands[2] = gen_rtx (MEM, GET_MODE (operands[1]), addr); | |
5639 | MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]); | |
5640 | MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]); | |
5641 | RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]); | |
7a768814 RS |
5642 | }") |
5643 | ||
5644 | ;; Sign- and Zero-extend operations can have symbolic memory operands. | |
5645 | ||
5646 | (define_split | |
5647 | [(set (match_operand 0 "register_operand" "") | |
d750d0de | 5648 | (match_operator 1 "extend_op" [(match_operand 2 "splittable_immediate_memory_operand" "")]))] |
7a768814 | 5649 | "flag_pic" |
d750d0de | 5650 | [(set (match_dup 0) (match_op_dup 1 [(match_dup 3)]))] |
7a768814 RS |
5651 | " |
5652 | { | |
d750d0de DE |
5653 | rtx addr = legitimize_pic_address (XEXP (operands[2], 0), |
5654 | GET_MODE (operands[2]), | |
5655 | operands[0]); | |
5656 | operands[3] = gen_rtx (MEM, GET_MODE (operands[2]), addr); | |
5657 | MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[2]); | |
5658 | MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[2]); | |
5659 | RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[2]); | |
7a768814 RS |
5660 | }") |
5661 | ||
5662 | (define_split | |
5663 | [(set (match_operand:SI 0 "register_operand" "") | |
5664 | (match_operand:SI 1 "immediate_operand" ""))] | |
5665 | "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF | |
5666 | || GET_CODE (operands[1]) == CONST | |
5667 | || GET_CODE (operands[1]) == LABEL_REF)" | |
5668 | [(set (match_dup 0) (high:SI (match_dup 1))) | |
5669 | (set (match_dup 0) | |
5670 | (lo_sum:SI (match_dup 0) (match_dup 1)))] | |
5671 | "") | |
5672 | ||
967ba98d | 5673 | ;; LABEL_REFs are not modified by `legitimize_pic_address' |
7a768814 RS |
5674 | ;; so do not recurse infinitely in the PIC case. |
5675 | (define_split | |
5676 | [(set (match_operand:SI 0 "register_operand" "") | |
5677 | (match_operand:SI 1 "immediate_operand" ""))] | |
5678 | "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF | |
5679 | || GET_CODE (operands[1]) == CONST)" | |
5680 | [(set (match_dup 0) (match_dup 1))] | |
5681 | " | |
5682 | { | |
d0fc7bea | 5683 | operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]); |
7a768814 RS |
5684 | }") |
5685 | \f | |
5686 | ;; These split sne/seq insns. The forms of the resulting insns are | |
5687 | ;; somewhat bogus, but they avoid extra patterns and show data dependency. | |
5688 | ;; Nothing will look at these in detail after splitting has occurred. | |
5689 | ||
a8d2b752 DE |
5690 | ;; ??? v9 DImode versions are missing because addc and subc use %icc. |
5691 | ||
7a768814 RS |
5692 | (define_split |
5693 | [(set (match_operand:SI 0 "register_operand" "") | |
a8d2b752 DE |
5694 | (ne:SI (match_operand:SI 1 "register_operand" "") |
5695 | (const_int 0))) | |
c4ce6853 | 5696 | (clobber (reg:CC 100))] |
7a768814 | 5697 | "" |
c4ce6853 DE |
5698 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5699 | (const_int 0))) | |
5700 | (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))] | |
7a768814 RS |
5701 | "") |
5702 | ||
5703 | (define_split | |
5704 | [(set (match_operand:SI 0 "register_operand" "") | |
5705 | (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "") | |
5706 | (const_int 0)))) | |
c4ce6853 | 5707 | (clobber (reg:CC 100))] |
7a768814 | 5708 | "" |
c4ce6853 DE |
5709 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5710 | (const_int 0))) | |
5711 | (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))] | |
7a768814 RS |
5712 | "") |
5713 | ||
5714 | (define_split | |
5715 | [(set (match_operand:SI 0 "register_operand" "") | |
a8d2b752 DE |
5716 | (eq:SI (match_operand:SI 1 "register_operand" "") |
5717 | (const_int 0))) | |
c4ce6853 | 5718 | (clobber (reg:CC 100))] |
7a768814 | 5719 | "" |
c4ce6853 DE |
5720 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5721 | (const_int 0))) | |
5722 | (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))] | |
7a768814 RS |
5723 | "") |
5724 | ||
5725 | (define_split | |
5726 | [(set (match_operand:SI 0 "register_operand" "") | |
5727 | (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "") | |
5728 | (const_int 0)))) | |
c4ce6853 | 5729 | (clobber (reg:CC 100))] |
7a768814 | 5730 | "" |
c4ce6853 DE |
5731 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5732 | (const_int 0))) | |
5733 | (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))] | |
7a768814 RS |
5734 | "") |
5735 | ||
5736 | (define_split | |
5737 | [(set (match_operand:SI 0 "register_operand" "") | |
5738 | (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "") | |
5739 | (const_int 0)) | |
5740 | (match_operand:SI 2 "register_operand" ""))) | |
c4ce6853 | 5741 | (clobber (reg:CC 100))] |
7a768814 | 5742 | "" |
c4ce6853 DE |
5743 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5744 | (const_int 0))) | |
5745 | (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) | |
7a768814 RS |
5746 | (match_dup 2)))] |
5747 | "") | |
5748 | ||
5749 | (define_split | |
5750 | [(set (match_operand:SI 0 "register_operand" "") | |
5751 | (minus:SI (match_operand:SI 2 "register_operand" "") | |
5752 | (ne:SI (match_operand:SI 1 "register_operand" "") | |
5753 | (const_int 0)))) | |
c4ce6853 | 5754 | (clobber (reg:CC 100))] |
7a768814 | 5755 | "" |
c4ce6853 DE |
5756 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5757 | (const_int 0))) | |
7a768814 | 5758 | (set (match_dup 0) (minus:SI (match_dup 2) |
c4ce6853 | 5759 | (ltu:SI (reg:CC 100) (const_int 0))))] |
7a768814 RS |
5760 | "") |
5761 | ||
5762 | (define_split | |
5763 | [(set (match_operand:SI 0 "register_operand" "") | |
5764 | (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "") | |
5765 | (const_int 0)) | |
5766 | (match_operand:SI 2 "register_operand" ""))) | |
c4ce6853 | 5767 | (clobber (reg:CC 100))] |
7a768814 | 5768 | "" |
c4ce6853 DE |
5769 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5770 | (const_int 0))) | |
5771 | (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0)) | |
7a768814 RS |
5772 | (match_dup 2)))] |
5773 | "") | |
5774 | ||
5775 | (define_split | |
5776 | [(set (match_operand:SI 0 "register_operand" "") | |
5777 | (minus:SI (match_operand:SI 2 "register_operand" "") | |
5778 | (eq:SI (match_operand:SI 1 "register_operand" "") | |
5779 | (const_int 0)))) | |
c4ce6853 | 5780 | (clobber (reg:CC 100))] |
7a768814 | 5781 | "" |
c4ce6853 DE |
5782 | [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1)) |
5783 | (const_int 0))) | |
7a768814 | 5784 | (set (match_dup 0) (minus:SI (match_dup 2) |
c4ce6853 | 5785 | (geu:SI (reg:CC 100) (const_int 0))))] |
7a768814 RS |
5786 | "") |
5787 | \f | |
5788 | ;; Peepholes go at the end. | |
5789 | ||
35016322 JW |
5790 | ;; Optimize consecutive loads or stores into ldd and std when possible. |
5791 | ;; The conditions in which we do this are very restricted and are | |
5792 | ;; explained in the code for {registers,memory}_ok_for_ldd functions. | |
5793 | ||
5794 | (define_peephole | |
82b56258 | 5795 | [(set (match_operand:SI 0 "register_operand" "=rf") |
35016322 | 5796 | (match_operand:SI 1 "memory_operand" "")) |
82b56258 | 5797 | (set (match_operand:SI 2 "register_operand" "=rf") |
35016322 | 5798 | (match_operand:SI 3 "memory_operand" ""))] |
fa0f39e4 | 5799 | "! TARGET_ARCH64 |
a8d2b752 | 5800 | && registers_ok_for_ldd_peep (operands[0], operands[2]) |
35016322 | 5801 | && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) |
e8d6096c | 5802 | && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" |
35016322 JW |
5803 | "ldd %1,%0") |
5804 | ||
5805 | (define_peephole | |
5806 | [(set (match_operand:SI 0 "memory_operand" "") | |
82b56258 | 5807 | (match_operand:SI 1 "register_operand" "rf")) |
35016322 | 5808 | (set (match_operand:SI 2 "memory_operand" "") |
82b56258 | 5809 | (match_operand:SI 3 "register_operand" "rf"))] |
fa0f39e4 | 5810 | "! TARGET_ARCH64 |
a8d2b752 | 5811 | && registers_ok_for_ldd_peep (operands[1], operands[3]) |
35016322 | 5812 | && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) |
e8d6096c | 5813 | && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" |
35016322 JW |
5814 | "std %1,%0") |
5815 | ||
5816 | (define_peephole | |
2abaee93 | 5817 | [(set (match_operand:SF 0 "register_operand" "=fr") |
35016322 | 5818 | (match_operand:SF 1 "memory_operand" "")) |
2abaee93 | 5819 | (set (match_operand:SF 2 "register_operand" "=fr") |
35016322 | 5820 | (match_operand:SF 3 "memory_operand" ""))] |
fa0f39e4 | 5821 | "! TARGET_ARCH64 |
a8d2b752 | 5822 | && registers_ok_for_ldd_peep (operands[0], operands[2]) |
35016322 | 5823 | && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) |
e8d6096c | 5824 | && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" |
35016322 JW |
5825 | "ldd %1,%0") |
5826 | ||
5827 | (define_peephole | |
5828 | [(set (match_operand:SF 0 "memory_operand" "") | |
5829 | (match_operand:SF 1 "register_operand" "fr")) | |
5830 | (set (match_operand:SF 2 "memory_operand" "") | |
5831 | (match_operand:SF 3 "register_operand" "fr"))] | |
fa0f39e4 | 5832 | "! TARGET_ARCH64 |
a8d2b752 | 5833 | && registers_ok_for_ldd_peep (operands[1], operands[3]) |
35016322 | 5834 | && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) |
e8d6096c | 5835 | && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" |
35016322 JW |
5836 | "std %1,%0") |
5837 | ||
5838 | (define_peephole | |
82b56258 | 5839 | [(set (match_operand:SI 0 "register_operand" "=rf") |
35016322 | 5840 | (match_operand:SI 1 "memory_operand" "")) |
82b56258 | 5841 | (set (match_operand:SI 2 "register_operand" "=rf") |
35016322 | 5842 | (match_operand:SI 3 "memory_operand" ""))] |
fa0f39e4 | 5843 | "! TARGET_ARCH64 |
a8d2b752 | 5844 | && registers_ok_for_ldd_peep (operands[2], operands[0]) |
35016322 | 5845 | && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) |
e8d6096c | 5846 | && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" |
35016322 JW |
5847 | "ldd %3,%2") |
5848 | ||
5849 | (define_peephole | |
5850 | [(set (match_operand:SI 0 "memory_operand" "") | |
82b56258 | 5851 | (match_operand:SI 1 "register_operand" "rf")) |
35016322 | 5852 | (set (match_operand:SI 2 "memory_operand" "") |
82b56258 | 5853 | (match_operand:SI 3 "register_operand" "rf"))] |
fa0f39e4 | 5854 | "! TARGET_ARCH64 |
a8d2b752 | 5855 | && registers_ok_for_ldd_peep (operands[3], operands[1]) |
35016322 | 5856 | && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) |
e8d6096c | 5857 | && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" |
35016322 JW |
5858 | "std %3,%2") |
5859 | ||
5860 | (define_peephole | |
2abaee93 | 5861 | [(set (match_operand:SF 0 "register_operand" "=fr") |
35016322 | 5862 | (match_operand:SF 1 "memory_operand" "")) |
2abaee93 | 5863 | (set (match_operand:SF 2 "register_operand" "=fr") |
35016322 | 5864 | (match_operand:SF 3 "memory_operand" ""))] |
fa0f39e4 | 5865 | "! TARGET_ARCH64 |
a8d2b752 | 5866 | && registers_ok_for_ldd_peep (operands[2], operands[0]) |
35016322 | 5867 | && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) |
e8d6096c | 5868 | && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" |
35016322 JW |
5869 | "ldd %3,%2") |
5870 | ||
5871 | (define_peephole | |
5872 | [(set (match_operand:SF 0 "memory_operand" "") | |
5873 | (match_operand:SF 1 "register_operand" "fr")) | |
5874 | (set (match_operand:SF 2 "memory_operand" "") | |
5875 | (match_operand:SF 3 "register_operand" "fr"))] | |
fa0f39e4 | 5876 | "! TARGET_ARCH64 |
a8d2b752 | 5877 | && registers_ok_for_ldd_peep (operands[3], operands[1]) |
35016322 | 5878 | && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) |
e8d6096c | 5879 | && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" |
35016322 JW |
5880 | "std %3,%2") |
5881 | ||
7a768814 | 5882 | ;; Optimize the case of following a reg-reg move with a test |
1a1ba90e | 5883 | ;; of reg just moved. Don't allow floating point regs for operand 0 or 1. |
72f4648e | 5884 | ;; This can result from a float to fix conversion. |
7a768814 RS |
5885 | |
5886 | (define_peephole | |
5887 | [(set (match_operand:SI 0 "register_operand" "=r") | |
5888 | (match_operand:SI 1 "register_operand" "r")) | |
c4ce6853 | 5889 | (set (reg:CC 100) |
7a768814 RS |
5890 | (compare:CC (match_operand:SI 2 "register_operand" "r") |
5891 | (const_int 0)))] | |
72f4648e JW |
5892 | "(rtx_equal_p (operands[2], operands[0]) |
5893 | || rtx_equal_p (operands[2], operands[1])) | |
1a1ba90e | 5894 | && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" |
c4ce6853 | 5895 | "orcc %1,0,%0") |
7a768814 | 5896 | |
a8d2b752 DE |
5897 | (define_peephole |
5898 | [(set (match_operand:DI 0 "register_operand" "=r") | |
5899 | (match_operand:DI 1 "register_operand" "r")) | |
c4ce6853 | 5900 | (set (reg:CCX 100) |
a8d2b752 DE |
5901 | (compare:CCX (match_operand:DI 2 "register_operand" "r") |
5902 | (const_int 0)))] | |
fa0f39e4 | 5903 | "TARGET_ARCH64 |
a8d2b752 DE |
5904 | && (rtx_equal_p (operands[2], operands[0]) |
5905 | || rtx_equal_p (operands[2], operands[1])) | |
5906 | && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" | |
c4ce6853 | 5907 | "orcc %1,0,%0") |
a8d2b752 | 5908 | |
7a768814 RS |
5909 | ;; Do {sign,zero}-extended compares somewhat more efficiently. |
5910 | ;; ??? Is this now the Right Way to do this? Or will SCRATCH | |
5911 | ;; eventually have some impact here? | |
5912 | ||
5913 | (define_peephole | |
5914 | [(set (match_operand:HI 0 "register_operand" "") | |
5915 | (match_operand:HI 1 "memory_operand" "")) | |
5916 | (set (match_operand:SI 2 "register_operand" "") | |
5917 | (sign_extend:SI (match_dup 0))) | |
c4ce6853 | 5918 | (set (reg:CC 100) |
7a768814 RS |
5919 | (compare:CC (match_dup 2) |
5920 | (const_int 0)))] | |
5921 | "" | |
c4ce6853 | 5922 | "ldsh %1,%0\;orcc %0,0,%2") |
7a768814 | 5923 | |
a8d2b752 DE |
5924 | (define_peephole |
5925 | [(set (match_operand:HI 0 "register_operand" "") | |
5926 | (match_operand:HI 1 "memory_operand" "")) | |
5927 | (set (match_operand:DI 2 "register_operand" "") | |
5928 | (sign_extend:DI (match_dup 0))) | |
c4ce6853 | 5929 | (set (reg:CCX 100) |
a8d2b752 DE |
5930 | (compare:CCX (match_dup 2) |
5931 | (const_int 0)))] | |
fa0f39e4 | 5932 | "TARGET_ARCH64" |
c4ce6853 | 5933 | "ldsh %1,%0\;orcc %0,0,%2") |
a8d2b752 | 5934 | |
7a768814 RS |
5935 | (define_peephole |
5936 | [(set (match_operand:QI 0 "register_operand" "") | |
5937 | (match_operand:QI 1 "memory_operand" "")) | |
5938 | (set (match_operand:SI 2 "register_operand" "") | |
5939 | (sign_extend:SI (match_dup 0))) | |
c4ce6853 | 5940 | (set (reg:CC 100) |
7a768814 RS |
5941 | (compare:CC (match_dup 2) |
5942 | (const_int 0)))] | |
5943 | "" | |
c4ce6853 | 5944 | "ldsb %1,%0\;orcc %0,0,%2") |
7a768814 | 5945 | |
a8d2b752 DE |
5946 | (define_peephole |
5947 | [(set (match_operand:QI 0 "register_operand" "") | |
5948 | (match_operand:QI 1 "memory_operand" "")) | |
5949 | (set (match_operand:DI 2 "register_operand" "") | |
5950 | (sign_extend:DI (match_dup 0))) | |
c4ce6853 | 5951 | (set (reg:CCX 100) |
a8d2b752 DE |
5952 | (compare:CCX (match_dup 2) |
5953 | (const_int 0)))] | |
fa0f39e4 | 5954 | "TARGET_ARCH64" |
c4ce6853 | 5955 | "ldsb %1,%0\;orcc %0,0,%2") |
a8d2b752 | 5956 | |
7a768814 | 5957 | ;; Floating-point move peepholes |
a8d2b752 | 5958 | ;; ??? v9: Do we want similar ones? |
7a768814 RS |
5959 | |
5960 | (define_peephole | |
5961 | [(set (match_operand:SI 0 "register_operand" "=r") | |
5962 | (lo_sum:SI (match_dup 0) | |
5963 | (match_operand:SI 1 "immediate_operand" "i"))) | |
b6d3c4ba | 5964 | (set (match_operand:DF 2 "register_operand" "=er") |
7a768814 RS |
5965 | (mem:DF (match_dup 0)))] |
5966 | "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" | |
5967 | "* | |
5968 | { | |
5969 | /* Go by way of output_move_double in case the register in operand 2 | |
5970 | is not properly aligned for ldd. */ | |
5971 | operands[1] = gen_rtx (MEM, DFmode, | |
5972 | gen_rtx (LO_SUM, SImode, operands[0], operands[1])); | |
5973 | operands[0] = operands[2]; | |
5974 | return output_move_double (operands); | |
5975 | }") | |
5976 | ||
5977 | (define_peephole | |
5978 | [(set (match_operand:SI 0 "register_operand" "=r") | |
5979 | (lo_sum:SI (match_dup 0) | |
5980 | (match_operand:SI 1 "immediate_operand" "i"))) | |
5981 | (set (match_operand:SF 2 "register_operand" "=fr") | |
5982 | (mem:SF (match_dup 0)))] | |
5983 | "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)" | |
5984 | "ld [%0+%%lo(%a1)],%2") | |
5985 | ||
c4ce6853 DE |
5986 | ;; Return peepholes. First the "normal" ones. |
5987 | ;; These are necessary to catch insns ending up in the epilogue delay list. | |
262121f0 | 5988 | |
c8b3b7d6 | 5989 | (define_insn "*return_qi" |
262121f0 JW |
5990 | [(set (match_operand:QI 0 "restore_operand" "") |
5991 | (match_operand:QI 1 "arith_operand" "rI")) | |
5992 | (return)] | |
c4ce6853 | 5993 | "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" |
262121f0 JW |
5994 | "* |
5995 | { | |
fa0f39e4 | 5996 | if (! TARGET_ARCH64 && current_function_returns_struct) |
262121f0 JW |
5997 | return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; |
5998 | else | |
5999 | return \"ret\;restore %%g0,%1,%Y0\"; | |
6000 | }" | |
6001 | [(set_attr "type" "multi")]) | |
6002 | ||
c8b3b7d6 | 6003 | (define_insn "*return_hi" |
262121f0 JW |
6004 | [(set (match_operand:HI 0 "restore_operand" "") |
6005 | (match_operand:HI 1 "arith_operand" "rI")) | |
6006 | (return)] | |
c4ce6853 | 6007 | "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" |
262121f0 JW |
6008 | "* |
6009 | { | |
fa0f39e4 | 6010 | if (! TARGET_ARCH64 && current_function_returns_struct) |
262121f0 JW |
6011 | return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; |
6012 | else | |
6013 | return \"ret\;restore %%g0,%1,%Y0\"; | |
6014 | }" | |
6015 | [(set_attr "type" "multi")]) | |
6016 | ||
c8b3b7d6 | 6017 | (define_insn "*return_si" |
7a768814 RS |
6018 | [(set (match_operand:SI 0 "restore_operand" "") |
6019 | (match_operand:SI 1 "arith_operand" "rI")) | |
6020 | (return)] | |
c4ce6853 | 6021 | "! TARGET_EPILOGUE && ! TARGET_LIVE_G0" |
7a768814 RS |
6022 | "* |
6023 | { | |
fa0f39e4 | 6024 | if (! TARGET_ARCH64 && current_function_returns_struct) |
7a768814 RS |
6025 | return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; |
6026 | else | |
6027 | return \"ret\;restore %%g0,%1,%Y0\"; | |
6028 | }" | |
6029 | [(set_attr "type" "multi")]) | |
6030 | ||
ab5519b7 JW |
6031 | ;; The following pattern is only generated by delayed-branch scheduling, |
6032 | ;; when the insn winds up in the epilogue. This can only happen when | |
6033 | ;; ! TARGET_FPU because otherwise fp return values are in %f0. | |
c8b3b7d6 | 6034 | (define_insn "*return_sf_no_fpu" |
ab5519b7 JW |
6035 | [(set (match_operand:SF 0 "restore_operand" "r") |
6036 | (match_operand:SF 1 "register_operand" "r")) | |
6037 | (return)] | |
c4ce6853 | 6038 | "! TARGET_FPU && ! TARGET_EPILOGUE && ! TARGET_LIVE_G0" |
ab5519b7 JW |
6039 | "* |
6040 | { | |
fa0f39e4 | 6041 | if (! TARGET_ARCH64 && current_function_returns_struct) |
ab5519b7 JW |
6042 | return \"jmp %%i7+12\;restore %%g0,%1,%Y0\"; |
6043 | else | |
6044 | return \"ret\;restore %%g0,%1,%Y0\"; | |
6045 | }" | |
6046 | [(set_attr "type" "multi")]) | |
6047 | ||
c8b3b7d6 | 6048 | (define_insn "*return_addsi" |
7a768814 RS |
6049 | [(set (match_operand:SI 0 "restore_operand" "") |
6050 | (plus:SI (match_operand:SI 1 "arith_operand" "%r") | |
6051 | (match_operand:SI 2 "arith_operand" "rI"))) | |
6052 | (return)] | |
eead6b5b RK |
6053 | "! TARGET_EPILOGUE && ! TARGET_LIVE_G0 |
6054 | && (register_operand (operands[1], SImode) | |
6055 | || register_operand (operands[2], SImode))" | |
7a768814 RS |
6056 | "* |
6057 | { | |
fa0f39e4 | 6058 | if (! TARGET_ARCH64 && current_function_returns_struct) |
7a768814 RS |
6059 | return \"jmp %%i7+12\;restore %r1,%2,%Y0\"; |
6060 | else | |
6061 | return \"ret\;restore %r1,%2,%Y0\"; | |
6062 | }" | |
6063 | [(set_attr "type" "multi")]) | |
6064 | ||
c8b3b7d6 | 6065 | (define_insn "*return_di" |
a8d2b752 DE |
6066 | [(set (match_operand:DI 0 "restore_operand" "") |
6067 | (match_operand:DI 1 "arith_double_operand" "rHI")) | |
6068 | (return)] | |
fa0f39e4 | 6069 | "TARGET_ARCH64 && ! TARGET_EPILOGUE" |
a8d2b752 DE |
6070 | "ret\;restore %%g0,%1,%Y0" |
6071 | [(set_attr "type" "multi")]) | |
6072 | ||
c8b3b7d6 | 6073 | (define_insn "*return_adddi" |
a8d2b752 | 6074 | [(set (match_operand:DI 0 "restore_operand" "") |
eead6b5b | 6075 | (plus:DI (match_operand:DI 1 "arith_double_operand" "%r") |
a8d2b752 DE |
6076 | (match_operand:DI 2 "arith_double_operand" "rHI"))) |
6077 | (return)] | |
eead6b5b RK |
6078 | "TARGET_ARCH64 && ! TARGET_EPILOGUE |
6079 | && (register_operand (operands[1], DImode) | |
6080 | || register_operand (operands[2], DImode))" | |
a8d2b752 DE |
6081 | "ret\;restore %r1,%2,%Y0" |
6082 | [(set_attr "type" "multi")]) | |
6083 | ||
eead6b5b RK |
6084 | (define_insn "*return_subsi" |
6085 | [(set (match_operand:SI 0 "restore_operand" "") | |
6086 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
6087 | (match_operand:SI 2 "small_int" "I"))) | |
6088 | (return)] | |
6089 | "! TARGET_EPILOGUE && INTVAL (operands[2]) != -4096" | |
6090 | "ret\;restore %1,%n2,%Y0" | |
6091 | [(set_attr "type" "multi")]) | |
7a768814 RS |
6092 | |
6093 | ;; The following pattern is only generated by delayed-branch scheduling, | |
6094 | ;; when the insn winds up in the epilogue. | |
c8b3b7d6 | 6095 | (define_insn "*return_sf" |
7a768814 RS |
6096 | [(set (reg:SF 32) |
6097 | (match_operand:SF 0 "register_operand" "f")) | |
6098 | (return)] | |
6099 | "! TARGET_EPILOGUE" | |
b4ac57ab RS |
6100 | "ret\;fmovs %0,%%f0" |
6101 | [(set_attr "type" "multi")]) | |
7a768814 | 6102 | |
a8d2b752 | 6103 | ;; Now peepholes to do a call followed by a jump. |
7a768814 RS |
6104 | |
6105 | (define_peephole | |
6106 | [(parallel [(set (match_operand 0 "" "") | |
2c435002 | 6107 | (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps")) |
7a768814 RS |
6108 | (match_operand 2 "" ""))) |
6109 | (clobber (reg:SI 15))]) | |
6110 | (set (pc) (label_ref (match_operand 3 "" "")))] | |
6111 | "short_branch (INSN_UID (insn), INSN_UID (operands[3]))" | |
d0511997 | 6112 | "call %a1,%2\;add %%o7,(%l3-.-4),%%o7") |
7a768814 RS |
6113 | |
6114 | (define_peephole | |
2c435002 | 6115 | [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps")) |
7a768814 RS |
6116 | (match_operand 1 "" "")) |
6117 | (clobber (reg:SI 15))]) | |
6118 | (set (pc) (label_ref (match_operand 2 "" "")))] | |
6119 | "short_branch (INSN_UID (insn), INSN_UID (operands[2]))" | |
6120 | "* | |
6121 | { | |
6122 | return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\"; | |
6123 | }") | |
6124 | ||
a8d2b752 DE |
6125 | (define_peephole |
6126 | [(parallel [(set (match_operand 0 "" "") | |
2c435002 | 6127 | (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps")) |
a8d2b752 DE |
6128 | (match_operand 2 "" ""))) |
6129 | (clobber (reg:DI 15))]) | |
6130 | (set (pc) (label_ref (match_operand 3 "" "")))] | |
fa0f39e4 | 6131 | "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))" |
d0511997 | 6132 | "call %a1,%2\;add %%o7,(%l3-.-4),%%o7") |
a8d2b752 DE |
6133 | |
6134 | (define_peephole | |
2c435002 | 6135 | [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps")) |
a8d2b752 DE |
6136 | (match_operand 1 "" "")) |
6137 | (clobber (reg:DI 15))]) | |
6138 | (set (pc) (label_ref (match_operand 2 "" "")))] | |
fa0f39e4 | 6139 | "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))" |
d0511997 | 6140 | "call %a0,%1\;add %%o7,(%l2-.-4),%%o7") |
a8d2b752 DE |
6141 | |
6142 | ;; Other miscellaneous peepholes. | |
6143 | ||
c4ce6853 | 6144 | ;; (reg:SI 100) is created by the {add,neg,sub}di patterns. |
7a768814 RS |
6145 | (define_peephole |
6146 | [(parallel [(set (match_operand:SI 0 "register_operand" "=r") | |
6147 | (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") | |
c4ce6853 DE |
6148 | (reg:SI 100))) |
6149 | (clobber (reg:CC 100))]) | |
6150 | (set (reg:CC 100) (compare (match_dup 0) (const_int 0)))] | |
7a768814 | 6151 | "" |
b4ac57ab | 6152 | "subxcc %r1,0,%0") |
c85f7c16 JL |
6153 | |
6154 | ;; After a nonlocal goto, we need to restore the PIC register, but only | |
6155 | ;; if we need it. So do nothing much here, but we'll check for this in | |
6156 | ;; finalize_pic. | |
6157 | ||
6158 | (define_insn "nonlocal_goto_receiver" | |
6159 | [(unspec_volatile [(const_int 0)] 4)] | |
6160 | "flag_pic" | |
6161 | "") |