re PR middle-end/7151 ([sparc] ICE when compiling for UltraSPARC)
[gcc.git] / gcc / config / sparc / sparc.md
1 ;; Machine description for SPARC chip for GNU C compiler
2 ;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 ;; 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4 ;; Contributed by Michael Tiemann (tiemann@cygnus.com)
5 ;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
6 ;; at Cygnus Support.
7
8 ;; This file is part of GNU CC.
9
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 (define_constants
28 [(UNSPEC_MOVE_PIC 0)
29 (UNSPEC_UPDATE_RETURN 1)
30 (UNSPEC_GET_PC 2)
31 (UNSPEC_MOVE_PIC_LABEL 5)
32 (UNSPEC_SETH44 6)
33 (UNSPEC_SETM44 7)
34 (UNSPEC_SETHH 9)
35 (UNSPEC_SETLM 10)
36 (UNSPEC_EMB_HISUM 11)
37 (UNSPEC_EMB_TEXTUHI 13)
38 (UNSPEC_EMB_TEXTHI 14)
39 (UNSPEC_EMB_TEXTULO 15)
40 (UNSPEC_EMB_SETHM 18)
41 ])
42
43 (define_constants
44 [(UNSPECV_BLOCKAGE 0)
45 (UNSPECV_FLUSHW 1)
46 (UNSPECV_GOTO 2)
47 (UNSPECV_GOTO_V9 3)
48 (UNSPECV_FLUSH 4)
49 (UNSPECV_SETJMP 5)
50 ])
51
52 ;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
53 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
54 ;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
55 ;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
56 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
57
58 ;; Attribute for cpu type.
59 ;; These must match the values for enum processor_type in sparc.h.
60 (define_attr "cpu"
61 "v7,
62 cypress,
63 v8,
64 supersparc,
65 sparclite,f930,f934,
66 hypersparc,sparclite86x,
67 sparclet,tsc701,
68 v9,
69 ultrasparc,
70 ultrasparc3"
71 (const (symbol_ref "sparc_cpu_attr")))
72
73 ;; Attribute for the instruction set.
74 ;; At present we only need to distinguish v9/!v9, but for clarity we
75 ;; test TARGET_V8 too.
76 (define_attr "isa" "v6,v8,v9,sparclet"
77 (const
78 (cond [(symbol_ref "TARGET_V9") (const_string "v9")
79 (symbol_ref "TARGET_V8") (const_string "v8")
80 (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
81 (const_string "v6"))))
82
83 ;; Architecture size.
84 (define_attr "arch" "arch32bit,arch64bit"
85 (const
86 (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
87 (const_string "arch32bit"))))
88
89 ;; Insn type.
90
91 (define_attr "type"
92 "ialu,compare,shift,
93 load,sload,store,
94 uncond_branch,branch,call,sibcall,call_no_delay_slot,
95 imul,idiv,
96 fpload,fpstore,
97 fp,fpmove,
98 fpcmove,fpcrmove,
99 fpcmp,
100 fpmul,fpdivs,fpdivd,
101 fpsqrts,fpsqrtd,
102 cmove,
103 ialuX,
104 multi,flushw,iflush,trap"
105 (const_string "ialu"))
106
107 ;; true if branch/call has empty delay slot and will emit a nop in it
108 (define_attr "empty_delay_slot" "false,true"
109 (symbol_ref "empty_delay_slot (insn)"))
110
111 (define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))
112
113 (define_attr "pic" "false,true"
114 (symbol_ref "flag_pic != 0"))
115
116 (define_attr "current_function_calls_alloca" "false,true"
117 (symbol_ref "current_function_calls_alloca != 0"))
118
119 (define_attr "flat" "false,true"
120 (symbol_ref "TARGET_FLAT != 0"))
121
122 ;; Length (in # of insns).
123 (define_attr "length" ""
124 (cond [(eq_attr "type" "uncond_branch,call,sibcall")
125 (if_then_else (eq_attr "empty_delay_slot" "true")
126 (const_int 2)
127 (const_int 1))
128 (eq_attr "branch_type" "icc")
129 (if_then_else (match_operand 0 "noov_compare64_op" "")
130 (if_then_else (lt (pc) (match_dup 1))
131 (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
132 (if_then_else (eq_attr "empty_delay_slot" "true")
133 (const_int 2)
134 (const_int 1))
135 (if_then_else (eq_attr "empty_delay_slot" "true")
136 (const_int 4)
137 (const_int 3)))
138 (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000))
139 (if_then_else (eq_attr "empty_delay_slot" "true")
140 (const_int 2)
141 (const_int 1))
142 (if_then_else (eq_attr "empty_delay_slot" "true")
143 (const_int 4)
144 (const_int 3))))
145 (if_then_else (eq_attr "empty_delay_slot" "true")
146 (const_int 2)
147 (const_int 1)))
148 (eq_attr "branch_type" "fcc")
149 (if_then_else (match_operand 0 "fcc0_reg_operand" "")
150 (if_then_else (eq_attr "empty_delay_slot" "true")
151 (const_int 2)
152 (const_int 1))
153 (if_then_else (lt (pc) (match_dup 2))
154 (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
155 (if_then_else (eq_attr "empty_delay_slot" "true")
156 (const_int 2)
157 (const_int 1))
158 (if_then_else (eq_attr "empty_delay_slot" "true")
159 (const_int 4)
160 (const_int 3)))
161 (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
162 (if_then_else (eq_attr "empty_delay_slot" "true")
163 (const_int 2)
164 (const_int 1))
165 (if_then_else (eq_attr "empty_delay_slot" "true")
166 (const_int 4)
167 (const_int 3)))))
168 (eq_attr "branch_type" "reg")
169 (if_then_else (lt (pc) (match_dup 2))
170 (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
171 (if_then_else (eq_attr "empty_delay_slot" "true")
172 (const_int 2)
173 (const_int 1))
174 (if_then_else (eq_attr "empty_delay_slot" "true")
175 (const_int 4)
176 (const_int 3)))
177 (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
178 (if_then_else (eq_attr "empty_delay_slot" "true")
179 (const_int 2)
180 (const_int 1))
181 (if_then_else (eq_attr "empty_delay_slot" "true")
182 (const_int 4)
183 (const_int 3))))
184 ] (const_int 1)))
185
186 ;; FP precision.
187 (define_attr "fptype" "single,double" (const_string "single"))
188
189 ;; UltraSPARC-III integer load type.
190 (define_attr "us3load_type" "2cycle,3cycle" (const_string "2cycle"))
191
192 (define_asm_attributes
193 [(set_attr "length" "2")
194 (set_attr "type" "multi")])
195
196 ;; Attributes for instruction and branch scheduling
197
198 (define_attr "in_call_delay" "false,true"
199 (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
200 (const_string "false")
201 (eq_attr "type" "load,fpload,store,fpstore")
202 (if_then_else (eq_attr "length" "1")
203 (const_string "true")
204 (const_string "false"))]
205 (if_then_else (eq_attr "length" "1")
206 (const_string "true")
207 (const_string "false"))))
208
209 (define_delay (eq_attr "type" "call")
210 [(eq_attr "in_call_delay" "true") (nil) (nil)])
211
212 (define_attr "eligible_for_sibcall_delay" "false,true"
213 (symbol_ref "eligible_for_sibcall_delay (insn)"))
214
215 (define_delay (eq_attr "type" "sibcall")
216 [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])
217
218 (define_attr "leaf_function" "false,true"
219 (const (symbol_ref "current_function_uses_only_leaf_regs")))
220
221 ;; ??? Should implement the notion of predelay slots for floating point
222 ;; branches. This would allow us to remove the nop always inserted before
223 ;; a floating point branch.
224
225 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
226 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
227 ;; This is because doing so will add several pipeline stalls to the path
228 ;; that the load/store did not come from. Unfortunately, there is no way
229 ;; to prevent fill_eager_delay_slots from using load/store without completely
230 ;; disabling them. For the SPEC benchmark set, this is a serious lose,
231 ;; because it prevents us from moving back the final store of inner loops.
232
233 (define_attr "in_branch_delay" "false,true"
234 (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
235 (eq_attr "length" "1"))
236 (const_string "true")
237 (const_string "false")))
238
239 (define_attr "in_uncond_branch_delay" "false,true"
240 (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
241 (eq_attr "length" "1"))
242 (const_string "true")
243 (const_string "false")))
244
245 (define_attr "in_annul_branch_delay" "false,true"
246 (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
247 (eq_attr "length" "1"))
248 (const_string "true")
249 (const_string "false")))
250
251 (define_delay (eq_attr "type" "branch")
252 [(eq_attr "in_branch_delay" "true")
253 (nil) (eq_attr "in_annul_branch_delay" "true")])
254
255 (define_delay (eq_attr "type" "uncond_branch")
256 [(eq_attr "in_uncond_branch_delay" "true")
257 (nil) (nil)])
258
259 ;; Include SPARC DFA schedulers
260
261 (include "cypress.md")
262 (include "supersparc.md")
263 (include "hypersparc.md")
264 (include "sparclet.md")
265 (include "ultra1_2.md")
266 (include "ultra3.md")
267
268 \f
269 ;; Compare instructions.
270 ;; This controls RTL generation and register allocation.
271
272 ;; We generate RTL for comparisons and branches by having the cmpxx
273 ;; patterns store away the operands. Then, the scc and bcc patterns
274 ;; emit RTL for both the compare and the branch.
275 ;;
276 ;; We do this because we want to generate different code for an sne and
277 ;; seq insn. In those cases, if the second operand of the compare is not
278 ;; const0_rtx, we want to compute the xor of the two operands and test
279 ;; it against zero.
280 ;;
281 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
282 ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc
283 ;; insns that actually require more than one machine instruction.
284
285 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
286
287 (define_expand "cmpsi"
288 [(set (reg:CC 100)
289 (compare:CC (match_operand:SI 0 "register_operand" "")
290 (match_operand:SI 1 "arith_operand" "")))]
291 ""
292 {
293 sparc_compare_op0 = operands[0];
294 sparc_compare_op1 = operands[1];
295 DONE;
296 })
297
298 (define_expand "cmpdi"
299 [(set (reg:CCX 100)
300 (compare:CCX (match_operand:DI 0 "register_operand" "")
301 (match_operand:DI 1 "arith_double_operand" "")))]
302 "TARGET_ARCH64"
303 {
304 sparc_compare_op0 = operands[0];
305 sparc_compare_op1 = operands[1];
306 DONE;
307 })
308
309 (define_expand "cmpsf"
310 ;; The 96 here isn't ever used by anyone.
311 [(set (reg:CCFP 96)
312 (compare:CCFP (match_operand:SF 0 "register_operand" "")
313 (match_operand:SF 1 "register_operand" "")))]
314 "TARGET_FPU"
315 {
316 sparc_compare_op0 = operands[0];
317 sparc_compare_op1 = operands[1];
318 DONE;
319 })
320
321 (define_expand "cmpdf"
322 ;; The 96 here isn't ever used by anyone.
323 [(set (reg:CCFP 96)
324 (compare:CCFP (match_operand:DF 0 "register_operand" "")
325 (match_operand:DF 1 "register_operand" "")))]
326 "TARGET_FPU"
327 {
328 sparc_compare_op0 = operands[0];
329 sparc_compare_op1 = operands[1];
330 DONE;
331 })
332
333 (define_expand "cmptf"
334 ;; The 96 here isn't ever used by anyone.
335 [(set (reg:CCFP 96)
336 (compare:CCFP (match_operand:TF 0 "register_operand" "")
337 (match_operand:TF 1 "register_operand" "")))]
338 "TARGET_FPU"
339 {
340 sparc_compare_op0 = operands[0];
341 sparc_compare_op1 = operands[1];
342 DONE;
343 })
344
345 ;; Now the compare DEFINE_INSNs.
346
347 (define_insn "*cmpsi_insn"
348 [(set (reg:CC 100)
349 (compare:CC (match_operand:SI 0 "register_operand" "r")
350 (match_operand:SI 1 "arith_operand" "rI")))]
351 ""
352 "cmp\t%0, %1"
353 [(set_attr "type" "compare")])
354
355 (define_insn "*cmpdi_sp64"
356 [(set (reg:CCX 100)
357 (compare:CCX (match_operand:DI 0 "register_operand" "r")
358 (match_operand:DI 1 "arith_double_operand" "rHI")))]
359 "TARGET_ARCH64"
360 "cmp\t%0, %1"
361 [(set_attr "type" "compare")])
362
363 (define_insn "*cmpsf_fpe"
364 [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
365 (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
366 (match_operand:SF 2 "register_operand" "f")))]
367 "TARGET_FPU"
368 {
369 if (TARGET_V9)
370 return "fcmpes\t%0, %1, %2";
371 return "fcmpes\t%1, %2";
372 }
373 [(set_attr "type" "fpcmp")])
374
375 (define_insn "*cmpdf_fpe"
376 [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
377 (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
378 (match_operand:DF 2 "register_operand" "e")))]
379 "TARGET_FPU"
380 {
381 if (TARGET_V9)
382 return "fcmped\t%0, %1, %2";
383 return "fcmped\t%1, %2";
384 }
385 [(set_attr "type" "fpcmp")
386 (set_attr "fptype" "double")])
387
388 (define_insn "*cmptf_fpe"
389 [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
390 (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
391 (match_operand:TF 2 "register_operand" "e")))]
392 "TARGET_FPU && TARGET_HARD_QUAD"
393 {
394 if (TARGET_V9)
395 return "fcmpeq\t%0, %1, %2";
396 return "fcmpeq\t%1, %2";
397 }
398 [(set_attr "type" "fpcmp")])
399
400 (define_insn "*cmpsf_fp"
401 [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
402 (compare:CCFP (match_operand:SF 1 "register_operand" "f")
403 (match_operand:SF 2 "register_operand" "f")))]
404 "TARGET_FPU"
405 {
406 if (TARGET_V9)
407 return "fcmps\t%0, %1, %2";
408 return "fcmps\t%1, %2";
409 }
410 [(set_attr "type" "fpcmp")])
411
412 (define_insn "*cmpdf_fp"
413 [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
414 (compare:CCFP (match_operand:DF 1 "register_operand" "e")
415 (match_operand:DF 2 "register_operand" "e")))]
416 "TARGET_FPU"
417 {
418 if (TARGET_V9)
419 return "fcmpd\t%0, %1, %2";
420 return "fcmpd\t%1, %2";
421 }
422 [(set_attr "type" "fpcmp")
423 (set_attr "fptype" "double")])
424
425 (define_insn "*cmptf_fp"
426 [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
427 (compare:CCFP (match_operand:TF 1 "register_operand" "e")
428 (match_operand:TF 2 "register_operand" "e")))]
429 "TARGET_FPU && TARGET_HARD_QUAD"
430 {
431 if (TARGET_V9)
432 return "fcmpq\t%0, %1, %2";
433 return "fcmpq\t%1, %2";
434 }
435 [(set_attr "type" "fpcmp")])
436 \f
437 ;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this
438 ;; without jumps using the addx/subx instructions. For seq/sne on v9 we use
439 ;; the same code as v8 (the addx/subx method has more applications). The
440 ;; exception to this is "reg != 0" which can be done in one instruction on v9
441 ;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do
442 ;; branches.
443
444 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
445 ;; generate addcc/subcc instructions.
446
447 (define_expand "seqsi_special"
448 [(set (match_dup 3)
449 (xor:SI (match_operand:SI 1 "register_operand" "")
450 (match_operand:SI 2 "register_operand" "")))
451 (parallel [(set (match_operand:SI 0 "register_operand" "")
452 (eq:SI (match_dup 3) (const_int 0)))
453 (clobber (reg:CC 100))])]
454 ""
455 { operands[3] = gen_reg_rtx (SImode); })
456
457 (define_expand "seqdi_special"
458 [(set (match_dup 3)
459 (xor:DI (match_operand:DI 1 "register_operand" "")
460 (match_operand:DI 2 "register_operand" "")))
461 (set (match_operand:DI 0 "register_operand" "")
462 (eq:DI (match_dup 3) (const_int 0)))]
463 "TARGET_ARCH64"
464 { operands[3] = gen_reg_rtx (DImode); })
465
466 (define_expand "snesi_special"
467 [(set (match_dup 3)
468 (xor:SI (match_operand:SI 1 "register_operand" "")
469 (match_operand:SI 2 "register_operand" "")))
470 (parallel [(set (match_operand:SI 0 "register_operand" "")
471 (ne:SI (match_dup 3) (const_int 0)))
472 (clobber (reg:CC 100))])]
473 ""
474 { operands[3] = gen_reg_rtx (SImode); })
475
476 (define_expand "snedi_special"
477 [(set (match_dup 3)
478 (xor:DI (match_operand:DI 1 "register_operand" "")
479 (match_operand:DI 2 "register_operand" "")))
480 (set (match_operand:DI 0 "register_operand" "")
481 (ne:DI (match_dup 3) (const_int 0)))]
482 "TARGET_ARCH64"
483 { operands[3] = gen_reg_rtx (DImode); })
484
485 (define_expand "seqdi_special_trunc"
486 [(set (match_dup 3)
487 (xor:DI (match_operand:DI 1 "register_operand" "")
488 (match_operand:DI 2 "register_operand" "")))
489 (set (match_operand:SI 0 "register_operand" "")
490 (eq:SI (match_dup 3) (const_int 0)))]
491 "TARGET_ARCH64"
492 { operands[3] = gen_reg_rtx (DImode); })
493
494 (define_expand "snedi_special_trunc"
495 [(set (match_dup 3)
496 (xor:DI (match_operand:DI 1 "register_operand" "")
497 (match_operand:DI 2 "register_operand" "")))
498 (set (match_operand:SI 0 "register_operand" "")
499 (ne:SI (match_dup 3) (const_int 0)))]
500 "TARGET_ARCH64"
501 { operands[3] = gen_reg_rtx (DImode); })
502
503 (define_expand "seqsi_special_extend"
504 [(set (match_dup 3)
505 (xor:SI (match_operand:SI 1 "register_operand" "")
506 (match_operand:SI 2 "register_operand" "")))
507 (parallel [(set (match_operand:DI 0 "register_operand" "")
508 (eq:DI (match_dup 3) (const_int 0)))
509 (clobber (reg:CC 100))])]
510 "TARGET_ARCH64"
511 { operands[3] = gen_reg_rtx (SImode); })
512
513 (define_expand "snesi_special_extend"
514 [(set (match_dup 3)
515 (xor:SI (match_operand:SI 1 "register_operand" "")
516 (match_operand:SI 2 "register_operand" "")))
517 (parallel [(set (match_operand:DI 0 "register_operand" "")
518 (ne:DI (match_dup 3) (const_int 0)))
519 (clobber (reg:CC 100))])]
520 "TARGET_ARCH64"
521 { operands[3] = gen_reg_rtx (SImode); })
522
523 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
524 ;; However, the code handles both SImode and DImode.
525 (define_expand "seq"
526 [(set (match_operand:SI 0 "intreg_operand" "")
527 (eq:SI (match_dup 1) (const_int 0)))]
528 ""
529 {
530 if (GET_MODE (sparc_compare_op0) == SImode)
531 {
532 rtx pat;
533
534 if (GET_MODE (operands[0]) == SImode)
535 pat = gen_seqsi_special (operands[0], sparc_compare_op0,
536 sparc_compare_op1);
537 else if (! TARGET_ARCH64)
538 FAIL;
539 else
540 pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
541 sparc_compare_op1);
542 emit_insn (pat);
543 DONE;
544 }
545 else if (GET_MODE (sparc_compare_op0) == DImode)
546 {
547 rtx pat;
548
549 if (! TARGET_ARCH64)
550 FAIL;
551 else if (GET_MODE (operands[0]) == SImode)
552 pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
553 sparc_compare_op1);
554 else
555 pat = gen_seqdi_special (operands[0], sparc_compare_op0,
556 sparc_compare_op1);
557 emit_insn (pat);
558 DONE;
559 }
560 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
561 {
562 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
563 emit_jump_insn (gen_sne (operands[0]));
564 DONE;
565 }
566 else if (TARGET_V9)
567 {
568 if (gen_v9_scc (EQ, operands))
569 DONE;
570 /* fall through */
571 }
572 FAIL;
573 })
574
575 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
576 ;; However, the code handles both SImode and DImode.
577 (define_expand "sne"
578 [(set (match_operand:SI 0 "intreg_operand" "")
579 (ne:SI (match_dup 1) (const_int 0)))]
580 ""
581 {
582 if (GET_MODE (sparc_compare_op0) == SImode)
583 {
584 rtx pat;
585
586 if (GET_MODE (operands[0]) == SImode)
587 pat = gen_snesi_special (operands[0], sparc_compare_op0,
588 sparc_compare_op1);
589 else if (! TARGET_ARCH64)
590 FAIL;
591 else
592 pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
593 sparc_compare_op1);
594 emit_insn (pat);
595 DONE;
596 }
597 else if (GET_MODE (sparc_compare_op0) == DImode)
598 {
599 rtx pat;
600
601 if (! TARGET_ARCH64)
602 FAIL;
603 else if (GET_MODE (operands[0]) == SImode)
604 pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
605 sparc_compare_op1);
606 else
607 pat = gen_snedi_special (operands[0], sparc_compare_op0,
608 sparc_compare_op1);
609 emit_insn (pat);
610 DONE;
611 }
612 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
613 {
614 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
615 emit_jump_insn (gen_sne (operands[0]));
616 DONE;
617 }
618 else if (TARGET_V9)
619 {
620 if (gen_v9_scc (NE, operands))
621 DONE;
622 /* fall through */
623 }
624 FAIL;
625 })
626
627 (define_expand "sgt"
628 [(set (match_operand:SI 0 "intreg_operand" "")
629 (gt:SI (match_dup 1) (const_int 0)))]
630 ""
631 {
632 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
633 {
634 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
635 emit_jump_insn (gen_sne (operands[0]));
636 DONE;
637 }
638 else if (TARGET_V9)
639 {
640 if (gen_v9_scc (GT, operands))
641 DONE;
642 /* fall through */
643 }
644 FAIL;
645 })
646
647 (define_expand "slt"
648 [(set (match_operand:SI 0 "intreg_operand" "")
649 (lt:SI (match_dup 1) (const_int 0)))]
650 ""
651 {
652 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
653 {
654 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
655 emit_jump_insn (gen_sne (operands[0]));
656 DONE;
657 }
658 else if (TARGET_V9)
659 {
660 if (gen_v9_scc (LT, operands))
661 DONE;
662 /* fall through */
663 }
664 FAIL;
665 })
666
667 (define_expand "sge"
668 [(set (match_operand:SI 0 "intreg_operand" "")
669 (ge:SI (match_dup 1) (const_int 0)))]
670 ""
671 {
672 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
673 {
674 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
675 emit_jump_insn (gen_sne (operands[0]));
676 DONE;
677 }
678 else if (TARGET_V9)
679 {
680 if (gen_v9_scc (GE, operands))
681 DONE;
682 /* fall through */
683 }
684 FAIL;
685 })
686
687 (define_expand "sle"
688 [(set (match_operand:SI 0 "intreg_operand" "")
689 (le:SI (match_dup 1) (const_int 0)))]
690 ""
691 {
692 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
693 {
694 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
695 emit_jump_insn (gen_sne (operands[0]));
696 DONE;
697 }
698 else if (TARGET_V9)
699 {
700 if (gen_v9_scc (LE, operands))
701 DONE;
702 /* fall through */
703 }
704 FAIL;
705 })
706
707 (define_expand "sgtu"
708 [(set (match_operand:SI 0 "intreg_operand" "")
709 (gtu:SI (match_dup 1) (const_int 0)))]
710 ""
711 {
712 if (! TARGET_V9)
713 {
714 rtx tem, pat;
715
716 /* We can do ltu easily, so if both operands are registers, swap them and
717 do a LTU. */
718 if ((GET_CODE (sparc_compare_op0) == REG
719 || GET_CODE (sparc_compare_op0) == SUBREG)
720 && (GET_CODE (sparc_compare_op1) == REG
721 || GET_CODE (sparc_compare_op1) == SUBREG))
722 {
723 tem = sparc_compare_op0;
724 sparc_compare_op0 = sparc_compare_op1;
725 sparc_compare_op1 = tem;
726 pat = gen_sltu (operands[0]);
727 if (pat == NULL_RTX)
728 FAIL;
729 emit_insn (pat);
730 DONE;
731 }
732 }
733 else
734 {
735 if (gen_v9_scc (GTU, operands))
736 DONE;
737 }
738 FAIL;
739 })
740
741 (define_expand "sltu"
742 [(set (match_operand:SI 0 "intreg_operand" "")
743 (ltu:SI (match_dup 1) (const_int 0)))]
744 ""
745 {
746 if (TARGET_V9)
747 {
748 if (gen_v9_scc (LTU, operands))
749 DONE;
750 }
751 operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
752 })
753
754 (define_expand "sgeu"
755 [(set (match_operand:SI 0 "intreg_operand" "")
756 (geu:SI (match_dup 1) (const_int 0)))]
757 ""
758 {
759 if (TARGET_V9)
760 {
761 if (gen_v9_scc (GEU, operands))
762 DONE;
763 }
764 operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
765 })
766
767 (define_expand "sleu"
768 [(set (match_operand:SI 0 "intreg_operand" "")
769 (leu:SI (match_dup 1) (const_int 0)))]
770 ""
771 {
772 if (! TARGET_V9)
773 {
774 rtx tem, pat;
775
776 /* We can do geu easily, so if both operands are registers, swap them and
777 do a GEU. */
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 pat = gen_sgeu (operands[0]);
787 if (pat == NULL_RTX)
788 FAIL;
789 emit_insn (pat);
790 DONE;
791 }
792 }
793 else
794 {
795 if (gen_v9_scc (LEU, operands))
796 DONE;
797 }
798 FAIL;
799 })
800
801 ;; Now the DEFINE_INSNs for the scc cases.
802
803 ;; The SEQ and SNE patterns are special because they can be done
804 ;; without any branching and do not involve a COMPARE. We want
805 ;; them to always use the splitz below so the results can be
806 ;; scheduled.
807
808 (define_insn_and_split "*snesi_zero"
809 [(set (match_operand:SI 0 "register_operand" "=r")
810 (ne:SI (match_operand:SI 1 "register_operand" "r")
811 (const_int 0)))
812 (clobber (reg:CC 100))]
813 ""
814 "#"
815 ""
816 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
817 (const_int 0)))
818 (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
819 ""
820 [(set_attr "length" "2")])
821
822 (define_insn_and_split "*neg_snesi_zero"
823 [(set (match_operand:SI 0 "register_operand" "=r")
824 (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
825 (const_int 0))))
826 (clobber (reg:CC 100))]
827 ""
828 "#"
829 ""
830 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
831 (const_int 0)))
832 (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
833 ""
834 [(set_attr "length" "2")])
835
836 (define_insn_and_split "*snesi_zero_extend"
837 [(set (match_operand:DI 0 "register_operand" "=r")
838 (ne:DI (match_operand:SI 1 "register_operand" "r")
839 (const_int 0)))
840 (clobber (reg:CC 100))]
841 "TARGET_ARCH64"
842 "#"
843 "&& 1"
844 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
845 (match_dup 1))
846 (const_int 0)))
847 (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
848 (const_int 0))
849 (ltu:SI (reg:CC_NOOV 100)
850 (const_int 0)))))]
851 ""
852 [(set_attr "length" "2")])
853
854 (define_insn_and_split "*snedi_zero"
855 [(set (match_operand:DI 0 "register_operand" "=&r")
856 (ne:DI (match_operand:DI 1 "register_operand" "r")
857 (const_int 0)))]
858 "TARGET_ARCH64"
859 "#"
860 "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
861 [(set (match_dup 0) (const_int 0))
862 (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
863 (const_int 0))
864 (const_int 1)
865 (match_dup 0)))]
866 ""
867 [(set_attr "length" "2")])
868
869 (define_insn_and_split "*neg_snedi_zero"
870 [(set (match_operand:DI 0 "register_operand" "=&r")
871 (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
872 (const_int 0))))]
873 "TARGET_ARCH64"
874 "#"
875 "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
876 [(set (match_dup 0) (const_int 0))
877 (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
878 (const_int 0))
879 (const_int -1)
880 (match_dup 0)))]
881 ""
882 [(set_attr "length" "2")])
883
884 (define_insn_and_split "*snedi_zero_trunc"
885 [(set (match_operand:SI 0 "register_operand" "=&r")
886 (ne:SI (match_operand:DI 1 "register_operand" "r")
887 (const_int 0)))]
888 "TARGET_ARCH64"
889 "#"
890 "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
891 [(set (match_dup 0) (const_int 0))
892 (set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
893 (const_int 0))
894 (const_int 1)
895 (match_dup 0)))]
896 ""
897 [(set_attr "length" "2")])
898
899 (define_insn_and_split "*seqsi_zero"
900 [(set (match_operand:SI 0 "register_operand" "=r")
901 (eq:SI (match_operand:SI 1 "register_operand" "r")
902 (const_int 0)))
903 (clobber (reg:CC 100))]
904 ""
905 "#"
906 ""
907 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
908 (const_int 0)))
909 (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
910 ""
911 [(set_attr "length" "2")])
912
913 (define_insn_and_split "*neg_seqsi_zero"
914 [(set (match_operand:SI 0 "register_operand" "=r")
915 (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
916 (const_int 0))))
917 (clobber (reg:CC 100))]
918 ""
919 "#"
920 ""
921 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
922 (const_int 0)))
923 (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
924 ""
925 [(set_attr "length" "2")])
926
927 (define_insn_and_split "*seqsi_zero_extend"
928 [(set (match_operand:DI 0 "register_operand" "=r")
929 (eq:DI (match_operand:SI 1 "register_operand" "r")
930 (const_int 0)))
931 (clobber (reg:CC 100))]
932 "TARGET_ARCH64"
933 "#"
934 "&& 1"
935 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
936 (match_dup 1))
937 (const_int 0)))
938 (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
939 (const_int -1))
940 (ltu:SI (reg:CC_NOOV 100)
941 (const_int 0)))))]
942 ""
943 [(set_attr "length" "2")])
944
945 (define_insn_and_split "*seqdi_zero"
946 [(set (match_operand:DI 0 "register_operand" "=&r")
947 (eq:DI (match_operand:DI 1 "register_operand" "r")
948 (const_int 0)))]
949 "TARGET_ARCH64"
950 "#"
951 "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
952 [(set (match_dup 0) (const_int 0))
953 (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
954 (const_int 0))
955 (const_int 1)
956 (match_dup 0)))]
957 ""
958 [(set_attr "length" "2")])
959
960 (define_insn_and_split "*neg_seqdi_zero"
961 [(set (match_operand:DI 0 "register_operand" "=&r")
962 (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
963 (const_int 0))))]
964 "TARGET_ARCH64"
965 "#"
966 "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
967 [(set (match_dup 0) (const_int 0))
968 (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
969 (const_int 0))
970 (const_int -1)
971 (match_dup 0)))]
972 ""
973 [(set_attr "length" "2")])
974
975 (define_insn_and_split "*seqdi_zero_trunc"
976 [(set (match_operand:SI 0 "register_operand" "=&r")
977 (eq:SI (match_operand:DI 1 "register_operand" "r")
978 (const_int 0)))]
979 "TARGET_ARCH64"
980 "#"
981 "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
982 [(set (match_dup 0) (const_int 0))
983 (set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
984 (const_int 0))
985 (const_int 1)
986 (match_dup 0)))]
987 ""
988 [(set_attr "length" "2")])
989
990 ;; We can also do (x + (i == 0)) and related, so put them in.
991 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
992 ;; versions for v9.
993
994 (define_insn_and_split "*x_plus_i_ne_0"
995 [(set (match_operand:SI 0 "register_operand" "=r")
996 (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
997 (const_int 0))
998 (match_operand:SI 2 "register_operand" "r")))
999 (clobber (reg:CC 100))]
1000 ""
1001 "#"
1002 ""
1003 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1004 (const_int 0)))
1005 (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1006 (match_dup 2)))]
1007 ""
1008 [(set_attr "length" "2")])
1009
1010 (define_insn_and_split "*x_minus_i_ne_0"
1011 [(set (match_operand:SI 0 "register_operand" "=r")
1012 (minus:SI (match_operand:SI 2 "register_operand" "r")
1013 (ne:SI (match_operand:SI 1 "register_operand" "r")
1014 (const_int 0))))
1015 (clobber (reg:CC 100))]
1016 ""
1017 "#"
1018 ""
1019 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1020 (const_int 0)))
1021 (set (match_dup 0) (minus:SI (match_dup 2)
1022 (ltu:SI (reg:CC 100) (const_int 0))))]
1023 ""
1024 [(set_attr "length" "2")])
1025
1026 (define_insn_and_split "*x_plus_i_eq_0"
1027 [(set (match_operand:SI 0 "register_operand" "=r")
1028 (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1029 (const_int 0))
1030 (match_operand:SI 2 "register_operand" "r")))
1031 (clobber (reg:CC 100))]
1032 ""
1033 "#"
1034 ""
1035 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1036 (const_int 0)))
1037 (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1038 (match_dup 2)))]
1039 ""
1040 [(set_attr "length" "2")])
1041
1042 (define_insn_and_split "*x_minus_i_eq_0"
1043 [(set (match_operand:SI 0 "register_operand" "=r")
1044 (minus:SI (match_operand:SI 2 "register_operand" "r")
1045 (eq:SI (match_operand:SI 1 "register_operand" "r")
1046 (const_int 0))))
1047 (clobber (reg:CC 100))]
1048 ""
1049 "#"
1050 ""
1051 [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1052 (const_int 0)))
1053 (set (match_dup 0) (minus:SI (match_dup 2)
1054 (geu:SI (reg:CC 100) (const_int 0))))]
1055 ""
1056 [(set_attr "length" "2")])
1057
1058 ;; We can also do GEU and LTU directly, but these operate after a compare.
1059 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1060 ;; versions for v9.
1061
1062 (define_insn "*sltu_insn"
1063 [(set (match_operand:SI 0 "register_operand" "=r")
1064 (ltu:SI (reg:CC 100) (const_int 0)))]
1065 ""
1066 "addx\t%%g0, 0, %0"
1067 [(set_attr "type" "ialuX")])
1068
1069 (define_insn "*neg_sltu_insn"
1070 [(set (match_operand:SI 0 "register_operand" "=r")
1071 (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1072 ""
1073 "subx\t%%g0, 0, %0"
1074 [(set_attr "type" "ialuX")])
1075
1076 ;; ??? Combine should canonicalize these next two to the same pattern.
1077 (define_insn "*neg_sltu_minus_x"
1078 [(set (match_operand:SI 0 "register_operand" "=r")
1079 (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1080 (match_operand:SI 1 "arith_operand" "rI")))]
1081 ""
1082 "subx\t%%g0, %1, %0"
1083 [(set_attr "type" "ialuX")])
1084
1085 (define_insn "*neg_sltu_plus_x"
1086 [(set (match_operand:SI 0 "register_operand" "=r")
1087 (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1088 (match_operand:SI 1 "arith_operand" "rI"))))]
1089 ""
1090 "subx\t%%g0, %1, %0"
1091 [(set_attr "type" "ialuX")])
1092
1093 (define_insn "*sgeu_insn"
1094 [(set (match_operand:SI 0 "register_operand" "=r")
1095 (geu:SI (reg:CC 100) (const_int 0)))]
1096 ""
1097 "subx\t%%g0, -1, %0"
1098 [(set_attr "type" "ialuX")])
1099
1100 (define_insn "*neg_sgeu_insn"
1101 [(set (match_operand:SI 0 "register_operand" "=r")
1102 (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1103 ""
1104 "addx\t%%g0, -1, %0"
1105 [(set_attr "type" "ialuX")])
1106
1107 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1108 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1109 ;; versions for v9.
1110
1111 (define_insn "*sltu_plus_x"
1112 [(set (match_operand:SI 0 "register_operand" "=r")
1113 (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1114 (match_operand:SI 1 "arith_operand" "rI")))]
1115 ""
1116 "addx\t%%g0, %1, %0"
1117 [(set_attr "type" "ialuX")])
1118
1119 (define_insn "*sltu_plus_x_plus_y"
1120 [(set (match_operand:SI 0 "register_operand" "=r")
1121 (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1122 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1123 (match_operand:SI 2 "arith_operand" "rI"))))]
1124 ""
1125 "addx\t%1, %2, %0"
1126 [(set_attr "type" "ialuX")])
1127
1128 (define_insn "*x_minus_sltu"
1129 [(set (match_operand:SI 0 "register_operand" "=r")
1130 (minus:SI (match_operand:SI 1 "register_operand" "r")
1131 (ltu:SI (reg:CC 100) (const_int 0))))]
1132 ""
1133 "subx\t%1, 0, %0"
1134 [(set_attr "type" "ialuX")])
1135
1136 ;; ??? Combine should canonicalize these next two to the same pattern.
1137 (define_insn "*x_minus_y_minus_sltu"
1138 [(set (match_operand:SI 0 "register_operand" "=r")
1139 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1140 (match_operand:SI 2 "arith_operand" "rI"))
1141 (ltu:SI (reg:CC 100) (const_int 0))))]
1142 ""
1143 "subx\t%r1, %2, %0"
1144 [(set_attr "type" "ialuX")])
1145
1146 (define_insn "*x_minus_sltu_plus_y"
1147 [(set (match_operand:SI 0 "register_operand" "=r")
1148 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1149 (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1150 (match_operand:SI 2 "arith_operand" "rI"))))]
1151 ""
1152 "subx\t%r1, %2, %0"
1153 [(set_attr "type" "ialuX")])
1154
1155 (define_insn "*sgeu_plus_x"
1156 [(set (match_operand:SI 0 "register_operand" "=r")
1157 (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1158 (match_operand:SI 1 "register_operand" "r")))]
1159 ""
1160 "subx\t%1, -1, %0"
1161 [(set_attr "type" "ialuX")])
1162
1163 (define_insn "*x_minus_sgeu"
1164 [(set (match_operand:SI 0 "register_operand" "=r")
1165 (minus:SI (match_operand:SI 1 "register_operand" "r")
1166 (geu:SI (reg:CC 100) (const_int 0))))]
1167 ""
1168 "addx\t%1, -1, %0"
1169 [(set_attr "type" "ialuX")])
1170
1171 (define_split
1172 [(set (match_operand:SI 0 "register_operand" "")
1173 (match_operator:SI 2 "noov_compare_op"
1174 [(match_operand 1 "icc_or_fcc_reg_operand" "")
1175 (const_int 0)]))]
1176 ;; 32 bit LTU/GEU are better implemented using addx/subx
1177 "TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG
1178 && (GET_MODE (operands[1]) == CCXmode
1179 || (GET_CODE (operands[2]) != LTU && GET_CODE (operands[2]) != GEU))"
1180 [(set (match_dup 0) (const_int 0))
1181 (set (match_dup 0)
1182 (if_then_else:SI (match_op_dup:SI 2 [(match_dup 1) (const_int 0)])
1183 (const_int 1)
1184 (match_dup 0)))]
1185 "")
1186
1187 \f
1188 ;; These control RTL generation for conditional jump insns
1189
1190 ;; The quad-word fp compare library routines all return nonzero to indicate
1191 ;; true, which is different from the equivalent libgcc routines, so we must
1192 ;; handle them specially here.
1193
1194 (define_expand "beq"
1195 [(set (pc)
1196 (if_then_else (eq (match_dup 1) (const_int 0))
1197 (label_ref (match_operand 0 "" ""))
1198 (pc)))]
1199 ""
1200 {
1201 if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1202 && GET_CODE (sparc_compare_op0) == REG
1203 && GET_MODE (sparc_compare_op0) == DImode)
1204 {
1205 emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1206 DONE;
1207 }
1208 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1209 {
1210 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1211 emit_jump_insn (gen_bne (operands[0]));
1212 DONE;
1213 }
1214 operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1215 })
1216
1217 (define_expand "bne"
1218 [(set (pc)
1219 (if_then_else (ne (match_dup 1) (const_int 0))
1220 (label_ref (match_operand 0 "" ""))
1221 (pc)))]
1222 ""
1223 {
1224 if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1225 && GET_CODE (sparc_compare_op0) == REG
1226 && GET_MODE (sparc_compare_op0) == DImode)
1227 {
1228 emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1229 DONE;
1230 }
1231 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1232 {
1233 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1234 emit_jump_insn (gen_bne (operands[0]));
1235 DONE;
1236 }
1237 operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1238 })
1239
1240 (define_expand "bgt"
1241 [(set (pc)
1242 (if_then_else (gt (match_dup 1) (const_int 0))
1243 (label_ref (match_operand 0 "" ""))
1244 (pc)))]
1245 ""
1246 {
1247 if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1248 && GET_CODE (sparc_compare_op0) == REG
1249 && GET_MODE (sparc_compare_op0) == DImode)
1250 {
1251 emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1252 DONE;
1253 }
1254 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1255 {
1256 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1257 emit_jump_insn (gen_bne (operands[0]));
1258 DONE;
1259 }
1260 operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1261 })
1262
1263 (define_expand "bgtu"
1264 [(set (pc)
1265 (if_then_else (gtu (match_dup 1) (const_int 0))
1266 (label_ref (match_operand 0 "" ""))
1267 (pc)))]
1268 ""
1269 {
1270 operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1271 })
1272
1273 (define_expand "blt"
1274 [(set (pc)
1275 (if_then_else (lt (match_dup 1) (const_int 0))
1276 (label_ref (match_operand 0 "" ""))
1277 (pc)))]
1278 ""
1279 {
1280 if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1281 && GET_CODE (sparc_compare_op0) == REG
1282 && GET_MODE (sparc_compare_op0) == DImode)
1283 {
1284 emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1285 DONE;
1286 }
1287 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1288 {
1289 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1290 emit_jump_insn (gen_bne (operands[0]));
1291 DONE;
1292 }
1293 operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1294 })
1295
1296 (define_expand "bltu"
1297 [(set (pc)
1298 (if_then_else (ltu (match_dup 1) (const_int 0))
1299 (label_ref (match_operand 0 "" ""))
1300 (pc)))]
1301 ""
1302 {
1303 operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1304 })
1305
1306 (define_expand "bge"
1307 [(set (pc)
1308 (if_then_else (ge (match_dup 1) (const_int 0))
1309 (label_ref (match_operand 0 "" ""))
1310 (pc)))]
1311 ""
1312 {
1313 if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1314 && GET_CODE (sparc_compare_op0) == REG
1315 && GET_MODE (sparc_compare_op0) == DImode)
1316 {
1317 emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1318 DONE;
1319 }
1320 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1321 {
1322 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1323 emit_jump_insn (gen_bne (operands[0]));
1324 DONE;
1325 }
1326 operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1327 })
1328
1329 (define_expand "bgeu"
1330 [(set (pc)
1331 (if_then_else (geu (match_dup 1) (const_int 0))
1332 (label_ref (match_operand 0 "" ""))
1333 (pc)))]
1334 ""
1335 {
1336 operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1337 })
1338
1339 (define_expand "ble"
1340 [(set (pc)
1341 (if_then_else (le (match_dup 1) (const_int 0))
1342 (label_ref (match_operand 0 "" ""))
1343 (pc)))]
1344 ""
1345 {
1346 if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1347 && GET_CODE (sparc_compare_op0) == REG
1348 && GET_MODE (sparc_compare_op0) == DImode)
1349 {
1350 emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1351 DONE;
1352 }
1353 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1354 {
1355 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1356 emit_jump_insn (gen_bne (operands[0]));
1357 DONE;
1358 }
1359 operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1360 })
1361
1362 (define_expand "bleu"
1363 [(set (pc)
1364 (if_then_else (leu (match_dup 1) (const_int 0))
1365 (label_ref (match_operand 0 "" ""))
1366 (pc)))]
1367 ""
1368 {
1369 operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1370 })
1371
1372 (define_expand "bunordered"
1373 [(set (pc)
1374 (if_then_else (unordered (match_dup 1) (const_int 0))
1375 (label_ref (match_operand 0 "" ""))
1376 (pc)))]
1377 ""
1378 {
1379 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1380 {
1381 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
1382 UNORDERED);
1383 emit_jump_insn (gen_beq (operands[0]));
1384 DONE;
1385 }
1386 operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
1387 sparc_compare_op1);
1388 })
1389
1390 (define_expand "bordered"
1391 [(set (pc)
1392 (if_then_else (ordered (match_dup 1) (const_int 0))
1393 (label_ref (match_operand 0 "" ""))
1394 (pc)))]
1395 ""
1396 {
1397 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1398 {
1399 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
1400 emit_jump_insn (gen_bne (operands[0]));
1401 DONE;
1402 }
1403 operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
1404 sparc_compare_op1);
1405 })
1406
1407 (define_expand "bungt"
1408 [(set (pc)
1409 (if_then_else (ungt (match_dup 1) (const_int 0))
1410 (label_ref (match_operand 0 "" ""))
1411 (pc)))]
1412 ""
1413 {
1414 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1415 {
1416 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
1417 emit_jump_insn (gen_bgt (operands[0]));
1418 DONE;
1419 }
1420 operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
1421 })
1422
1423 (define_expand "bunlt"
1424 [(set (pc)
1425 (if_then_else (unlt (match_dup 1) (const_int 0))
1426 (label_ref (match_operand 0 "" ""))
1427 (pc)))]
1428 ""
1429 {
1430 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1431 {
1432 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
1433 emit_jump_insn (gen_bne (operands[0]));
1434 DONE;
1435 }
1436 operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
1437 })
1438
1439 (define_expand "buneq"
1440 [(set (pc)
1441 (if_then_else (uneq (match_dup 1) (const_int 0))
1442 (label_ref (match_operand 0 "" ""))
1443 (pc)))]
1444 ""
1445 {
1446 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1447 {
1448 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
1449 emit_jump_insn (gen_beq (operands[0]));
1450 DONE;
1451 }
1452 operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
1453 })
1454
1455 (define_expand "bunge"
1456 [(set (pc)
1457 (if_then_else (unge (match_dup 1) (const_int 0))
1458 (label_ref (match_operand 0 "" ""))
1459 (pc)))]
1460 ""
1461 {
1462 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1463 {
1464 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
1465 emit_jump_insn (gen_bne (operands[0]));
1466 DONE;
1467 }
1468 operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
1469 })
1470
1471 (define_expand "bunle"
1472 [(set (pc)
1473 (if_then_else (unle (match_dup 1) (const_int 0))
1474 (label_ref (match_operand 0 "" ""))
1475 (pc)))]
1476 ""
1477 {
1478 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1479 {
1480 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
1481 emit_jump_insn (gen_bne (operands[0]));
1482 DONE;
1483 }
1484 operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
1485 })
1486
1487 (define_expand "bltgt"
1488 [(set (pc)
1489 (if_then_else (ltgt (match_dup 1) (const_int 0))
1490 (label_ref (match_operand 0 "" ""))
1491 (pc)))]
1492 ""
1493 {
1494 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1495 {
1496 sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
1497 emit_jump_insn (gen_bne (operands[0]));
1498 DONE;
1499 }
1500 operands[1] = gen_compare_reg (LTGT, sparc_compare_op0, sparc_compare_op1);
1501 })
1502 \f
1503 ;; Now match both normal and inverted jump.
1504
1505 ;; XXX fpcmp nop braindamage
1506 (define_insn "*normal_branch"
1507 [(set (pc)
1508 (if_then_else (match_operator 0 "noov_compare_op"
1509 [(reg 100) (const_int 0)])
1510 (label_ref (match_operand 1 "" ""))
1511 (pc)))]
1512 ""
1513 {
1514 return output_cbranch (operands[0], operands[1], 1, 0,
1515 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1516 ! final_sequence, insn);
1517 }
1518 [(set_attr "type" "branch")
1519 (set_attr "branch_type" "icc")])
1520
1521 ;; XXX fpcmp nop braindamage
1522 (define_insn "*inverted_branch"
1523 [(set (pc)
1524 (if_then_else (match_operator 0 "noov_compare_op"
1525 [(reg 100) (const_int 0)])
1526 (pc)
1527 (label_ref (match_operand 1 "" ""))))]
1528 ""
1529 {
1530 return output_cbranch (operands[0], operands[1], 1, 1,
1531 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1532 ! final_sequence, insn);
1533 }
1534 [(set_attr "type" "branch")
1535 (set_attr "branch_type" "icc")])
1536
1537 ;; XXX fpcmp nop braindamage
1538 (define_insn "*normal_fp_branch"
1539 [(set (pc)
1540 (if_then_else (match_operator 1 "comparison_operator"
1541 [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1542 (const_int 0)])
1543 (label_ref (match_operand 2 "" ""))
1544 (pc)))]
1545 ""
1546 {
1547 return output_cbranch (operands[1], operands[2], 2, 0,
1548 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1549 ! final_sequence, insn);
1550 }
1551 [(set_attr "type" "branch")
1552 (set_attr "branch_type" "fcc")])
1553
1554 ;; XXX fpcmp nop braindamage
1555 (define_insn "*inverted_fp_branch"
1556 [(set (pc)
1557 (if_then_else (match_operator 1 "comparison_operator"
1558 [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1559 (const_int 0)])
1560 (pc)
1561 (label_ref (match_operand 2 "" ""))))]
1562 ""
1563 {
1564 return output_cbranch (operands[1], operands[2], 2, 1,
1565 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1566 ! final_sequence, insn);
1567 }
1568 [(set_attr "type" "branch")
1569 (set_attr "branch_type" "fcc")])
1570
1571 ;; XXX fpcmp nop braindamage
1572 (define_insn "*normal_fpe_branch"
1573 [(set (pc)
1574 (if_then_else (match_operator 1 "comparison_operator"
1575 [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1576 (const_int 0)])
1577 (label_ref (match_operand 2 "" ""))
1578 (pc)))]
1579 ""
1580 {
1581 return output_cbranch (operands[1], operands[2], 2, 0,
1582 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1583 ! final_sequence, insn);
1584 }
1585 [(set_attr "type" "branch")
1586 (set_attr "branch_type" "fcc")])
1587
1588 ;; XXX fpcmp nop braindamage
1589 (define_insn "*inverted_fpe_branch"
1590 [(set (pc)
1591 (if_then_else (match_operator 1 "comparison_operator"
1592 [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1593 (const_int 0)])
1594 (pc)
1595 (label_ref (match_operand 2 "" ""))))]
1596 ""
1597 {
1598 return output_cbranch (operands[1], operands[2], 2, 1,
1599 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1600 ! final_sequence, insn);
1601 }
1602 [(set_attr "type" "branch")
1603 (set_attr "branch_type" "fcc")])
1604
1605 ;; SPARC V9-specific jump insns. None of these are guaranteed to be
1606 ;; in the architecture.
1607
1608 ;; There are no 32 bit brreg insns.
1609
1610 ;; XXX
1611 (define_insn "*normal_int_branch_sp64"
1612 [(set (pc)
1613 (if_then_else (match_operator 0 "v9_regcmp_op"
1614 [(match_operand:DI 1 "register_operand" "r")
1615 (const_int 0)])
1616 (label_ref (match_operand 2 "" ""))
1617 (pc)))]
1618 "TARGET_ARCH64"
1619 {
1620 return output_v9branch (operands[0], operands[2], 1, 2, 0,
1621 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1622 ! final_sequence, insn);
1623 }
1624 [(set_attr "type" "branch")
1625 (set_attr "branch_type" "reg")])
1626
1627 ;; XXX
1628 (define_insn "*inverted_int_branch_sp64"
1629 [(set (pc)
1630 (if_then_else (match_operator 0 "v9_regcmp_op"
1631 [(match_operand:DI 1 "register_operand" "r")
1632 (const_int 0)])
1633 (pc)
1634 (label_ref (match_operand 2 "" ""))))]
1635 "TARGET_ARCH64"
1636 {
1637 return output_v9branch (operands[0], operands[2], 1, 2, 1,
1638 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1639 ! final_sequence, insn);
1640 }
1641 [(set_attr "type" "branch")
1642 (set_attr "branch_type" "reg")])
1643 \f
1644 ;; Load program counter insns.
1645
1646 (define_insn "get_pc"
1647 [(clobber (reg:SI 15))
1648 (set (match_operand 0 "register_operand" "=r")
1649 (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] UNSPEC_GET_PC))]
1650 "flag_pic && REGNO (operands[0]) == 23"
1651 "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\tadd\t%0, %%lo(%a1+4), %0"
1652 [(set_attr "type" "multi")
1653 (set_attr "length" "3")])
1654
1655 \f
1656 ;; Move instructions
1657
1658 (define_expand "movqi"
1659 [(set (match_operand:QI 0 "general_operand" "")
1660 (match_operand:QI 1 "general_operand" ""))]
1661 ""
1662 {
1663 /* Working with CONST_INTs is easier, so convert
1664 a double if needed. */
1665 if (GET_CODE (operands[1]) == CONST_DOUBLE)
1666 {
1667 operands[1] = GEN_INT (trunc_int_for_mode
1668 (CONST_DOUBLE_LOW (operands[1]), QImode));
1669 }
1670
1671 /* Handle sets of MEM first. */
1672 if (GET_CODE (operands[0]) == MEM)
1673 {
1674 if (reg_or_0_operand (operands[1], QImode))
1675 goto movqi_is_ok;
1676
1677 if (! reload_in_progress)
1678 {
1679 operands[0] = validize_mem (operands[0]);
1680 operands[1] = force_reg (QImode, operands[1]);
1681 }
1682 }
1683
1684 /* Fixup PIC cases. */
1685 if (flag_pic)
1686 {
1687 if (CONSTANT_P (operands[1])
1688 && pic_address_needs_scratch (operands[1]))
1689 operands[1] = legitimize_pic_address (operands[1], QImode, 0);
1690
1691 if (symbolic_operand (operands[1], QImode))
1692 {
1693 operands[1] = legitimize_pic_address (operands[1],
1694 QImode,
1695 (reload_in_progress ?
1696 operands[0] :
1697 NULL_RTX));
1698 goto movqi_is_ok;
1699 }
1700 }
1701
1702 /* All QI constants require only one insn, so proceed. */
1703
1704 movqi_is_ok:
1705 ;
1706 })
1707
1708 (define_insn "*movqi_insn"
1709 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
1710 (match_operand:QI 1 "input_operand" "rI,m,rJ"))]
1711 "(register_operand (operands[0], QImode)
1712 || reg_or_0_operand (operands[1], QImode))"
1713 "@
1714 mov\t%1, %0
1715 ldub\t%1, %0
1716 stb\t%r1, %0"
1717 [(set_attr "type" "*,load,store")
1718 (set_attr "us3load_type" "*,3cycle,*")])
1719
1720 (define_expand "movhi"
1721 [(set (match_operand:HI 0 "general_operand" "")
1722 (match_operand:HI 1 "general_operand" ""))]
1723 ""
1724 {
1725 /* Working with CONST_INTs is easier, so convert
1726 a double if needed. */
1727 if (GET_CODE (operands[1]) == CONST_DOUBLE)
1728 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
1729
1730 /* Handle sets of MEM first. */
1731 if (GET_CODE (operands[0]) == MEM)
1732 {
1733 if (reg_or_0_operand (operands[1], HImode))
1734 goto movhi_is_ok;
1735
1736 if (! reload_in_progress)
1737 {
1738 operands[0] = validize_mem (operands[0]);
1739 operands[1] = force_reg (HImode, operands[1]);
1740 }
1741 }
1742
1743 /* Fixup PIC cases. */
1744 if (flag_pic)
1745 {
1746 if (CONSTANT_P (operands[1])
1747 && pic_address_needs_scratch (operands[1]))
1748 operands[1] = legitimize_pic_address (operands[1], HImode, 0);
1749
1750 if (symbolic_operand (operands[1], HImode))
1751 {
1752 operands[1] = legitimize_pic_address (operands[1],
1753 HImode,
1754 (reload_in_progress ?
1755 operands[0] :
1756 NULL_RTX));
1757 goto movhi_is_ok;
1758 }
1759 }
1760
1761 /* This makes sure we will not get rematched due to splittage. */
1762 if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
1763 ;
1764 else if (CONSTANT_P (operands[1])
1765 && GET_CODE (operands[1]) != HIGH
1766 && GET_CODE (operands[1]) != LO_SUM)
1767 {
1768 sparc_emit_set_const32 (operands[0], operands[1]);
1769 DONE;
1770 }
1771 movhi_is_ok:
1772 ;
1773 })
1774
1775 (define_insn "*movhi_const64_special"
1776 [(set (match_operand:HI 0 "register_operand" "=r")
1777 (match_operand:HI 1 "const64_high_operand" ""))]
1778 "TARGET_ARCH64"
1779 "sethi\t%%hi(%a1), %0")
1780
1781 (define_insn "*movhi_insn"
1782 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1783 (match_operand:HI 1 "input_operand" "rI,K,m,rJ"))]
1784 "(register_operand (operands[0], HImode)
1785 || reg_or_0_operand (operands[1], HImode))"
1786 "@
1787 mov\t%1, %0
1788 sethi\t%%hi(%a1), %0
1789 lduh\t%1, %0
1790 sth\t%r1, %0"
1791 [(set_attr "type" "*,*,load,store")
1792 (set_attr "us3load_type" "*,*,3cycle,*")])
1793
1794 ;; We always work with constants here.
1795 (define_insn "*movhi_lo_sum"
1796 [(set (match_operand:HI 0 "register_operand" "=r")
1797 (ior:HI (match_operand:HI 1 "arith_operand" "%r")
1798 (match_operand:HI 2 "arith_operand" "I")))]
1799 ""
1800 "or\t%1, %2, %0")
1801
1802 (define_expand "movsi"
1803 [(set (match_operand:SI 0 "general_operand" "")
1804 (match_operand:SI 1 "general_operand" ""))]
1805 ""
1806 {
1807 /* Working with CONST_INTs is easier, so convert
1808 a double if needed. */
1809 if (GET_CODE (operands[1]) == CONST_DOUBLE)
1810 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
1811
1812 /* Handle sets of MEM first. */
1813 if (GET_CODE (operands[0]) == MEM)
1814 {
1815 if (reg_or_0_operand (operands[1], SImode))
1816 goto movsi_is_ok;
1817
1818 if (! reload_in_progress)
1819 {
1820 operands[0] = validize_mem (operands[0]);
1821 operands[1] = force_reg (SImode, operands[1]);
1822 }
1823 }
1824
1825 /* Fixup PIC cases. */
1826 if (flag_pic)
1827 {
1828 if (CONSTANT_P (operands[1])
1829 && pic_address_needs_scratch (operands[1]))
1830 operands[1] = legitimize_pic_address (operands[1], SImode, 0);
1831
1832 if (GET_CODE (operands[1]) == LABEL_REF)
1833 {
1834 /* shit */
1835 emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
1836 DONE;
1837 }
1838
1839 if (symbolic_operand (operands[1], SImode))
1840 {
1841 operands[1] = legitimize_pic_address (operands[1],
1842 SImode,
1843 (reload_in_progress ?
1844 operands[0] :
1845 NULL_RTX));
1846 goto movsi_is_ok;
1847 }
1848 }
1849
1850 /* If we are trying to toss an integer constant into the
1851 FPU registers, force it into memory. */
1852 if (GET_CODE (operands[0]) == REG
1853 && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
1854 && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
1855 && CONSTANT_P (operands[1]))
1856 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
1857 operands[1]));
1858
1859 /* This makes sure we will not get rematched due to splittage. */
1860 if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
1861 ;
1862 else if (CONSTANT_P (operands[1])
1863 && GET_CODE (operands[1]) != HIGH
1864 && GET_CODE (operands[1]) != LO_SUM)
1865 {
1866 sparc_emit_set_const32 (operands[0], operands[1]);
1867 DONE;
1868 }
1869 movsi_is_ok:
1870 ;
1871 })
1872
1873 ;; This is needed to show CSE exactly which bits are set
1874 ;; in a 64-bit register by sethi instructions.
1875 (define_insn "*movsi_const64_special"
1876 [(set (match_operand:SI 0 "register_operand" "=r")
1877 (match_operand:SI 1 "const64_high_operand" ""))]
1878 "TARGET_ARCH64"
1879 "sethi\t%%hi(%a1), %0")
1880
1881 (define_insn "*movsi_insn"
1882 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,f,r,r,r,f,m,m,d")
1883 (match_operand:SI 1 "input_operand" "rI,!f,K,J,m,!m,rJ,!f,J"))]
1884 "(register_operand (operands[0], SImode)
1885 || reg_or_0_operand (operands[1], SImode))"
1886 "@
1887 mov\t%1, %0
1888 fmovs\t%1, %0
1889 sethi\t%%hi(%a1), %0
1890 clr\t%0
1891 ld\t%1, %0
1892 ld\t%1, %0
1893 st\t%r1, %0
1894 st\t%1, %0
1895 fzeros\t%0"
1896 [(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fpmove")])
1897
1898 (define_insn "*movsi_lo_sum"
1899 [(set (match_operand:SI 0 "register_operand" "=r")
1900 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1901 (match_operand:SI 2 "immediate_operand" "in")))]
1902 ""
1903 "or\t%1, %%lo(%a2), %0")
1904
1905 (define_insn "*movsi_high"
1906 [(set (match_operand:SI 0 "register_operand" "=r")
1907 (high:SI (match_operand:SI 1 "immediate_operand" "in")))]
1908 ""
1909 "sethi\t%%hi(%a1), %0")
1910
1911 ;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
1912 ;; so that CSE won't optimize the address computation away.
1913 (define_insn "movsi_lo_sum_pic"
1914 [(set (match_operand:SI 0 "register_operand" "=r")
1915 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1916 (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
1917 "flag_pic"
1918 "or\t%1, %%lo(%a2), %0")
1919
1920 (define_insn "movsi_high_pic"
1921 [(set (match_operand:SI 0 "register_operand" "=r")
1922 (high:SI (unspec:SI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
1923 "flag_pic && check_pic (1)"
1924 "sethi\t%%hi(%a1), %0")
1925
1926 (define_expand "movsi_pic_label_ref"
1927 [(set (match_dup 3) (high:SI
1928 (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
1929 (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1930 (set (match_dup 4) (lo_sum:SI (match_dup 3)
1931 (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1932 (set (match_operand:SI 0 "register_operand" "=r")
1933 (minus:SI (match_dup 5) (match_dup 4)))]
1934 "flag_pic"
1935 {
1936 current_function_uses_pic_offset_table = 1;
1937 operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
1938 if (no_new_pseudos)
1939 {
1940 operands[3] = operands[0];
1941 operands[4] = operands[0];
1942 }
1943 else
1944 {
1945 operands[3] = gen_reg_rtx (SImode);
1946 operands[4] = gen_reg_rtx (SImode);
1947 }
1948 operands[5] = pic_offset_table_rtx;
1949 })
1950
1951 (define_insn "*movsi_high_pic_label_ref"
1952 [(set (match_operand:SI 0 "register_operand" "=r")
1953 (high:SI
1954 (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
1955 (match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1956 "flag_pic"
1957 "sethi\t%%hi(%a2-(%a1-.)), %0")
1958
1959 (define_insn "*movsi_lo_sum_pic_label_ref"
1960 [(set (match_operand:SI 0 "register_operand" "=r")
1961 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1962 (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
1963 (match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1964 "flag_pic"
1965 "or\t%1, %%lo(%a3-(%a2-.)), %0")
1966
1967 (define_expand "movdi"
1968 [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1969 (match_operand:DI 1 "general_operand" ""))]
1970 ""
1971 {
1972 /* Where possible, convert CONST_DOUBLE into a CONST_INT. */
1973 if (GET_CODE (operands[1]) == CONST_DOUBLE
1974 #if HOST_BITS_PER_WIDE_INT == 32
1975 && ((CONST_DOUBLE_HIGH (operands[1]) == 0
1976 && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
1977 || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
1978 && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
1979 #endif
1980 )
1981 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
1982
1983 /* Handle MEM cases first. */
1984 if (GET_CODE (operands[0]) == MEM)
1985 {
1986 /* If it's a REG, we can always do it.
1987 The const zero case is more complex, on v9
1988 we can always perform it. */
1989 if (register_operand (operands[1], DImode)
1990 || (TARGET_V9
1991 && (operands[1] == const0_rtx)))
1992 goto movdi_is_ok;
1993
1994 if (! reload_in_progress)
1995 {
1996 operands[0] = validize_mem (operands[0]);
1997 operands[1] = force_reg (DImode, operands[1]);
1998 }
1999 }
2000
2001 if (flag_pic)
2002 {
2003 if (CONSTANT_P (operands[1])
2004 && pic_address_needs_scratch (operands[1]))
2005 operands[1] = legitimize_pic_address (operands[1], DImode, 0);
2006
2007 if (GET_CODE (operands[1]) == LABEL_REF)
2008 {
2009 if (! TARGET_ARCH64)
2010 abort ();
2011 emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
2012 DONE;
2013 }
2014
2015 if (symbolic_operand (operands[1], DImode))
2016 {
2017 operands[1] = legitimize_pic_address (operands[1],
2018 DImode,
2019 (reload_in_progress ?
2020 operands[0] :
2021 NULL_RTX));
2022 goto movdi_is_ok;
2023 }
2024 }
2025
2026 /* If we are trying to toss an integer constant into the
2027 FPU registers, force it into memory. */
2028 if (GET_CODE (operands[0]) == REG
2029 && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
2030 && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
2031 && CONSTANT_P (operands[1]))
2032 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2033 operands[1]));
2034
2035 /* This makes sure we will not get rematched due to splittage. */
2036 if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
2037 ;
2038 else if (TARGET_ARCH64
2039 && CONSTANT_P (operands[1])
2040 && GET_CODE (operands[1]) != HIGH
2041 && GET_CODE (operands[1]) != LO_SUM)
2042 {
2043 sparc_emit_set_const64 (operands[0], operands[1]);
2044 DONE;
2045 }
2046
2047 movdi_is_ok:
2048 ;
2049 })
2050
2051 ;; Be careful, fmovd does not exist when !v9.
2052 ;; We match MEM moves directly when we have correct even
2053 ;; numbered registers, but fall into splits otherwise.
2054 ;; The constraint ordering here is really important to
2055 ;; avoid insane problems in reload, especially for patterns
2056 ;; of the form:
2057 ;;
2058 ;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
2059 ;; (const_int -5016)))
2060 ;; (reg:DI 2 %g2))
2061 ;;
2062
2063 (define_insn "*movdi_insn_sp32_v9"
2064 [(set (match_operand:DI 0 "nonimmediate_operand"
2065 "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f,?e,?e,?W")
2066 (match_operand:DI 1 "input_operand"
2067 " J,J,U,T,r,o,i,r, f, T, o, f, f, e, W, e"))]
2068 "! TARGET_ARCH64 && TARGET_V9
2069 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2070 "@
2071 stx\t%%g0, %0
2072 #
2073 std\t%1, %0
2074 ldd\t%1, %0
2075 #
2076 #
2077 #
2078 #
2079 std\t%1, %0
2080 ldd\t%1, %0
2081 #
2082 #
2083 #
2084 fmovd\\t%1, %0
2085 ldd\\t%1, %0
2086 std\\t%1, %0"
2087 [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*,fpmove,fpload,fpstore")
2088 (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2,*,*,*")
2089 (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
2090
2091 (define_insn "*movdi_insn_sp32"
2092 [(set (match_operand:DI 0 "nonimmediate_operand"
2093 "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
2094 (match_operand:DI 1 "input_operand"
2095 " J,U,T,r,o,i,r, f, T, o, f, f"))]
2096 "! TARGET_ARCH64
2097 && (register_operand (operands[0], DImode)
2098 || register_operand (operands[1], DImode))"
2099 "@
2100 #
2101 std\t%1, %0
2102 ldd\t%1, %0
2103 #
2104 #
2105 #
2106 #
2107 std\t%1, %0
2108 ldd\t%1, %0
2109 #
2110 #
2111 #"
2112 [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
2113 (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
2114
2115 ;; The following are generated by sparc_emit_set_const64
2116 (define_insn "*movdi_sp64_dbl"
2117 [(set (match_operand:DI 0 "register_operand" "=r")
2118 (match_operand:DI 1 "const64_operand" ""))]
2119 "(TARGET_ARCH64
2120 && HOST_BITS_PER_WIDE_INT != 64)"
2121 "mov\t%1, %0")
2122
2123 ;; This is needed to show CSE exactly which bits are set
2124 ;; in a 64-bit register by sethi instructions.
2125 (define_insn "*movdi_const64_special"
2126 [(set (match_operand:DI 0 "register_operand" "=r")
2127 (match_operand:DI 1 "const64_high_operand" ""))]
2128 "TARGET_ARCH64"
2129 "sethi\t%%hi(%a1), %0")
2130
2131 (define_insn "*movdi_insn_sp64_novis"
2132 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
2133 (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e"))]
2134 "TARGET_ARCH64 && ! TARGET_VIS
2135 && (register_operand (operands[0], DImode)
2136 || reg_or_0_operand (operands[1], DImode))"
2137 "@
2138 mov\t%1, %0
2139 sethi\t%%hi(%a1), %0
2140 clr\t%0
2141 ldx\t%1, %0
2142 stx\t%r1, %0
2143 fmovd\t%1, %0
2144 ldd\t%1, %0
2145 std\t%1, %0"
2146 [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore")
2147 (set_attr "fptype" "*,*,*,*,*,double,*,*")])
2148
2149 (define_insn "*movdi_insn_sp64_vis"
2150 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b")
2151 (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e,J"))]
2152 "TARGET_ARCH64 && TARGET_VIS &&
2153 (register_operand (operands[0], DImode)
2154 || reg_or_0_operand (operands[1], DImode))"
2155 "@
2156 mov\t%1, %0
2157 sethi\t%%hi(%a1), %0
2158 clr\t%0
2159 ldx\t%1, %0
2160 stx\t%r1, %0
2161 fmovd\t%1, %0
2162 ldd\t%1, %0
2163 std\t%1, %0
2164 fzero\t%0"
2165 [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fpmove")
2166 (set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
2167
2168 (define_expand "movdi_pic_label_ref"
2169 [(set (match_dup 3) (high:DI
2170 (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2171 (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
2172 (set (match_dup 4) (lo_sum:DI (match_dup 3)
2173 (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
2174 (set (match_operand:DI 0 "register_operand" "=r")
2175 (minus:DI (match_dup 5) (match_dup 4)))]
2176 "TARGET_ARCH64 && flag_pic"
2177 {
2178 current_function_uses_pic_offset_table = 1;
2179 operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
2180 if (no_new_pseudos)
2181 {
2182 operands[3] = operands[0];
2183 operands[4] = operands[0];
2184 }
2185 else
2186 {
2187 operands[3] = gen_reg_rtx (DImode);
2188 operands[4] = gen_reg_rtx (DImode);
2189 }
2190 operands[5] = pic_offset_table_rtx;
2191 })
2192
2193 (define_insn "*movdi_high_pic_label_ref"
2194 [(set (match_operand:DI 0 "register_operand" "=r")
2195 (high:DI
2196 (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2197 (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2198 "TARGET_ARCH64 && flag_pic"
2199 "sethi\t%%hi(%a2-(%a1-.)), %0")
2200
2201 (define_insn "*movdi_lo_sum_pic_label_ref"
2202 [(set (match_operand:DI 0 "register_operand" "=r")
2203 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2204 (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
2205 (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2206 "TARGET_ARCH64 && flag_pic"
2207 "or\t%1, %%lo(%a3-(%a2-.)), %0")
2208
2209 ;; SPARC-v9 code model support insns. See sparc_emit_set_symbolic_const64
2210 ;; in sparc.c to see what is going on here... PIC stuff comes first.
2211
2212 (define_insn "movdi_lo_sum_pic"
2213 [(set (match_operand:DI 0 "register_operand" "=r")
2214 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2215 (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
2216 "TARGET_ARCH64 && flag_pic"
2217 "or\t%1, %%lo(%a2), %0")
2218
2219 (define_insn "movdi_high_pic"
2220 [(set (match_operand:DI 0 "register_operand" "=r")
2221 (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
2222 "TARGET_ARCH64 && flag_pic && check_pic (1)"
2223 "sethi\t%%hi(%a1), %0")
2224
2225 (define_insn "*sethi_di_medlow_embmedany_pic"
2226 [(set (match_operand:DI 0 "register_operand" "=r")
2227 (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
2228 "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
2229 "sethi\t%%hi(%a1), %0")
2230
2231 (define_insn "*sethi_di_medlow"
2232 [(set (match_operand:DI 0 "register_operand" "=r")
2233 (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
2234 "TARGET_CM_MEDLOW && check_pic (1)"
2235 "sethi\t%%hi(%a1), %0")
2236
2237 (define_insn "*losum_di_medlow"
2238 [(set (match_operand:DI 0 "register_operand" "=r")
2239 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2240 (match_operand:DI 2 "symbolic_operand" "")))]
2241 "TARGET_CM_MEDLOW"
2242 "or\t%1, %%lo(%a2), %0")
2243
2244 (define_insn "seth44"
2245 [(set (match_operand:DI 0 "register_operand" "=r")
2246 (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
2247 "TARGET_CM_MEDMID"
2248 "sethi\t%%h44(%a1), %0")
2249
2250 (define_insn "setm44"
2251 [(set (match_operand:DI 0 "register_operand" "=r")
2252 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2253 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
2254 "TARGET_CM_MEDMID"
2255 "or\t%1, %%m44(%a2), %0")
2256
2257 (define_insn "setl44"
2258 [(set (match_operand:DI 0 "register_operand" "=r")
2259 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2260 (match_operand:DI 2 "symbolic_operand" "")))]
2261 "TARGET_CM_MEDMID"
2262 "or\t%1, %%l44(%a2), %0")
2263
2264 (define_insn "sethh"
2265 [(set (match_operand:DI 0 "register_operand" "=r")
2266 (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
2267 "TARGET_CM_MEDANY"
2268 "sethi\t%%hh(%a1), %0")
2269
2270 (define_insn "setlm"
2271 [(set (match_operand:DI 0 "register_operand" "=r")
2272 (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
2273 "TARGET_CM_MEDANY"
2274 "sethi\t%%lm(%a1), %0")
2275
2276 (define_insn "sethm"
2277 [(set (match_operand:DI 0 "register_operand" "=r")
2278 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2279 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
2280 "TARGET_CM_MEDANY"
2281 "or\t%1, %%hm(%a2), %0")
2282
2283 (define_insn "setlo"
2284 [(set (match_operand:DI 0 "register_operand" "=r")
2285 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2286 (match_operand:DI 2 "symbolic_operand" "")))]
2287 "TARGET_CM_MEDANY"
2288 "or\t%1, %%lo(%a2), %0")
2289
2290 (define_insn "embmedany_sethi"
2291 [(set (match_operand:DI 0 "register_operand" "=r")
2292 (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
2293 "TARGET_CM_EMBMEDANY && check_pic (1)"
2294 "sethi\t%%hi(%a1), %0")
2295
2296 (define_insn "embmedany_losum"
2297 [(set (match_operand:DI 0 "register_operand" "=r")
2298 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2299 (match_operand:DI 2 "data_segment_operand" "")))]
2300 "TARGET_CM_EMBMEDANY"
2301 "add\t%1, %%lo(%a2), %0")
2302
2303 (define_insn "embmedany_brsum"
2304 [(set (match_operand:DI 0 "register_operand" "=r")
2305 (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
2306 "TARGET_CM_EMBMEDANY"
2307 "add\t%1, %_, %0")
2308
2309 (define_insn "embmedany_textuhi"
2310 [(set (match_operand:DI 0 "register_operand" "=r")
2311 (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
2312 "TARGET_CM_EMBMEDANY && check_pic (1)"
2313 "sethi\t%%uhi(%a1), %0")
2314
2315 (define_insn "embmedany_texthi"
2316 [(set (match_operand:DI 0 "register_operand" "=r")
2317 (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
2318 "TARGET_CM_EMBMEDANY && check_pic (1)"
2319 "sethi\t%%hi(%a1), %0")
2320
2321 (define_insn "embmedany_textulo"
2322 [(set (match_operand:DI 0 "register_operand" "=r")
2323 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2324 (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
2325 "TARGET_CM_EMBMEDANY"
2326 "or\t%1, %%ulo(%a2), %0")
2327
2328 (define_insn "embmedany_textlo"
2329 [(set (match_operand:DI 0 "register_operand" "=r")
2330 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2331 (match_operand:DI 2 "text_segment_operand" "")))]
2332 "TARGET_CM_EMBMEDANY"
2333 "or\t%1, %%lo(%a2), %0")
2334
2335 ;; Now some patterns to help reload out a bit.
2336 (define_expand "reload_indi"
2337 [(parallel [(match_operand:DI 0 "register_operand" "=r")
2338 (match_operand:DI 1 "immediate_operand" "")
2339 (match_operand:TI 2 "register_operand" "=&r")])]
2340 "(TARGET_CM_MEDANY
2341 || TARGET_CM_EMBMEDANY)
2342 && ! flag_pic"
2343 {
2344 sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2345 DONE;
2346 })
2347
2348 (define_expand "reload_outdi"
2349 [(parallel [(match_operand:DI 0 "register_operand" "=r")
2350 (match_operand:DI 1 "immediate_operand" "")
2351 (match_operand:TI 2 "register_operand" "=&r")])]
2352 "(TARGET_CM_MEDANY
2353 || TARGET_CM_EMBMEDANY)
2354 && ! flag_pic"
2355 {
2356 sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2357 DONE;
2358 })
2359
2360 ;; Split up putting CONSTs and REGs into DI regs when !arch64
2361 (define_split
2362 [(set (match_operand:DI 0 "register_operand" "")
2363 (match_operand:DI 1 "const_int_operand" ""))]
2364 "! TARGET_ARCH64 && reload_completed"
2365 [(clobber (const_int 0))]
2366 {
2367 #if HOST_BITS_PER_WIDE_INT == 32
2368 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2369 (INTVAL (operands[1]) < 0) ?
2370 constm1_rtx :
2371 const0_rtx));
2372 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2373 operands[1]));
2374 #else
2375 unsigned int low, high;
2376
2377 low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
2378 high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
2379 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
2380
2381 /* Slick... but this trick loses if this subreg constant part
2382 can be done in one insn. */
2383 if (low == high && (low & 0x3ff) != 0 && low + 0x1000 >= 0x2000)
2384 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2385 gen_highpart (SImode, operands[0])));
2386 else
2387 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
2388 #endif
2389 DONE;
2390 })
2391
2392 (define_split
2393 [(set (match_operand:DI 0 "register_operand" "")
2394 (match_operand:DI 1 "const_double_operand" ""))]
2395 "reload_completed
2396 && (! TARGET_V9
2397 || (! TARGET_ARCH64
2398 && ((GET_CODE (operands[0]) == REG
2399 && REGNO (operands[0]) < 32)
2400 || (GET_CODE (operands[0]) == SUBREG
2401 && GET_CODE (SUBREG_REG (operands[0])) == REG
2402 && REGNO (SUBREG_REG (operands[0])) < 32))))"
2403 [(clobber (const_int 0))]
2404 {
2405 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2406 GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
2407
2408 /* Slick... but this trick loses if this subreg constant part
2409 can be done in one insn. */
2410 if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
2411 && !(SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
2412 || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
2413 {
2414 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2415 gen_highpart (SImode, operands[0])));
2416 }
2417 else
2418 {
2419 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2420 GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
2421 }
2422 DONE;
2423 })
2424
2425 (define_split
2426 [(set (match_operand:DI 0 "register_operand" "")
2427 (match_operand:DI 1 "register_operand" ""))]
2428 "! TARGET_ARCH64 && reload_completed"
2429 [(clobber (const_int 0))]
2430 {
2431 rtx set_dest = operands[0];
2432 rtx set_src = operands[1];
2433 rtx dest1, dest2;
2434 rtx src1, src2;
2435
2436 dest1 = gen_highpart (SImode, set_dest);
2437 dest2 = gen_lowpart (SImode, set_dest);
2438 src1 = gen_highpart (SImode, set_src);
2439 src2 = gen_lowpart (SImode, set_src);
2440
2441 /* Now emit using the real source and destination we found, swapping
2442 the order if we detect overlap. */
2443 if (reg_overlap_mentioned_p (dest1, src2))
2444 {
2445 emit_insn (gen_movsi (dest2, src2));
2446 emit_insn (gen_movsi (dest1, src1));
2447 }
2448 else
2449 {
2450 emit_insn (gen_movsi (dest1, src1));
2451 emit_insn (gen_movsi (dest2, src2));
2452 }
2453 DONE;
2454 })
2455
2456 ;; Now handle the cases of memory moves from/to non-even
2457 ;; DI mode register pairs.
2458 (define_split
2459 [(set (match_operand:DI 0 "register_operand" "")
2460 (match_operand:DI 1 "memory_operand" ""))]
2461 "(! TARGET_ARCH64
2462 && reload_completed
2463 && sparc_splitdi_legitimate (operands[0], operands[1]))"
2464 [(clobber (const_int 0))]
2465 {
2466 rtx word0 = adjust_address (operands[1], SImode, 0);
2467 rtx word1 = adjust_address (operands[1], SImode, 4);
2468 rtx high_part = gen_highpart (SImode, operands[0]);
2469 rtx low_part = gen_lowpart (SImode, operands[0]);
2470
2471 if (reg_overlap_mentioned_p (high_part, word1))
2472 {
2473 emit_insn (gen_movsi (low_part, word1));
2474 emit_insn (gen_movsi (high_part, word0));
2475 }
2476 else
2477 {
2478 emit_insn (gen_movsi (high_part, word0));
2479 emit_insn (gen_movsi (low_part, word1));
2480 }
2481 DONE;
2482 })
2483
2484 (define_split
2485 [(set (match_operand:DI 0 "memory_operand" "")
2486 (match_operand:DI 1 "register_operand" ""))]
2487 "(! TARGET_ARCH64
2488 && reload_completed
2489 && sparc_splitdi_legitimate (operands[1], operands[0]))"
2490 [(clobber (const_int 0))]
2491 {
2492 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
2493 gen_highpart (SImode, operands[1])));
2494 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
2495 gen_lowpart (SImode, operands[1])));
2496 DONE;
2497 })
2498
2499 (define_split
2500 [(set (match_operand:DI 0 "memory_operand" "")
2501 (const_int 0))]
2502 "reload_completed
2503 && (! TARGET_V9
2504 || (! TARGET_ARCH64
2505 && ! mem_min_alignment (operands[0], 8)))
2506 && offsettable_memref_p (operands[0])"
2507 [(clobber (const_int 0))]
2508 {
2509 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
2510 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
2511 DONE;
2512 })
2513 \f
2514 ;; Floating point move insns
2515
2516 (define_insn "*movsf_insn_novis"
2517 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
2518 (match_operand:SF 1 "input_operand" "f,G,Q,*rR,S,m,m,f,*rG"))]
2519 "(TARGET_FPU && ! TARGET_VIS)
2520 && (register_operand (operands[0], SFmode)
2521 || register_operand (operands[1], SFmode)
2522 || fp_zero_operand (operands[1], SFmode))"
2523 {
2524 if (GET_CODE (operands[1]) == CONST_DOUBLE
2525 && (which_alternative == 2
2526 || which_alternative == 3
2527 || which_alternative == 4))
2528 {
2529 REAL_VALUE_TYPE r;
2530 long i;
2531
2532 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2533 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2534 operands[1] = GEN_INT (i);
2535 }
2536
2537 switch (which_alternative)
2538 {
2539 case 0:
2540 return "fmovs\t%1, %0";
2541 case 1:
2542 return "clr\t%0";
2543 case 2:
2544 return "sethi\t%%hi(%a1), %0";
2545 case 3:
2546 return "mov\t%1, %0";
2547 case 4:
2548 return "#";
2549 case 5:
2550 case 6:
2551 return "ld\t%1, %0";
2552 case 7:
2553 case 8:
2554 return "st\t%r1, %0";
2555 default:
2556 abort();
2557 }
2558 }
2559 [(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")])
2560
2561 (define_insn "*movsf_insn_vis"
2562 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
2563 (match_operand:SF 1 "input_operand" "f,G,G,Q,*rR,S,m,m,f,*rG"))]
2564 "(TARGET_FPU && TARGET_VIS)
2565 && (register_operand (operands[0], SFmode)
2566 || register_operand (operands[1], SFmode)
2567 || fp_zero_operand (operands[1], SFmode))"
2568 {
2569 if (GET_CODE (operands[1]) == CONST_DOUBLE
2570 && (which_alternative == 3
2571 || which_alternative == 4
2572 || which_alternative == 5))
2573 {
2574 REAL_VALUE_TYPE r;
2575 long i;
2576
2577 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2578 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2579 operands[1] = GEN_INT (i);
2580 }
2581
2582 switch (which_alternative)
2583 {
2584 case 0:
2585 return "fmovs\t%1, %0";
2586 case 1:
2587 return "fzeros\t%0";
2588 case 2:
2589 return "clr\t%0";
2590 case 3:
2591 return "sethi\t%%hi(%a1), %0";
2592 case 4:
2593 return "mov\t%1, %0";
2594 case 5:
2595 return "#";
2596 case 6:
2597 case 7:
2598 return "ld\t%1, %0";
2599 case 8:
2600 case 9:
2601 return "st\t%r1, %0";
2602 default:
2603 abort();
2604 }
2605 }
2606 [(set_attr "type" "fpmove,fpmove,*,*,*,*,load,fpload,fpstore,store")])
2607
2608 ;; Exactly the same as above, except that all `f' cases are deleted.
2609 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2610 ;; when -mno-fpu.
2611
2612 (define_insn "*movsf_no_f_insn"
2613 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,r,m")
2614 (match_operand:SF 1 "input_operand" "G,Q,rR,S,m,rG"))]
2615 "! TARGET_FPU
2616 && (register_operand (operands[0], SFmode)
2617 || register_operand (operands[1], SFmode)
2618 || fp_zero_operand (operands[1], SFmode))"
2619 {
2620 if (GET_CODE (operands[1]) == CONST_DOUBLE
2621 && (which_alternative == 1
2622 || which_alternative == 2
2623 || which_alternative == 3))
2624 {
2625 REAL_VALUE_TYPE r;
2626 long i;
2627
2628 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2629 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2630 operands[1] = GEN_INT (i);
2631 }
2632
2633 switch (which_alternative)
2634 {
2635 case 0:
2636 return "clr\t%0";
2637 case 1:
2638 return "sethi\t%%hi(%a1), %0";
2639 case 2:
2640 return "mov\t%1, %0";
2641 case 3:
2642 return "#";
2643 case 4:
2644 return "ld\t%1, %0";
2645 case 5:
2646 return "st\t%r1, %0";
2647 default:
2648 abort();
2649 }
2650 }
2651 [(set_attr "type" "*,*,*,*,load,store")])
2652
2653 (define_insn "*movsf_lo_sum"
2654 [(set (match_operand:SF 0 "register_operand" "=r")
2655 (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
2656 (match_operand:SF 2 "const_double_operand" "S")))]
2657 "fp_high_losum_p (operands[2])"
2658 {
2659 REAL_VALUE_TYPE r;
2660 long i;
2661
2662 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
2663 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2664 operands[2] = GEN_INT (i);
2665 return "or\t%1, %%lo(%a2), %0";
2666 })
2667
2668 (define_insn "*movsf_high"
2669 [(set (match_operand:SF 0 "register_operand" "=r")
2670 (high:SF (match_operand:SF 1 "const_double_operand" "S")))]
2671 "fp_high_losum_p (operands[1])"
2672 {
2673 REAL_VALUE_TYPE r;
2674 long i;
2675
2676 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2677 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2678 operands[1] = GEN_INT (i);
2679 return "sethi\t%%hi(%1), %0";
2680 })
2681
2682 (define_split
2683 [(set (match_operand:SF 0 "register_operand" "")
2684 (match_operand:SF 1 "const_double_operand" ""))]
2685 "fp_high_losum_p (operands[1])
2686 && (GET_CODE (operands[0]) == REG
2687 && REGNO (operands[0]) < 32)"
2688 [(set (match_dup 0) (high:SF (match_dup 1)))
2689 (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
2690
2691 (define_expand "movsf"
2692 [(set (match_operand:SF 0 "general_operand" "")
2693 (match_operand:SF 1 "general_operand" ""))]
2694 ""
2695 {
2696 /* Force SFmode constants into memory. */
2697 if (GET_CODE (operands[0]) == REG
2698 && CONSTANT_P (operands[1]))
2699 {
2700 /* emit_group_store will send such bogosity to us when it is
2701 not storing directly into memory. So fix this up to avoid
2702 crashes in output_constant_pool. */
2703 if (operands [1] == const0_rtx)
2704 operands[1] = CONST0_RTX (SFmode);
2705
2706 if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
2707 goto movsf_is_ok;
2708
2709 /* We are able to build any SF constant in integer registers
2710 with at most 2 instructions. */
2711 if (REGNO (operands[0]) < 32)
2712 goto movsf_is_ok;
2713
2714 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2715 operands[1]));
2716 }
2717
2718 /* Handle sets of MEM first. */
2719 if (GET_CODE (operands[0]) == MEM)
2720 {
2721 if (register_operand (operands[1], SFmode)
2722 || fp_zero_operand (operands[1], SFmode))
2723 goto movsf_is_ok;
2724
2725 if (! reload_in_progress)
2726 {
2727 operands[0] = validize_mem (operands[0]);
2728 operands[1] = force_reg (SFmode, operands[1]);
2729 }
2730 }
2731
2732 /* Fixup PIC cases. */
2733 if (flag_pic)
2734 {
2735 if (CONSTANT_P (operands[1])
2736 && pic_address_needs_scratch (operands[1]))
2737 operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
2738
2739 if (symbolic_operand (operands[1], SFmode))
2740 {
2741 operands[1] = legitimize_pic_address (operands[1],
2742 SFmode,
2743 (reload_in_progress ?
2744 operands[0] :
2745 NULL_RTX));
2746 }
2747 }
2748
2749 movsf_is_ok:
2750 ;
2751 })
2752
2753 (define_expand "movdf"
2754 [(set (match_operand:DF 0 "general_operand" "")
2755 (match_operand:DF 1 "general_operand" ""))]
2756 ""
2757 {
2758 /* Force DFmode constants into memory. */
2759 if (GET_CODE (operands[0]) == REG
2760 && CONSTANT_P (operands[1]))
2761 {
2762 /* emit_group_store will send such bogosity to us when it is
2763 not storing directly into memory. So fix this up to avoid
2764 crashes in output_constant_pool. */
2765 if (operands [1] == const0_rtx)
2766 operands[1] = CONST0_RTX (DFmode);
2767
2768 if ((TARGET_VIS || REGNO (operands[0]) < 32)
2769 && fp_zero_operand (operands[1], DFmode))
2770 goto movdf_is_ok;
2771
2772 /* We are able to build any DF constant in integer registers. */
2773 if (REGNO (operands[0]) < 32
2774 && (reload_completed || reload_in_progress))
2775 goto movdf_is_ok;
2776
2777 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2778 operands[1]));
2779 }
2780
2781 /* Handle MEM cases first. */
2782 if (GET_CODE (operands[0]) == MEM)
2783 {
2784 if (register_operand (operands[1], DFmode)
2785 || fp_zero_operand (operands[1], DFmode))
2786 goto movdf_is_ok;
2787
2788 if (! reload_in_progress)
2789 {
2790 operands[0] = validize_mem (operands[0]);
2791 operands[1] = force_reg (DFmode, operands[1]);
2792 }
2793 }
2794
2795 /* Fixup PIC cases. */
2796 if (flag_pic)
2797 {
2798 if (CONSTANT_P (operands[1])
2799 && pic_address_needs_scratch (operands[1]))
2800 operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
2801
2802 if (symbolic_operand (operands[1], DFmode))
2803 {
2804 operands[1] = legitimize_pic_address (operands[1],
2805 DFmode,
2806 (reload_in_progress ?
2807 operands[0] :
2808 NULL_RTX));
2809 }
2810 }
2811
2812 movdf_is_ok:
2813 ;
2814 })
2815
2816 ;; Be careful, fmovd does not exist when !v9.
2817 (define_insn "*movdf_insn_sp32"
2818 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
2819 (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
2820 "TARGET_FPU
2821 && ! TARGET_V9
2822 && (register_operand (operands[0], DFmode)
2823 || register_operand (operands[1], DFmode)
2824 || fp_zero_operand (operands[1], DFmode))"
2825 "@
2826 ldd\t%1, %0
2827 std\t%1, %0
2828 ldd\t%1, %0
2829 std\t%1, %0
2830 #
2831 #
2832 #
2833 #
2834 #
2835 #"
2836 [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
2837 (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
2838
2839 (define_insn "*movdf_no_e_insn_sp32"
2840 [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
2841 (match_operand:DF 1 "input_operand" "T,U,G,ro,r"))]
2842 "! TARGET_FPU
2843 && ! TARGET_V9
2844 && ! TARGET_ARCH64
2845 && (register_operand (operands[0], DFmode)
2846 || register_operand (operands[1], DFmode)
2847 || fp_zero_operand (operands[1], DFmode))"
2848 "@
2849 ldd\t%1, %0
2850 std\t%1, %0
2851 #
2852 #
2853 #"
2854 [(set_attr "type" "load,store,*,*,*")
2855 (set_attr "length" "*,*,2,2,2")])
2856
2857 (define_insn "*movdf_no_e_insn_v9_sp32"
2858 [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
2859 (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
2860 "! TARGET_FPU
2861 && TARGET_V9
2862 && ! TARGET_ARCH64
2863 && (register_operand (operands[0], DFmode)
2864 || register_operand (operands[1], DFmode)
2865 || fp_zero_operand (operands[1], DFmode))"
2866 "@
2867 ldd\t%1, %0
2868 std\t%1, %0
2869 stx\t%r1, %0
2870 #
2871 #"
2872 [(set_attr "type" "load,store,store,*,*")
2873 (set_attr "length" "*,*,*,2,2")])
2874
2875 ;; We have available v9 double floats but not 64-bit
2876 ;; integer registers and no VIS.
2877 (define_insn "*movdf_insn_v9only_novis"
2878 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
2879 (match_operand:DF 1 "input_operand" "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
2880 "TARGET_FPU
2881 && TARGET_V9
2882 && ! TARGET_VIS
2883 && ! TARGET_ARCH64
2884 && (register_operand (operands[0], DFmode)
2885 || register_operand (operands[1], DFmode)
2886 || fp_zero_operand (operands[1], DFmode))"
2887 "@
2888 fmovd\t%1, %0
2889 ldd\t%1, %0
2890 stx\t%r1, %0
2891 std\t%1, %0
2892 ldd\t%1, %0
2893 std\t%1, %0
2894 #
2895 #
2896 #"
2897 [(set_attr "type" "fpmove,load,store,store,load,store,*,*,*")
2898 (set_attr "length" "*,*,*,*,*,*,2,2,2")
2899 (set_attr "fptype" "double,*,*,*,*,*,*,*,*")])
2900
2901 ;; We have available v9 double floats but not 64-bit
2902 ;; integer registers but we have VIS.
2903 (define_insn "*movdf_insn_v9only_vis"
2904 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
2905 (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
2906 "TARGET_FPU
2907 && TARGET_VIS
2908 && ! TARGET_ARCH64
2909 && (register_operand (operands[0], DFmode)
2910 || register_operand (operands[1], DFmode)
2911 || fp_zero_operand (operands[1], DFmode))"
2912 "@
2913 fzero\t%0
2914 fmovd\t%1, %0
2915 ldd\t%1, %0
2916 stx\t%r1, %0
2917 std\t%1, %0
2918 ldd\t%1, %0
2919 std\t%1, %0
2920 #
2921 #
2922 #"
2923 [(set_attr "type" "fpmove,fpmove,load,store,store,load,store,*,*,*")
2924 (set_attr "length" "*,*,*,*,*,*,*,2,2,2")
2925 (set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
2926
2927 ;; We have available both v9 double floats and 64-bit
2928 ;; integer registers. No VIS though.
2929 (define_insn "*movdf_insn_sp64_novis"
2930 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,W,*r,*r,m,*r")
2931 (match_operand:DF 1 "input_operand" "e,W#F,e,*rG,m,*rG,F"))]
2932 "TARGET_FPU
2933 && ! TARGET_VIS
2934 && TARGET_ARCH64
2935 && (register_operand (operands[0], DFmode)
2936 || register_operand (operands[1], DFmode)
2937 || fp_zero_operand (operands[1], DFmode))"
2938 "@
2939 fmovd\t%1, %0
2940 ldd\t%1, %0
2941 std\t%1, %0
2942 mov\t%r1, %0
2943 ldx\t%1, %0
2944 stx\t%r1, %0
2945 #"
2946 [(set_attr "type" "fpmove,load,store,*,load,store,*")
2947 (set_attr "length" "*,*,*,*,*,*,2")
2948 (set_attr "fptype" "double,*,*,*,*,*,*")])
2949
2950 ;; We have available both v9 double floats and 64-bit
2951 ;; integer registers. And we have VIS.
2952 (define_insn "*movdf_insn_sp64_vis"
2953 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r")
2954 (match_operand:DF 1 "input_operand" "G,e,W#F,e,*rG,m,*rG,F"))]
2955 "TARGET_FPU
2956 && TARGET_VIS
2957 && TARGET_ARCH64
2958 && (register_operand (operands[0], DFmode)
2959 || register_operand (operands[1], DFmode)
2960 || fp_zero_operand (operands[1], DFmode))"
2961 "@
2962 fzero\t%0
2963 fmovd\t%1, %0
2964 ldd\t%1, %0
2965 std\t%1, %0
2966 mov\t%r1, %0
2967 ldx\t%1, %0
2968 stx\t%r1, %0
2969 #"
2970 [(set_attr "type" "fpmove,fpmove,load,store,*,load,store,*")
2971 (set_attr "length" "*,*,*,*,*,*,*,2")
2972 (set_attr "fptype" "double,double,*,*,*,*,*,*")])
2973
2974 (define_insn "*movdf_no_e_insn_sp64"
2975 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
2976 (match_operand:DF 1 "input_operand" "r,m,rG"))]
2977 "! TARGET_FPU
2978 && TARGET_ARCH64
2979 && (register_operand (operands[0], DFmode)
2980 || register_operand (operands[1], DFmode)
2981 || fp_zero_operand (operands[1], DFmode))"
2982 "@
2983 mov\t%1, %0
2984 ldx\t%1, %0
2985 stx\t%r1, %0"
2986 [(set_attr "type" "*,load,store")])
2987
2988 (define_split
2989 [(set (match_operand:DF 0 "register_operand" "")
2990 (match_operand:DF 1 "const_double_operand" ""))]
2991 "TARGET_FPU
2992 && (GET_CODE (operands[0]) == REG
2993 && REGNO (operands[0]) < 32)
2994 && ! fp_zero_operand(operands[1], DFmode)
2995 && reload_completed"
2996 [(clobber (const_int 0))]
2997 {
2998 REAL_VALUE_TYPE r;
2999 long l[2];
3000
3001 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3002 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
3003 operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
3004
3005 if (TARGET_ARCH64)
3006 {
3007 #if HOST_BITS_PER_WIDE_INT == 64
3008 HOST_WIDE_INT val;
3009
3010 val = ((HOST_WIDE_INT)(unsigned long)l[1] |
3011 ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
3012 emit_insn (gen_movdi (operands[0], GEN_INT (val)));
3013 #else
3014 emit_insn (gen_movdi (operands[0],
3015 immed_double_const (l[1], l[0], DImode)));
3016 #endif
3017 }
3018 else
3019 {
3020 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
3021 GEN_INT (l[0])));
3022
3023 /* Slick... but this trick loses if this subreg constant part
3024 can be done in one insn. */
3025 if (l[1] == l[0]
3026 && !(SPARC_SETHI32_P (l[0])
3027 || SPARC_SIMM13_P (l[0])))
3028 {
3029 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3030 gen_highpart (SImode, operands[0])));
3031 }
3032 else
3033 {
3034 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3035 GEN_INT (l[1])));
3036 }
3037 }
3038 DONE;
3039 })
3040
3041 ;; Ok, now the splits to handle all the multi insn and
3042 ;; mis-aligned memory address cases.
3043 ;; In these splits please take note that we must be
3044 ;; careful when V9 but not ARCH64 because the integer
3045 ;; register DFmode cases must be handled.
3046 (define_split
3047 [(set (match_operand:DF 0 "register_operand" "")
3048 (match_operand:DF 1 "register_operand" ""))]
3049 "(! TARGET_V9
3050 || (! TARGET_ARCH64
3051 && ((GET_CODE (operands[0]) == REG
3052 && REGNO (operands[0]) < 32)
3053 || (GET_CODE (operands[0]) == SUBREG
3054 && GET_CODE (SUBREG_REG (operands[0])) == REG
3055 && REGNO (SUBREG_REG (operands[0])) < 32))))
3056 && reload_completed"
3057 [(clobber (const_int 0))]
3058 {
3059 rtx set_dest = operands[0];
3060 rtx set_src = operands[1];
3061 rtx dest1, dest2;
3062 rtx src1, src2;
3063
3064 dest1 = gen_highpart (SFmode, set_dest);
3065 dest2 = gen_lowpart (SFmode, set_dest);
3066 src1 = gen_highpart (SFmode, set_src);
3067 src2 = gen_lowpart (SFmode, set_src);
3068
3069 /* Now emit using the real source and destination we found, swapping
3070 the order if we detect overlap. */
3071 if (reg_overlap_mentioned_p (dest1, src2))
3072 {
3073 emit_insn (gen_movsf (dest2, src2));
3074 emit_insn (gen_movsf (dest1, src1));
3075 }
3076 else
3077 {
3078 emit_insn (gen_movsf (dest1, src1));
3079 emit_insn (gen_movsf (dest2, src2));
3080 }
3081 DONE;
3082 })
3083
3084 (define_split
3085 [(set (match_operand:DF 0 "register_operand" "")
3086 (match_operand:DF 1 "memory_operand" ""))]
3087 "reload_completed
3088 && ! TARGET_ARCH64
3089 && (((REGNO (operands[0]) % 2) != 0)
3090 || ! mem_min_alignment (operands[1], 8))
3091 && offsettable_memref_p (operands[1])"
3092 [(clobber (const_int 0))]
3093 {
3094 rtx word0 = adjust_address (operands[1], SFmode, 0);
3095 rtx word1 = adjust_address (operands[1], SFmode, 4);
3096
3097 if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
3098 {
3099 emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3100 word1));
3101 emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3102 word0));
3103 }
3104 else
3105 {
3106 emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3107 word0));
3108 emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3109 word1));
3110 }
3111 DONE;
3112 })
3113
3114 (define_split
3115 [(set (match_operand:DF 0 "memory_operand" "")
3116 (match_operand:DF 1 "register_operand" ""))]
3117 "reload_completed
3118 && ! TARGET_ARCH64
3119 && (((REGNO (operands[1]) % 2) != 0)
3120 || ! mem_min_alignment (operands[0], 8))
3121 && offsettable_memref_p (operands[0])"
3122 [(clobber (const_int 0))]
3123 {
3124 rtx word0 = adjust_address (operands[0], SFmode, 0);
3125 rtx word1 = adjust_address (operands[0], SFmode, 4);
3126
3127 emit_insn (gen_movsf (word0,
3128 gen_highpart (SFmode, operands[1])));
3129 emit_insn (gen_movsf (word1,
3130 gen_lowpart (SFmode, operands[1])));
3131 DONE;
3132 })
3133
3134 (define_split
3135 [(set (match_operand:DF 0 "memory_operand" "")
3136 (match_operand:DF 1 "fp_zero_operand" ""))]
3137 "reload_completed
3138 && (! TARGET_V9
3139 || (! TARGET_ARCH64
3140 && ! mem_min_alignment (operands[0], 8)))
3141 && offsettable_memref_p (operands[0])"
3142 [(clobber (const_int 0))]
3143 {
3144 rtx dest1, dest2;
3145
3146 dest1 = adjust_address (operands[0], SFmode, 0);
3147 dest2 = adjust_address (operands[0], SFmode, 4);
3148
3149 emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
3150 emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
3151 DONE;
3152 })
3153
3154 (define_split
3155 [(set (match_operand:DF 0 "register_operand" "")
3156 (match_operand:DF 1 "fp_zero_operand" ""))]
3157 "reload_completed
3158 && ! TARGET_ARCH64
3159 && ((GET_CODE (operands[0]) == REG
3160 && REGNO (operands[0]) < 32)
3161 || (GET_CODE (operands[0]) == SUBREG
3162 && GET_CODE (SUBREG_REG (operands[0])) == REG
3163 && REGNO (SUBREG_REG (operands[0])) < 32))"
3164 [(clobber (const_int 0))]
3165 {
3166 rtx set_dest = operands[0];
3167 rtx dest1, dest2;
3168
3169 dest1 = gen_highpart (SFmode, set_dest);
3170 dest2 = gen_lowpart (SFmode, set_dest);
3171 emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
3172 emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
3173 DONE;
3174 })
3175
3176 (define_expand "movtf"
3177 [(set (match_operand:TF 0 "general_operand" "")
3178 (match_operand:TF 1 "general_operand" ""))]
3179 ""
3180 {
3181 /* Force TFmode constants into memory. */
3182 if (GET_CODE (operands[0]) == REG
3183 && CONSTANT_P (operands[1]))
3184 {
3185 /* emit_group_store will send such bogosity to us when it is
3186 not storing directly into memory. So fix this up to avoid
3187 crashes in output_constant_pool. */
3188 if (operands [1] == const0_rtx)
3189 operands[1] = CONST0_RTX (TFmode);
3190
3191 if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
3192 goto movtf_is_ok;
3193
3194 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
3195 operands[1]));
3196 }
3197
3198 /* Handle MEM cases first, note that only v9 guarentees
3199 full 16-byte alignment for quads. */
3200 if (GET_CODE (operands[0]) == MEM)
3201 {
3202 if (register_operand (operands[1], TFmode)
3203 || fp_zero_operand (operands[1], TFmode))
3204 goto movtf_is_ok;
3205
3206 if (! reload_in_progress)
3207 {
3208 operands[0] = validize_mem (operands[0]);
3209 operands[1] = force_reg (TFmode, operands[1]);
3210 }
3211 }
3212
3213 /* Fixup PIC cases. */
3214 if (flag_pic)
3215 {
3216 if (CONSTANT_P (operands[1])
3217 && pic_address_needs_scratch (operands[1]))
3218 operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
3219
3220 if (symbolic_operand (operands[1], TFmode))
3221 {
3222 operands[1] = legitimize_pic_address (operands[1],
3223 TFmode,
3224 (reload_in_progress ?
3225 operands[0] :
3226 NULL_RTX));
3227 }
3228 }
3229
3230 movtf_is_ok:
3231 ;
3232 })
3233
3234 ;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
3235 ;; we must split them all. :-(
3236 (define_insn "*movtf_insn_sp32"
3237 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
3238 (match_operand:TF 1 "input_operand" "oe,GeUr,o,roG"))]
3239 "TARGET_FPU
3240 && ! TARGET_VIS
3241 && ! TARGET_ARCH64
3242 && (register_operand (operands[0], TFmode)
3243 || register_operand (operands[1], TFmode)
3244 || fp_zero_operand (operands[1], TFmode))"
3245 "#"
3246 [(set_attr "length" "4")])
3247
3248 (define_insn "*movtf_insn_vis_sp32"
3249 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
3250 (match_operand:TF 1 "input_operand" "Goe,GeUr,o,roG"))]
3251 "TARGET_FPU
3252 && TARGET_VIS
3253 && ! TARGET_ARCH64
3254 && (register_operand (operands[0], TFmode)
3255 || register_operand (operands[1], TFmode)
3256 || fp_zero_operand (operands[1], TFmode))"
3257 "#"
3258 [(set_attr "length" "4")])
3259
3260 ;; Exactly the same as above, except that all `e' cases are deleted.
3261 ;; This is necessary to prevent reload from ever trying to use a `e' reg
3262 ;; when -mno-fpu.
3263
3264 (define_insn "*movtf_no_e_insn_sp32"
3265 [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
3266 (match_operand:TF 1 "input_operand" "G,o,U,roG,r"))]
3267 "! TARGET_FPU
3268 && ! TARGET_ARCH64
3269 && (register_operand (operands[0], TFmode)
3270 || register_operand (operands[1], TFmode)
3271 || fp_zero_operand (operands[1], TFmode))"
3272 "#"
3273 [(set_attr "length" "4")])
3274
3275 ;; Now handle the float reg cases directly when arch64,
3276 ;; hard_quad, and proper reg number alignment are all true.
3277 (define_insn "*movtf_insn_hq_sp64"
3278 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,o,r")
3279 (match_operand:TF 1 "input_operand" "e,m,e,Gr,roG"))]
3280 "TARGET_FPU
3281 && ! TARGET_VIS
3282 && TARGET_ARCH64
3283 && TARGET_HARD_QUAD
3284 && (register_operand (operands[0], TFmode)
3285 || register_operand (operands[1], TFmode)
3286 || fp_zero_operand (operands[1], TFmode))"
3287 "@
3288 fmovq\t%1, %0
3289 ldq\t%1, %0
3290 stq\t%1, %0
3291 #
3292 #"
3293 [(set_attr "type" "fpmove,fpload,fpstore,*,*")
3294 (set_attr "length" "*,*,*,2,2")])
3295
3296 (define_insn "*movtf_insn_hq_vis_sp64"
3297 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,eo,r,o")
3298 (match_operand:TF 1 "input_operand" "e,m,e,G,roG,r"))]
3299 "TARGET_FPU
3300 && TARGET_VIS
3301 && TARGET_ARCH64
3302 && TARGET_HARD_QUAD
3303 && (register_operand (operands[0], TFmode)
3304 || register_operand (operands[1], TFmode)
3305 || fp_zero_operand (operands[1], TFmode))"
3306 "@
3307 fmovq\t%1, %0
3308 ldq\t%1, %0
3309 stq\t%1, %0
3310 #
3311 #
3312 #"
3313 [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
3314 (set_attr "length" "*,*,*,2,2,2")])
3315
3316 ;; Now we allow the integer register cases even when
3317 ;; only arch64 is true.
3318 (define_insn "*movtf_insn_sp64"
3319 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
3320 (match_operand:TF 1 "input_operand" "oe,Ger,orG"))]
3321 "TARGET_FPU
3322 && ! TARGET_VIS
3323 && TARGET_ARCH64
3324 && ! TARGET_HARD_QUAD
3325 && (register_operand (operands[0], TFmode)
3326 || register_operand (operands[1], TFmode)
3327 || fp_zero_operand (operands[1], TFmode))"
3328 "#"
3329 [(set_attr "length" "2")])
3330
3331 (define_insn "*movtf_insn_vis_sp64"
3332 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
3333 (match_operand:TF 1 "input_operand" "Goe,Ger,orG"))]
3334 "TARGET_FPU
3335 && TARGET_VIS
3336 && TARGET_ARCH64
3337 && ! TARGET_HARD_QUAD
3338 && (register_operand (operands[0], TFmode)
3339 || register_operand (operands[1], TFmode)
3340 || fp_zero_operand (operands[1], TFmode))"
3341 "#"
3342 [(set_attr "length" "2")])
3343
3344 (define_insn "*movtf_no_e_insn_sp64"
3345 [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
3346 (match_operand:TF 1 "input_operand" "orG,rG"))]
3347 "! TARGET_FPU
3348 && TARGET_ARCH64
3349 && (register_operand (operands[0], TFmode)
3350 || register_operand (operands[1], TFmode)
3351 || fp_zero_operand (operands[1], TFmode))"
3352 "#"
3353 [(set_attr "length" "2")])
3354
3355 ;; Now all the splits to handle multi-insn TF mode moves.
3356 (define_split
3357 [(set (match_operand:TF 0 "register_operand" "")
3358 (match_operand:TF 1 "register_operand" ""))]
3359 "reload_completed
3360 && (! TARGET_ARCH64
3361 || (TARGET_FPU
3362 && ! TARGET_HARD_QUAD)
3363 || ! fp_register_operand (operands[0], TFmode))"
3364 [(clobber (const_int 0))]
3365 {
3366 rtx set_dest = operands[0];
3367 rtx set_src = operands[1];
3368 rtx dest1, dest2;
3369 rtx src1, src2;
3370
3371 dest1 = gen_df_reg (set_dest, 0);
3372 dest2 = gen_df_reg (set_dest, 1);
3373 src1 = gen_df_reg (set_src, 0);
3374 src2 = gen_df_reg (set_src, 1);
3375
3376 /* Now emit using the real source and destination we found, swapping
3377 the order if we detect overlap. */
3378 if (reg_overlap_mentioned_p (dest1, src2))
3379 {
3380 emit_insn (gen_movdf (dest2, src2));
3381 emit_insn (gen_movdf (dest1, src1));
3382 }
3383 else
3384 {
3385 emit_insn (gen_movdf (dest1, src1));
3386 emit_insn (gen_movdf (dest2, src2));
3387 }
3388 DONE;
3389 })
3390
3391 (define_split
3392 [(set (match_operand:TF 0 "nonimmediate_operand" "")
3393 (match_operand:TF 1 "fp_zero_operand" ""))]
3394 "reload_completed"
3395 [(clobber (const_int 0))]
3396 {
3397 rtx set_dest = operands[0];
3398 rtx dest1, dest2;
3399
3400 switch (GET_CODE (set_dest))
3401 {
3402 case REG:
3403 dest1 = gen_df_reg (set_dest, 0);
3404 dest2 = gen_df_reg (set_dest, 1);
3405 break;
3406 case MEM:
3407 dest1 = adjust_address (set_dest, DFmode, 0);
3408 dest2 = adjust_address (set_dest, DFmode, 8);
3409 break;
3410 default:
3411 abort ();
3412 }
3413
3414 emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
3415 emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
3416 DONE;
3417 })
3418
3419 (define_split
3420 [(set (match_operand:TF 0 "register_operand" "")
3421 (match_operand:TF 1 "memory_operand" ""))]
3422 "(reload_completed
3423 && offsettable_memref_p (operands[1])
3424 && (! TARGET_ARCH64
3425 || ! TARGET_HARD_QUAD
3426 || ! fp_register_operand (operands[0], TFmode)))"
3427 [(clobber (const_int 0))]
3428 {
3429 rtx word0 = adjust_address (operands[1], DFmode, 0);
3430 rtx word1 = adjust_address (operands[1], DFmode, 8);
3431 rtx set_dest, dest1, dest2;
3432
3433 set_dest = operands[0];
3434
3435 dest1 = gen_df_reg (set_dest, 0);
3436 dest2 = gen_df_reg (set_dest, 1);
3437
3438 /* Now output, ordering such that we don't clobber any registers
3439 mentioned in the address. */
3440 if (reg_overlap_mentioned_p (dest1, word1))
3441
3442 {
3443 emit_insn (gen_movdf (dest2, word1));
3444 emit_insn (gen_movdf (dest1, word0));
3445 }
3446 else
3447 {
3448 emit_insn (gen_movdf (dest1, word0));
3449 emit_insn (gen_movdf (dest2, word1));
3450 }
3451 DONE;
3452 })
3453
3454 (define_split
3455 [(set (match_operand:TF 0 "memory_operand" "")
3456 (match_operand:TF 1 "register_operand" ""))]
3457 "(reload_completed
3458 && offsettable_memref_p (operands[0])
3459 && (! TARGET_ARCH64
3460 || ! TARGET_HARD_QUAD
3461 || ! fp_register_operand (operands[1], TFmode)))"
3462 [(clobber (const_int 0))]
3463 {
3464 rtx set_src = operands[1];
3465
3466 emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
3467 gen_df_reg (set_src, 0)));
3468 emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
3469 gen_df_reg (set_src, 1)));
3470 DONE;
3471 })
3472 \f
3473 ;; SPARC V9 conditional move instructions.
3474
3475 ;; We can handle larger constants here for some flavors, but for now we keep
3476 ;; it simple and only allow those constants supported by all flavors.
3477 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
3478 ;; 3 contains the constant if one is present, but we handle either for
3479 ;; generality (sparc.c puts a constant in operand 2).
3480
3481 (define_expand "movqicc"
3482 [(set (match_operand:QI 0 "register_operand" "")
3483 (if_then_else:QI (match_operand 1 "comparison_operator" "")
3484 (match_operand:QI 2 "arith10_operand" "")
3485 (match_operand:QI 3 "arith10_operand" "")))]
3486 "TARGET_V9"
3487 {
3488 enum rtx_code code = GET_CODE (operands[1]);
3489
3490 if (GET_MODE (sparc_compare_op0) == DImode
3491 && ! TARGET_ARCH64)
3492 FAIL;
3493
3494 if (sparc_compare_op1 == const0_rtx
3495 && GET_CODE (sparc_compare_op0) == REG
3496 && GET_MODE (sparc_compare_op0) == DImode
3497 && v9_regcmp_p (code))
3498 {
3499 operands[1] = gen_rtx_fmt_ee (code, DImode,
3500 sparc_compare_op0, sparc_compare_op1);
3501 }
3502 else
3503 {
3504 rtx cc_reg = gen_compare_reg (code,
3505 sparc_compare_op0, sparc_compare_op1);
3506 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3507 }
3508 })
3509
3510 (define_expand "movhicc"
3511 [(set (match_operand:HI 0 "register_operand" "")
3512 (if_then_else:HI (match_operand 1 "comparison_operator" "")
3513 (match_operand:HI 2 "arith10_operand" "")
3514 (match_operand:HI 3 "arith10_operand" "")))]
3515 "TARGET_V9"
3516 {
3517 enum rtx_code code = GET_CODE (operands[1]);
3518
3519 if (GET_MODE (sparc_compare_op0) == DImode
3520 && ! TARGET_ARCH64)
3521 FAIL;
3522
3523 if (sparc_compare_op1 == const0_rtx
3524 && GET_CODE (sparc_compare_op0) == REG
3525 && GET_MODE (sparc_compare_op0) == DImode
3526 && v9_regcmp_p (code))
3527 {
3528 operands[1] = gen_rtx_fmt_ee (code, DImode,
3529 sparc_compare_op0, sparc_compare_op1);
3530 }
3531 else
3532 {
3533 rtx cc_reg = gen_compare_reg (code,
3534 sparc_compare_op0, sparc_compare_op1);
3535 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3536 }
3537 })
3538
3539 (define_expand "movsicc"
3540 [(set (match_operand:SI 0 "register_operand" "")
3541 (if_then_else:SI (match_operand 1 "comparison_operator" "")
3542 (match_operand:SI 2 "arith10_operand" "")
3543 (match_operand:SI 3 "arith10_operand" "")))]
3544 "TARGET_V9"
3545 {
3546 enum rtx_code code = GET_CODE (operands[1]);
3547 enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
3548
3549 if (sparc_compare_op1 == const0_rtx
3550 && GET_CODE (sparc_compare_op0) == REG
3551 && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
3552 {
3553 operands[1] = gen_rtx_fmt_ee (code, op0_mode,
3554 sparc_compare_op0, sparc_compare_op1);
3555 }
3556 else
3557 {
3558 rtx cc_reg = gen_compare_reg (code,
3559 sparc_compare_op0, sparc_compare_op1);
3560 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3561 cc_reg, const0_rtx);
3562 }
3563 })
3564
3565 (define_expand "movdicc"
3566 [(set (match_operand:DI 0 "register_operand" "")
3567 (if_then_else:DI (match_operand 1 "comparison_operator" "")
3568 (match_operand:DI 2 "arith10_double_operand" "")
3569 (match_operand:DI 3 "arith10_double_operand" "")))]
3570 "TARGET_ARCH64"
3571 {
3572 enum rtx_code code = GET_CODE (operands[1]);
3573
3574 if (sparc_compare_op1 == const0_rtx
3575 && GET_CODE (sparc_compare_op0) == REG
3576 && GET_MODE (sparc_compare_op0) == DImode
3577 && v9_regcmp_p (code))
3578 {
3579 operands[1] = gen_rtx_fmt_ee (code, DImode,
3580 sparc_compare_op0, sparc_compare_op1);
3581 }
3582 else
3583 {
3584 rtx cc_reg = gen_compare_reg (code,
3585 sparc_compare_op0, sparc_compare_op1);
3586 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3587 cc_reg, const0_rtx);
3588 }
3589 })
3590
3591 (define_expand "movsfcc"
3592 [(set (match_operand:SF 0 "register_operand" "")
3593 (if_then_else:SF (match_operand 1 "comparison_operator" "")
3594 (match_operand:SF 2 "register_operand" "")
3595 (match_operand:SF 3 "register_operand" "")))]
3596 "TARGET_V9 && TARGET_FPU"
3597 {
3598 enum rtx_code code = GET_CODE (operands[1]);
3599
3600 if (GET_MODE (sparc_compare_op0) == DImode
3601 && ! TARGET_ARCH64)
3602 FAIL;
3603
3604 if (sparc_compare_op1 == const0_rtx
3605 && GET_CODE (sparc_compare_op0) == REG
3606 && GET_MODE (sparc_compare_op0) == DImode
3607 && v9_regcmp_p (code))
3608 {
3609 operands[1] = gen_rtx_fmt_ee (code, DImode,
3610 sparc_compare_op0, sparc_compare_op1);
3611 }
3612 else
3613 {
3614 rtx cc_reg = gen_compare_reg (code,
3615 sparc_compare_op0, sparc_compare_op1);
3616 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3617 }
3618 })
3619
3620 (define_expand "movdfcc"
3621 [(set (match_operand:DF 0 "register_operand" "")
3622 (if_then_else:DF (match_operand 1 "comparison_operator" "")
3623 (match_operand:DF 2 "register_operand" "")
3624 (match_operand:DF 3 "register_operand" "")))]
3625 "TARGET_V9 && TARGET_FPU"
3626 {
3627 enum rtx_code code = GET_CODE (operands[1]);
3628
3629 if (GET_MODE (sparc_compare_op0) == DImode
3630 && ! TARGET_ARCH64)
3631 FAIL;
3632
3633 if (sparc_compare_op1 == const0_rtx
3634 && GET_CODE (sparc_compare_op0) == REG
3635 && GET_MODE (sparc_compare_op0) == DImode
3636 && v9_regcmp_p (code))
3637 {
3638 operands[1] = gen_rtx_fmt_ee (code, DImode,
3639 sparc_compare_op0, sparc_compare_op1);
3640 }
3641 else
3642 {
3643 rtx cc_reg = gen_compare_reg (code,
3644 sparc_compare_op0, sparc_compare_op1);
3645 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3646 }
3647 })
3648
3649 (define_expand "movtfcc"
3650 [(set (match_operand:TF 0 "register_operand" "")
3651 (if_then_else:TF (match_operand 1 "comparison_operator" "")
3652 (match_operand:TF 2 "register_operand" "")
3653 (match_operand:TF 3 "register_operand" "")))]
3654 "TARGET_V9 && TARGET_FPU"
3655 {
3656 enum rtx_code code = GET_CODE (operands[1]);
3657
3658 if (GET_MODE (sparc_compare_op0) == DImode
3659 && ! TARGET_ARCH64)
3660 FAIL;
3661
3662 if (sparc_compare_op1 == const0_rtx
3663 && GET_CODE (sparc_compare_op0) == REG
3664 && GET_MODE (sparc_compare_op0) == DImode
3665 && v9_regcmp_p (code))
3666 {
3667 operands[1] = gen_rtx_fmt_ee (code, DImode,
3668 sparc_compare_op0, sparc_compare_op1);
3669 }
3670 else
3671 {
3672 rtx cc_reg = gen_compare_reg (code,
3673 sparc_compare_op0, sparc_compare_op1);
3674 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3675 }
3676 })
3677
3678 ;; Conditional move define_insns.
3679
3680 (define_insn "*movqi_cc_sp64"
3681 [(set (match_operand:QI 0 "register_operand" "=r,r")
3682 (if_then_else:QI (match_operator 1 "comparison_operator"
3683 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3684 (const_int 0)])
3685 (match_operand:QI 3 "arith11_operand" "rL,0")
3686 (match_operand:QI 4 "arith11_operand" "0,rL")))]
3687 "TARGET_V9"
3688 "@
3689 mov%C1\t%x2, %3, %0
3690 mov%c1\t%x2, %4, %0"
3691 [(set_attr "type" "cmove")])
3692
3693 (define_insn "*movhi_cc_sp64"
3694 [(set (match_operand:HI 0 "register_operand" "=r,r")
3695 (if_then_else:HI (match_operator 1 "comparison_operator"
3696 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3697 (const_int 0)])
3698 (match_operand:HI 3 "arith11_operand" "rL,0")
3699 (match_operand:HI 4 "arith11_operand" "0,rL")))]
3700 "TARGET_V9"
3701 "@
3702 mov%C1\t%x2, %3, %0
3703 mov%c1\t%x2, %4, %0"
3704 [(set_attr "type" "cmove")])
3705
3706 (define_insn "*movsi_cc_sp64"
3707 [(set (match_operand:SI 0 "register_operand" "=r,r")
3708 (if_then_else:SI (match_operator 1 "comparison_operator"
3709 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3710 (const_int 0)])
3711 (match_operand:SI 3 "arith11_operand" "rL,0")
3712 (match_operand:SI 4 "arith11_operand" "0,rL")))]
3713 "TARGET_V9"
3714 "@
3715 mov%C1\t%x2, %3, %0
3716 mov%c1\t%x2, %4, %0"
3717 [(set_attr "type" "cmove")])
3718
3719 ;; ??? The constraints of operands 3,4 need work.
3720 (define_insn "*movdi_cc_sp64"
3721 [(set (match_operand:DI 0 "register_operand" "=r,r")
3722 (if_then_else:DI (match_operator 1 "comparison_operator"
3723 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3724 (const_int 0)])
3725 (match_operand:DI 3 "arith11_double_operand" "rLH,0")
3726 (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
3727 "TARGET_ARCH64"
3728 "@
3729 mov%C1\t%x2, %3, %0
3730 mov%c1\t%x2, %4, %0"
3731 [(set_attr "type" "cmove")])
3732
3733 (define_insn "*movdi_cc_sp64_trunc"
3734 [(set (match_operand:SI 0 "register_operand" "=r,r")
3735 (if_then_else:SI (match_operator 1 "comparison_operator"
3736 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3737 (const_int 0)])
3738 (match_operand:SI 3 "arith11_double_operand" "rLH,0")
3739 (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
3740 "TARGET_ARCH64"
3741 "@
3742 mov%C1\t%x2, %3, %0
3743 mov%c1\t%x2, %4, %0"
3744 [(set_attr "type" "cmove")])
3745
3746 (define_insn "*movsf_cc_sp64"
3747 [(set (match_operand:SF 0 "register_operand" "=f,f")
3748 (if_then_else:SF (match_operator 1 "comparison_operator"
3749 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3750 (const_int 0)])
3751 (match_operand:SF 3 "register_operand" "f,0")
3752 (match_operand:SF 4 "register_operand" "0,f")))]
3753 "TARGET_V9 && TARGET_FPU"
3754 "@
3755 fmovs%C1\t%x2, %3, %0
3756 fmovs%c1\t%x2, %4, %0"
3757 [(set_attr "type" "fpcmove")])
3758
3759 (define_insn "movdf_cc_sp64"
3760 [(set (match_operand:DF 0 "register_operand" "=e,e")
3761 (if_then_else:DF (match_operator 1 "comparison_operator"
3762 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3763 (const_int 0)])
3764 (match_operand:DF 3 "register_operand" "e,0")
3765 (match_operand:DF 4 "register_operand" "0,e")))]
3766 "TARGET_V9 && TARGET_FPU"
3767 "@
3768 fmovd%C1\t%x2, %3, %0
3769 fmovd%c1\t%x2, %4, %0"
3770 [(set_attr "type" "fpcmove")
3771 (set_attr "fptype" "double")])
3772
3773 (define_insn "*movtf_cc_hq_sp64"
3774 [(set (match_operand:TF 0 "register_operand" "=e,e")
3775 (if_then_else:TF (match_operator 1 "comparison_operator"
3776 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3777 (const_int 0)])
3778 (match_operand:TF 3 "register_operand" "e,0")
3779 (match_operand:TF 4 "register_operand" "0,e")))]
3780 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3781 "@
3782 fmovq%C1\t%x2, %3, %0
3783 fmovq%c1\t%x2, %4, %0"
3784 [(set_attr "type" "fpcmove")])
3785
3786 (define_insn_and_split "*movtf_cc_sp64"
3787 [(set (match_operand:TF 0 "register_operand" "=e,e")
3788 (if_then_else:TF (match_operator 1 "comparison_operator"
3789 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3790 (const_int 0)])
3791 (match_operand:TF 3 "register_operand" "e,0")
3792 (match_operand:TF 4 "register_operand" "0,e")))]
3793 "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
3794 "#"
3795 "&& reload_completed"
3796 [(clobber (const_int 0))]
3797 {
3798 rtx set_dest = operands[0];
3799 rtx set_srca = operands[3];
3800 rtx set_srcb = operands[4];
3801 int third = rtx_equal_p (set_dest, set_srca);
3802 rtx dest1, dest2;
3803 rtx srca1, srca2, srcb1, srcb2;
3804
3805 dest1 = gen_df_reg (set_dest, 0);
3806 dest2 = gen_df_reg (set_dest, 1);
3807 srca1 = gen_df_reg (set_srca, 0);
3808 srca2 = gen_df_reg (set_srca, 1);
3809 srcb1 = gen_df_reg (set_srcb, 0);
3810 srcb2 = gen_df_reg (set_srcb, 1);
3811
3812 /* Now emit using the real source and destination we found, swapping
3813 the order if we detect overlap. */
3814 if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3815 || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3816 {
3817 emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3818 emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3819 }
3820 else
3821 {
3822 emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3823 emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3824 }
3825 DONE;
3826 }
3827 [(set_attr "length" "2")])
3828
3829 (define_insn "*movqi_cc_reg_sp64"
3830 [(set (match_operand:QI 0 "register_operand" "=r,r")
3831 (if_then_else:QI (match_operator 1 "v9_regcmp_op"
3832 [(match_operand:DI 2 "register_operand" "r,r")
3833 (const_int 0)])
3834 (match_operand:QI 3 "arith10_operand" "rM,0")
3835 (match_operand:QI 4 "arith10_operand" "0,rM")))]
3836 "TARGET_ARCH64"
3837 "@
3838 movr%D1\t%2, %r3, %0
3839 movr%d1\t%2, %r4, %0"
3840 [(set_attr "type" "cmove")])
3841
3842 (define_insn "*movhi_cc_reg_sp64"
3843 [(set (match_operand:HI 0 "register_operand" "=r,r")
3844 (if_then_else:HI (match_operator 1 "v9_regcmp_op"
3845 [(match_operand:DI 2 "register_operand" "r,r")
3846 (const_int 0)])
3847 (match_operand:HI 3 "arith10_operand" "rM,0")
3848 (match_operand:HI 4 "arith10_operand" "0,rM")))]
3849 "TARGET_ARCH64"
3850 "@
3851 movr%D1\t%2, %r3, %0
3852 movr%d1\t%2, %r4, %0"
3853 [(set_attr "type" "cmove")])
3854
3855 (define_insn "*movsi_cc_reg_sp64"
3856 [(set (match_operand:SI 0 "register_operand" "=r,r")
3857 (if_then_else:SI (match_operator 1 "v9_regcmp_op"
3858 [(match_operand:DI 2 "register_operand" "r,r")
3859 (const_int 0)])
3860 (match_operand:SI 3 "arith10_operand" "rM,0")
3861 (match_operand:SI 4 "arith10_operand" "0,rM")))]
3862 "TARGET_ARCH64"
3863 "@
3864 movr%D1\t%2, %r3, %0
3865 movr%d1\t%2, %r4, %0"
3866 [(set_attr "type" "cmove")])
3867
3868 ;; ??? The constraints of operands 3,4 need work.
3869 (define_insn "*movdi_cc_reg_sp64"
3870 [(set (match_operand:DI 0 "register_operand" "=r,r")
3871 (if_then_else:DI (match_operator 1 "v9_regcmp_op"
3872 [(match_operand:DI 2 "register_operand" "r,r")
3873 (const_int 0)])
3874 (match_operand:DI 3 "arith10_double_operand" "rMH,0")
3875 (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
3876 "TARGET_ARCH64"
3877 "@
3878 movr%D1\t%2, %r3, %0
3879 movr%d1\t%2, %r4, %0"
3880 [(set_attr "type" "cmove")])
3881
3882 (define_insn "*movdi_cc_reg_sp64_trunc"
3883 [(set (match_operand:SI 0 "register_operand" "=r,r")
3884 (if_then_else:SI (match_operator 1 "v9_regcmp_op"
3885 [(match_operand:DI 2 "register_operand" "r,r")
3886 (const_int 0)])
3887 (match_operand:SI 3 "arith10_double_operand" "rMH,0")
3888 (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
3889 "TARGET_ARCH64"
3890 "@
3891 movr%D1\t%2, %r3, %0
3892 movr%d1\t%2, %r4, %0"
3893 [(set_attr "type" "cmove")])
3894
3895 (define_insn "*movsf_cc_reg_sp64"
3896 [(set (match_operand:SF 0 "register_operand" "=f,f")
3897 (if_then_else:SF (match_operator 1 "v9_regcmp_op"
3898 [(match_operand:DI 2 "register_operand" "r,r")
3899 (const_int 0)])
3900 (match_operand:SF 3 "register_operand" "f,0")
3901 (match_operand:SF 4 "register_operand" "0,f")))]
3902 "TARGET_ARCH64 && TARGET_FPU"
3903 "@
3904 fmovrs%D1\t%2, %3, %0
3905 fmovrs%d1\t%2, %4, %0"
3906 [(set_attr "type" "fpcrmove")])
3907
3908 (define_insn "movdf_cc_reg_sp64"
3909 [(set (match_operand:DF 0 "register_operand" "=e,e")
3910 (if_then_else:DF (match_operator 1 "v9_regcmp_op"
3911 [(match_operand:DI 2 "register_operand" "r,r")
3912 (const_int 0)])
3913 (match_operand:DF 3 "register_operand" "e,0")
3914 (match_operand:DF 4 "register_operand" "0,e")))]
3915 "TARGET_ARCH64 && TARGET_FPU"
3916 "@
3917 fmovrd%D1\t%2, %3, %0
3918 fmovrd%d1\t%2, %4, %0"
3919 [(set_attr "type" "fpcrmove")
3920 (set_attr "fptype" "double")])
3921
3922 (define_insn "*movtf_cc_reg_hq_sp64"
3923 [(set (match_operand:TF 0 "register_operand" "=e,e")
3924 (if_then_else:TF (match_operator 1 "v9_regcmp_op"
3925 [(match_operand:DI 2 "register_operand" "r,r")
3926 (const_int 0)])
3927 (match_operand:TF 3 "register_operand" "e,0")
3928 (match_operand:TF 4 "register_operand" "0,e")))]
3929 "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3930 "@
3931 fmovrq%D1\t%2, %3, %0
3932 fmovrq%d1\t%2, %4, %0"
3933 [(set_attr "type" "fpcrmove")])
3934
3935 (define_insn_and_split "*movtf_cc_reg_sp64"
3936 [(set (match_operand:TF 0 "register_operand" "=e,e")
3937 (if_then_else:TF (match_operator 1 "v9_regcmp_op"
3938 [(match_operand:DI 2 "register_operand" "r,r")
3939 (const_int 0)])
3940 (match_operand:TF 3 "register_operand" "e,0")
3941 (match_operand:TF 4 "register_operand" "0,e")))]
3942 "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
3943 "#"
3944 "&& reload_completed"
3945 [(clobber (const_int 0))]
3946 {
3947 rtx set_dest = operands[0];
3948 rtx set_srca = operands[3];
3949 rtx set_srcb = operands[4];
3950 int third = rtx_equal_p (set_dest, set_srca);
3951 rtx dest1, dest2;
3952 rtx srca1, srca2, srcb1, srcb2;
3953
3954 dest1 = gen_df_reg (set_dest, 0);
3955 dest2 = gen_df_reg (set_dest, 1);
3956 srca1 = gen_df_reg (set_srca, 0);
3957 srca2 = gen_df_reg (set_srca, 1);
3958 srcb1 = gen_df_reg (set_srcb, 0);
3959 srcb2 = gen_df_reg (set_srcb, 1);
3960
3961 /* Now emit using the real source and destination we found, swapping
3962 the order if we detect overlap. */
3963 if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3964 || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3965 {
3966 emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3967 emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3968 }
3969 else
3970 {
3971 emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3972 emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3973 }
3974 DONE;
3975 }
3976 [(set_attr "length" "2")])
3977
3978 \f
3979 ;;- zero extension instructions
3980
3981 ;; These patterns originally accepted general_operands, however, slightly
3982 ;; better code is generated by only accepting register_operands, and then
3983 ;; letting combine generate the ldu[hb] insns.
3984
3985 (define_expand "zero_extendhisi2"
3986 [(set (match_operand:SI 0 "register_operand" "")
3987 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
3988 ""
3989 {
3990 rtx temp = gen_reg_rtx (SImode);
3991 rtx shift_16 = GEN_INT (16);
3992 int op1_subbyte = 0;
3993
3994 if (GET_CODE (operand1) == SUBREG)
3995 {
3996 op1_subbyte = SUBREG_BYTE (operand1);
3997 op1_subbyte /= GET_MODE_SIZE (SImode);
3998 op1_subbyte *= GET_MODE_SIZE (SImode);
3999 operand1 = XEXP (operand1, 0);
4000 }
4001
4002 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4003 shift_16));
4004 emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
4005 DONE;
4006 })
4007
4008 (define_insn "*zero_extendhisi2_insn"
4009 [(set (match_operand:SI 0 "register_operand" "=r")
4010 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4011 ""
4012 "lduh\t%1, %0"
4013 [(set_attr "type" "load")
4014 (set_attr "us3load_type" "3cycle")])
4015
4016 (define_expand "zero_extendqihi2"
4017 [(set (match_operand:HI 0 "register_operand" "")
4018 (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
4019 ""
4020 "")
4021
4022 (define_insn "*zero_extendqihi2_insn"
4023 [(set (match_operand:HI 0 "register_operand" "=r,r")
4024 (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
4025 "GET_CODE (operands[1]) != CONST_INT"
4026 "@
4027 and\t%1, 0xff, %0
4028 ldub\t%1, %0"
4029 [(set_attr "type" "*,load")
4030 (set_attr "us3load_type" "*,3cycle")])
4031
4032 (define_expand "zero_extendqisi2"
4033 [(set (match_operand:SI 0 "register_operand" "")
4034 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4035 ""
4036 "")
4037
4038 (define_insn "*zero_extendqisi2_insn"
4039 [(set (match_operand:SI 0 "register_operand" "=r,r")
4040 (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
4041 "GET_CODE (operands[1]) != CONST_INT"
4042 "@
4043 and\t%1, 0xff, %0
4044 ldub\t%1, %0"
4045 [(set_attr "type" "*,load")
4046 (set_attr "us3load_type" "*,3cycle")])
4047
4048 (define_expand "zero_extendqidi2"
4049 [(set (match_operand:DI 0 "register_operand" "")
4050 (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
4051 "TARGET_ARCH64"
4052 "")
4053
4054 (define_insn "*zero_extendqidi2_insn"
4055 [(set (match_operand:DI 0 "register_operand" "=r,r")
4056 (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
4057 "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4058 "@
4059 and\t%1, 0xff, %0
4060 ldub\t%1, %0"
4061 [(set_attr "type" "*,load")
4062 (set_attr "us3load_type" "*,3cycle")])
4063
4064 (define_expand "zero_extendhidi2"
4065 [(set (match_operand:DI 0 "register_operand" "")
4066 (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
4067 "TARGET_ARCH64"
4068 {
4069 rtx temp = gen_reg_rtx (DImode);
4070 rtx shift_48 = GEN_INT (48);
4071 int op1_subbyte = 0;
4072
4073 if (GET_CODE (operand1) == SUBREG)
4074 {
4075 op1_subbyte = SUBREG_BYTE (operand1);
4076 op1_subbyte /= GET_MODE_SIZE (DImode);
4077 op1_subbyte *= GET_MODE_SIZE (DImode);
4078 operand1 = XEXP (operand1, 0);
4079 }
4080
4081 emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4082 shift_48));
4083 emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
4084 DONE;
4085 })
4086
4087 (define_insn "*zero_extendhidi2_insn"
4088 [(set (match_operand:DI 0 "register_operand" "=r")
4089 (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4090 "TARGET_ARCH64"
4091 "lduh\t%1, %0"
4092 [(set_attr "type" "load")
4093 (set_attr "us3load_type" "3cycle")])
4094
4095
4096 ;; ??? Write truncdisi pattern using sra?
4097
4098 (define_expand "zero_extendsidi2"
4099 [(set (match_operand:DI 0 "register_operand" "")
4100 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
4101 ""
4102 "")
4103
4104 (define_insn "*zero_extendsidi2_insn_sp64"
4105 [(set (match_operand:DI 0 "register_operand" "=r,r")
4106 (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4107 "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4108 "@
4109 srl\t%1, 0, %0
4110 lduw\t%1, %0"
4111 [(set_attr "type" "shift,load")])
4112
4113 (define_insn_and_split "*zero_extendsidi2_insn_sp32"
4114 [(set (match_operand:DI 0 "register_operand" "=r")
4115 (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
4116 "! TARGET_ARCH64"
4117 "#"
4118 "&& reload_completed"
4119 [(set (match_dup 2) (match_dup 3))
4120 (set (match_dup 4) (match_dup 5))]
4121 {
4122 rtx dest1, dest2;
4123
4124 dest1 = gen_highpart (SImode, operands[0]);
4125 dest2 = gen_lowpart (SImode, operands[0]);
4126
4127 /* Swap the order in case of overlap. */
4128 if (REGNO (dest1) == REGNO (operands[1]))
4129 {
4130 operands[2] = dest2;
4131 operands[3] = operands[1];
4132 operands[4] = dest1;
4133 operands[5] = const0_rtx;
4134 }
4135 else
4136 {
4137 operands[2] = dest1;
4138 operands[3] = const0_rtx;
4139 operands[4] = dest2;
4140 operands[5] = operands[1];
4141 }
4142 }
4143 [(set_attr "length" "2")])
4144
4145 ;; Simplify comparisons of extended values.
4146
4147 (define_insn "*cmp_zero_extendqisi2"
4148 [(set (reg:CC 100)
4149 (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
4150 (const_int 0)))]
4151 ""
4152 "andcc\t%0, 0xff, %%g0"
4153 [(set_attr "type" "compare")])
4154
4155 (define_insn "*cmp_zero_qi"
4156 [(set (reg:CC 100)
4157 (compare:CC (match_operand:QI 0 "register_operand" "r")
4158 (const_int 0)))]
4159 ""
4160 "andcc\t%0, 0xff, %%g0"
4161 [(set_attr "type" "compare")])
4162
4163 (define_insn "*cmp_zero_extendqisi2_set"
4164 [(set (reg:CC 100)
4165 (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
4166 (const_int 0)))
4167 (set (match_operand:SI 0 "register_operand" "=r")
4168 (zero_extend:SI (match_dup 1)))]
4169 ""
4170 "andcc\t%1, 0xff, %0"
4171 [(set_attr "type" "compare")])
4172
4173 (define_insn "*cmp_zero_extendqisi2_andcc_set"
4174 [(set (reg:CC 100)
4175 (compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
4176 (const_int 255))
4177 (const_int 0)))
4178 (set (match_operand:SI 0 "register_operand" "=r")
4179 (zero_extend:SI (subreg:QI (match_dup 1) 0)))]
4180 ""
4181 "andcc\t%1, 0xff, %0"
4182 [(set_attr "type" "compare")])
4183
4184 (define_insn "*cmp_zero_extendqidi2"
4185 [(set (reg:CCX 100)
4186 (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
4187 (const_int 0)))]
4188 "TARGET_ARCH64"
4189 "andcc\t%0, 0xff, %%g0"
4190 [(set_attr "type" "compare")])
4191
4192 (define_insn "*cmp_zero_qi_sp64"
4193 [(set (reg:CCX 100)
4194 (compare:CCX (match_operand:QI 0 "register_operand" "r")
4195 (const_int 0)))]
4196 "TARGET_ARCH64"
4197 "andcc\t%0, 0xff, %%g0"
4198 [(set_attr "type" "compare")])
4199
4200 (define_insn "*cmp_zero_extendqidi2_set"
4201 [(set (reg:CCX 100)
4202 (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
4203 (const_int 0)))
4204 (set (match_operand:DI 0 "register_operand" "=r")
4205 (zero_extend:DI (match_dup 1)))]
4206 "TARGET_ARCH64"
4207 "andcc\t%1, 0xff, %0"
4208 [(set_attr "type" "compare")])
4209
4210 (define_insn "*cmp_zero_extendqidi2_andcc_set"
4211 [(set (reg:CCX 100)
4212 (compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
4213 (const_int 255))
4214 (const_int 0)))
4215 (set (match_operand:DI 0 "register_operand" "=r")
4216 (zero_extend:DI (subreg:QI (match_dup 1) 0)))]
4217 "TARGET_ARCH64"
4218 "andcc\t%1, 0xff, %0"
4219 [(set_attr "type" "compare")])
4220
4221 ;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
4222
4223 (define_insn "*cmp_siqi_trunc"
4224 [(set (reg:CC 100)
4225 (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
4226 (const_int 0)))]
4227 ""
4228 "andcc\t%0, 0xff, %%g0"
4229 [(set_attr "type" "compare")])
4230
4231 (define_insn "*cmp_siqi_trunc_set"
4232 [(set (reg:CC 100)
4233 (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
4234 (const_int 0)))
4235 (set (match_operand:QI 0 "register_operand" "=r")
4236 (subreg:QI (match_dup 1) 3))]
4237 ""
4238 "andcc\t%1, 0xff, %0"
4239 [(set_attr "type" "compare")])
4240
4241 (define_insn "*cmp_diqi_trunc"
4242 [(set (reg:CC 100)
4243 (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
4244 (const_int 0)))]
4245 "TARGET_ARCH64"
4246 "andcc\t%0, 0xff, %%g0"
4247 [(set_attr "type" "compare")])
4248
4249 (define_insn "*cmp_diqi_trunc_set"
4250 [(set (reg:CC 100)
4251 (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
4252 (const_int 0)))
4253 (set (match_operand:QI 0 "register_operand" "=r")
4254 (subreg:QI (match_dup 1) 7))]
4255 "TARGET_ARCH64"
4256 "andcc\t%1, 0xff, %0"
4257 [(set_attr "type" "compare")])
4258 \f
4259 ;;- sign extension instructions
4260
4261 ;; These patterns originally accepted general_operands, however, slightly
4262 ;; better code is generated by only accepting register_operands, and then
4263 ;; letting combine generate the lds[hb] insns.
4264
4265 (define_expand "extendhisi2"
4266 [(set (match_operand:SI 0 "register_operand" "")
4267 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4268 ""
4269 {
4270 rtx temp = gen_reg_rtx (SImode);
4271 rtx shift_16 = GEN_INT (16);
4272 int op1_subbyte = 0;
4273
4274 if (GET_CODE (operand1) == SUBREG)
4275 {
4276 op1_subbyte = SUBREG_BYTE (operand1);
4277 op1_subbyte /= GET_MODE_SIZE (SImode);
4278 op1_subbyte *= GET_MODE_SIZE (SImode);
4279 operand1 = XEXP (operand1, 0);
4280 }
4281
4282 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4283 shift_16));
4284 emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
4285 DONE;
4286 })
4287
4288 (define_insn "*sign_extendhisi2_insn"
4289 [(set (match_operand:SI 0 "register_operand" "=r")
4290 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4291 ""
4292 "ldsh\t%1, %0"
4293 [(set_attr "type" "sload")
4294 (set_attr "us3load_type" "3cycle")])
4295
4296 (define_expand "extendqihi2"
4297 [(set (match_operand:HI 0 "register_operand" "")
4298 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
4299 ""
4300 {
4301 rtx temp = gen_reg_rtx (SImode);
4302 rtx shift_24 = GEN_INT (24);
4303 int op1_subbyte = 0;
4304 int op0_subbyte = 0;
4305
4306 if (GET_CODE (operand1) == SUBREG)
4307 {
4308 op1_subbyte = SUBREG_BYTE (operand1);
4309 op1_subbyte /= GET_MODE_SIZE (SImode);
4310 op1_subbyte *= GET_MODE_SIZE (SImode);
4311 operand1 = XEXP (operand1, 0);
4312 }
4313 if (GET_CODE (operand0) == SUBREG)
4314 {
4315 op0_subbyte = SUBREG_BYTE (operand0);
4316 op0_subbyte /= GET_MODE_SIZE (SImode);
4317 op0_subbyte *= GET_MODE_SIZE (SImode);
4318 operand0 = XEXP (operand0, 0);
4319 }
4320 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4321 shift_24));
4322 if (GET_MODE (operand0) != SImode)
4323 operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
4324 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4325 DONE;
4326 })
4327
4328 (define_insn "*sign_extendqihi2_insn"
4329 [(set (match_operand:HI 0 "register_operand" "=r")
4330 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
4331 ""
4332 "ldsb\t%1, %0"
4333 [(set_attr "type" "sload")
4334 (set_attr "us3load_type" "3cycle")])
4335
4336 (define_expand "extendqisi2"
4337 [(set (match_operand:SI 0 "register_operand" "")
4338 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4339 ""
4340 {
4341 rtx temp = gen_reg_rtx (SImode);
4342 rtx shift_24 = GEN_INT (24);
4343 int op1_subbyte = 0;
4344
4345 if (GET_CODE (operand1) == SUBREG)
4346 {
4347 op1_subbyte = SUBREG_BYTE (operand1);
4348 op1_subbyte /= GET_MODE_SIZE (SImode);
4349 op1_subbyte *= GET_MODE_SIZE (SImode);
4350 operand1 = XEXP (operand1, 0);
4351 }
4352
4353 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4354 shift_24));
4355 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4356 DONE;
4357 })
4358
4359 (define_insn "*sign_extendqisi2_insn"
4360 [(set (match_operand:SI 0 "register_operand" "=r")
4361 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4362 ""
4363 "ldsb\t%1, %0"
4364 [(set_attr "type" "sload")
4365 (set_attr "us3load_type" "3cycle")])
4366
4367 (define_expand "extendqidi2"
4368 [(set (match_operand:DI 0 "register_operand" "")
4369 (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
4370 "TARGET_ARCH64"
4371 {
4372 rtx temp = gen_reg_rtx (DImode);
4373 rtx shift_56 = GEN_INT (56);
4374 int op1_subbyte = 0;
4375
4376 if (GET_CODE (operand1) == SUBREG)
4377 {
4378 op1_subbyte = SUBREG_BYTE (operand1);
4379 op1_subbyte /= GET_MODE_SIZE (DImode);
4380 op1_subbyte *= GET_MODE_SIZE (DImode);
4381 operand1 = XEXP (operand1, 0);
4382 }
4383
4384 emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4385 shift_56));
4386 emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
4387 DONE;
4388 })
4389
4390 (define_insn "*sign_extendqidi2_insn"
4391 [(set (match_operand:DI 0 "register_operand" "=r")
4392 (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
4393 "TARGET_ARCH64"
4394 "ldsb\t%1, %0"
4395 [(set_attr "type" "sload")
4396 (set_attr "us3load_type" "3cycle")])
4397
4398 (define_expand "extendhidi2"
4399 [(set (match_operand:DI 0 "register_operand" "")
4400 (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
4401 "TARGET_ARCH64"
4402 {
4403 rtx temp = gen_reg_rtx (DImode);
4404 rtx shift_48 = GEN_INT (48);
4405 int op1_subbyte = 0;
4406
4407 if (GET_CODE (operand1) == SUBREG)
4408 {
4409 op1_subbyte = SUBREG_BYTE (operand1);
4410 op1_subbyte /= GET_MODE_SIZE (DImode);
4411 op1_subbyte *= GET_MODE_SIZE (DImode);
4412 operand1 = XEXP (operand1, 0);
4413 }
4414
4415 emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4416 shift_48));
4417 emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
4418 DONE;
4419 })
4420
4421 (define_insn "*sign_extendhidi2_insn"
4422 [(set (match_operand:DI 0 "register_operand" "=r")
4423 (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4424 "TARGET_ARCH64"
4425 "ldsh\t%1, %0"
4426 [(set_attr "type" "sload")
4427 (set_attr "us3load_type" "3cycle")])
4428
4429 (define_expand "extendsidi2"
4430 [(set (match_operand:DI 0 "register_operand" "")
4431 (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
4432 "TARGET_ARCH64"
4433 "")
4434
4435 (define_insn "*sign_extendsidi2_insn"
4436 [(set (match_operand:DI 0 "register_operand" "=r,r")
4437 (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4438 "TARGET_ARCH64"
4439 "@
4440 sra\t%1, 0, %0
4441 ldsw\t%1, %0"
4442 [(set_attr "type" "shift,sload")
4443 (set_attr "us3load_type" "*,3cycle")])
4444 \f
4445 ;; Special pattern for optimizing bit-field compares. This is needed
4446 ;; because combine uses this as a canonical form.
4447
4448 (define_insn "*cmp_zero_extract"
4449 [(set (reg:CC 100)
4450 (compare:CC
4451 (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
4452 (match_operand:SI 1 "small_int_or_double" "n")
4453 (match_operand:SI 2 "small_int_or_double" "n"))
4454 (const_int 0)))]
4455 "(GET_CODE (operands[2]) == CONST_INT
4456 && INTVAL (operands[2]) > 19)
4457 || (GET_CODE (operands[2]) == CONST_DOUBLE
4458 && CONST_DOUBLE_LOW (operands[2]) > 19)"
4459 {
4460 int len = (GET_CODE (operands[1]) == CONST_INT
4461 ? INTVAL (operands[1])
4462 : CONST_DOUBLE_LOW (operands[1]));
4463 int pos = 32 -
4464 (GET_CODE (operands[2]) == CONST_INT
4465 ? INTVAL (operands[2])
4466 : CONST_DOUBLE_LOW (operands[2])) - len;
4467 HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
4468
4469 operands[1] = GEN_INT (mask);
4470 return "andcc\t%0, %1, %%g0";
4471 }
4472 [(set_attr "type" "compare")])
4473
4474 (define_insn "*cmp_zero_extract_sp64"
4475 [(set (reg:CCX 100)
4476 (compare:CCX
4477 (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
4478 (match_operand:SI 1 "small_int_or_double" "n")
4479 (match_operand:SI 2 "small_int_or_double" "n"))
4480 (const_int 0)))]
4481 "TARGET_ARCH64
4482 && ((GET_CODE (operands[2]) == CONST_INT
4483 && INTVAL (operands[2]) > 51)
4484 || (GET_CODE (operands[2]) == CONST_DOUBLE
4485 && CONST_DOUBLE_LOW (operands[2]) > 51))"
4486 {
4487 int len = (GET_CODE (operands[1]) == CONST_INT
4488 ? INTVAL (operands[1])
4489 : CONST_DOUBLE_LOW (operands[1]));
4490 int pos = 64 -
4491 (GET_CODE (operands[2]) == CONST_INT
4492 ? INTVAL (operands[2])
4493 : CONST_DOUBLE_LOW (operands[2])) - len;
4494 HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
4495
4496 operands[1] = GEN_INT (mask);
4497 return "andcc\t%0, %1, %%g0";
4498 }
4499 [(set_attr "type" "compare")])
4500 \f
4501 ;; Conversions between float, double and long double.
4502
4503 (define_insn "extendsfdf2"
4504 [(set (match_operand:DF 0 "register_operand" "=e")
4505 (float_extend:DF
4506 (match_operand:SF 1 "register_operand" "f")))]
4507 "TARGET_FPU"
4508 "fstod\t%1, %0"
4509 [(set_attr "type" "fp")
4510 (set_attr "fptype" "double")])
4511
4512 (define_expand "extendsftf2"
4513 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4514 (float_extend:TF
4515 (match_operand:SF 1 "register_operand" "")))]
4516 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4517 "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
4518
4519 (define_insn "*extendsftf2_hq"
4520 [(set (match_operand:TF 0 "register_operand" "=e")
4521 (float_extend:TF
4522 (match_operand:SF 1 "register_operand" "f")))]
4523 "TARGET_FPU && TARGET_HARD_QUAD"
4524 "fstoq\t%1, %0"
4525 [(set_attr "type" "fp")])
4526
4527 (define_expand "extenddftf2"
4528 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4529 (float_extend:TF
4530 (match_operand:DF 1 "register_operand" "")))]
4531 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4532 "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
4533
4534 (define_insn "*extenddftf2_hq"
4535 [(set (match_operand:TF 0 "register_operand" "=e")
4536 (float_extend:TF
4537 (match_operand:DF 1 "register_operand" "e")))]
4538 "TARGET_FPU && TARGET_HARD_QUAD"
4539 "fdtoq\t%1, %0"
4540 [(set_attr "type" "fp")])
4541
4542 (define_insn "truncdfsf2"
4543 [(set (match_operand:SF 0 "register_operand" "=f")
4544 (float_truncate:SF
4545 (match_operand:DF 1 "register_operand" "e")))]
4546 "TARGET_FPU"
4547 "fdtos\t%1, %0"
4548 [(set_attr "type" "fp")
4549 (set_attr "fptype" "double")])
4550
4551 (define_expand "trunctfsf2"
4552 [(set (match_operand:SF 0 "register_operand" "")
4553 (float_truncate:SF
4554 (match_operand:TF 1 "general_operand" "")))]
4555 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4556 "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
4557
4558 (define_insn "*trunctfsf2_hq"
4559 [(set (match_operand:SF 0 "register_operand" "=f")
4560 (float_truncate:SF
4561 (match_operand:TF 1 "register_operand" "e")))]
4562 "TARGET_FPU && TARGET_HARD_QUAD"
4563 "fqtos\t%1, %0"
4564 [(set_attr "type" "fp")])
4565
4566 (define_expand "trunctfdf2"
4567 [(set (match_operand:DF 0 "register_operand" "")
4568 (float_truncate:DF
4569 (match_operand:TF 1 "general_operand" "")))]
4570 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4571 "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
4572
4573 (define_insn "*trunctfdf2_hq"
4574 [(set (match_operand:DF 0 "register_operand" "=e")
4575 (float_truncate:DF
4576 (match_operand:TF 1 "register_operand" "e")))]
4577 "TARGET_FPU && TARGET_HARD_QUAD"
4578 "fqtod\t%1, %0"
4579 [(set_attr "type" "fp")])
4580 \f
4581 ;; Conversion between fixed point and floating point.
4582
4583 (define_insn "floatsisf2"
4584 [(set (match_operand:SF 0 "register_operand" "=f")
4585 (float:SF (match_operand:SI 1 "register_operand" "f")))]
4586 "TARGET_FPU"
4587 "fitos\t%1, %0"
4588 [(set_attr "type" "fp")
4589 (set_attr "fptype" "double")])
4590
4591 (define_insn "floatsidf2"
4592 [(set (match_operand:DF 0 "register_operand" "=e")
4593 (float:DF (match_operand:SI 1 "register_operand" "f")))]
4594 "TARGET_FPU"
4595 "fitod\t%1, %0"
4596 [(set_attr "type" "fp")
4597 (set_attr "fptype" "double")])
4598
4599 (define_expand "floatsitf2"
4600 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4601 (float:TF (match_operand:SI 1 "register_operand" "")))]
4602 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4603 "emit_tfmode_cvt (FLOAT, operands); DONE;")
4604
4605 (define_insn "*floatsitf2_hq"
4606 [(set (match_operand:TF 0 "register_operand" "=e")
4607 (float:TF (match_operand:SI 1 "register_operand" "f")))]
4608 "TARGET_FPU && TARGET_HARD_QUAD"
4609 "fitoq\t%1, %0"
4610 [(set_attr "type" "fp")])
4611
4612 (define_expand "floatunssitf2"
4613 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4614 (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
4615 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4616 "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
4617
4618 ;; Now the same for 64 bit sources.
4619
4620 (define_insn "floatdisf2"
4621 [(set (match_operand:SF 0 "register_operand" "=f")
4622 (float:SF (match_operand:DI 1 "register_operand" "e")))]
4623 "TARGET_V9 && TARGET_FPU"
4624 "fxtos\t%1, %0"
4625 [(set_attr "type" "fp")
4626 (set_attr "fptype" "double")])
4627
4628 (define_expand "floatunsdisf2"
4629 [(use (match_operand:SF 0 "register_operand" ""))
4630 (use (match_operand:DI 1 "register_operand" ""))]
4631 "TARGET_ARCH64 && TARGET_FPU"
4632 "sparc_emit_floatunsdi (operands); DONE;")
4633
4634 (define_insn "floatdidf2"
4635 [(set (match_operand:DF 0 "register_operand" "=e")
4636 (float:DF (match_operand:DI 1 "register_operand" "e")))]
4637 "TARGET_V9 && TARGET_FPU"
4638 "fxtod\t%1, %0"
4639 [(set_attr "type" "fp")
4640 (set_attr "fptype" "double")])
4641
4642 (define_expand "floatunsdidf2"
4643 [(use (match_operand:DF 0 "register_operand" ""))
4644 (use (match_operand:DI 1 "register_operand" ""))]
4645 "TARGET_ARCH64 && TARGET_FPU"
4646 "sparc_emit_floatunsdi (operands); DONE;")
4647
4648 (define_expand "floatditf2"
4649 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4650 (float:TF (match_operand:DI 1 "register_operand" "")))]
4651 "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4652 "emit_tfmode_cvt (FLOAT, operands); DONE;")
4653
4654 (define_insn "*floatditf2_hq"
4655 [(set (match_operand:TF 0 "register_operand" "=e")
4656 (float:TF (match_operand:DI 1 "register_operand" "e")))]
4657 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4658 "fxtoq\t%1, %0"
4659 [(set_attr "type" "fp")])
4660
4661 (define_expand "floatunsditf2"
4662 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4663 (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
4664 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4665 "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
4666
4667 ;; Convert a float to an actual integer.
4668 ;; Truncation is performed as part of the conversion.
4669
4670 (define_insn "fix_truncsfsi2"
4671 [(set (match_operand:SI 0 "register_operand" "=f")
4672 (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
4673 "TARGET_FPU"
4674 "fstoi\t%1, %0"
4675 [(set_attr "type" "fp")
4676 (set_attr "fptype" "double")])
4677
4678 (define_insn "fix_truncdfsi2"
4679 [(set (match_operand:SI 0 "register_operand" "=f")
4680 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
4681 "TARGET_FPU"
4682 "fdtoi\t%1, %0"
4683 [(set_attr "type" "fp")
4684 (set_attr "fptype" "double")])
4685
4686 (define_expand "fix_trunctfsi2"
4687 [(set (match_operand:SI 0 "register_operand" "")
4688 (fix:SI (match_operand:TF 1 "general_operand" "")))]
4689 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4690 "emit_tfmode_cvt (FIX, operands); DONE;")
4691
4692 (define_insn "*fix_trunctfsi2_hq"
4693 [(set (match_operand:SI 0 "register_operand" "=f")
4694 (fix:SI (match_operand:TF 1 "register_operand" "e")))]
4695 "TARGET_FPU && TARGET_HARD_QUAD"
4696 "fqtoi\t%1, %0"
4697 [(set_attr "type" "fp")])
4698
4699 (define_expand "fixuns_trunctfsi2"
4700 [(set (match_operand:SI 0 "register_operand" "")
4701 (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
4702 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4703 "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
4704
4705 ;; Now the same, for V9 targets
4706
4707 (define_insn "fix_truncsfdi2"
4708 [(set (match_operand:DI 0 "register_operand" "=e")
4709 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
4710 "TARGET_V9 && TARGET_FPU"
4711 "fstox\t%1, %0"
4712 [(set_attr "type" "fp")
4713 (set_attr "fptype" "double")])
4714
4715 (define_insn "fix_truncdfdi2"
4716 [(set (match_operand:DI 0 "register_operand" "=e")
4717 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
4718 "TARGET_V9 && TARGET_FPU"
4719 "fdtox\t%1, %0"
4720 [(set_attr "type" "fp")
4721 (set_attr "fptype" "double")])
4722
4723 (define_expand "fix_trunctfdi2"
4724 [(set (match_operand:DI 0 "register_operand" "")
4725 (fix:DI (match_operand:TF 1 "general_operand" "")))]
4726 "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4727 "emit_tfmode_cvt (FIX, operands); DONE;")
4728
4729 (define_insn "*fix_trunctfdi2_hq"
4730 [(set (match_operand:DI 0 "register_operand" "=e")
4731 (fix:DI (match_operand:TF 1 "register_operand" "e")))]
4732 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4733 "fqtox\t%1, %0"
4734 [(set_attr "type" "fp")])
4735
4736 (define_expand "fixuns_trunctfdi2"
4737 [(set (match_operand:DI 0 "register_operand" "")
4738 (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
4739 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4740 "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
4741 \f
4742 ;;- arithmetic instructions
4743
4744 (define_expand "adddi3"
4745 [(set (match_operand:DI 0 "register_operand" "=r")
4746 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4747 (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
4748 ""
4749 {
4750 HOST_WIDE_INT i;
4751
4752 if (! TARGET_ARCH64)
4753 {
4754 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
4755 gen_rtx_SET (VOIDmode, operands[0],
4756 gen_rtx_PLUS (DImode, operands[1],
4757 operands[2])),
4758 gen_rtx_CLOBBER (VOIDmode,
4759 gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
4760 DONE;
4761 }
4762 if (arith_double_4096_operand(operands[2], DImode))
4763 {
4764 switch (GET_CODE (operands[1]))
4765 {
4766 case CONST_INT: i = INTVAL (operands[1]); break;
4767 case CONST_DOUBLE: i = CONST_DOUBLE_LOW (operands[1]); break;
4768 default:
4769 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4770 gen_rtx_MINUS (DImode, operands[1],
4771 GEN_INT(-4096))));
4772 DONE;
4773 }
4774 emit_insn (gen_movdi (operands[0], GEN_INT (i + 4096)));
4775 DONE;
4776 }
4777 })
4778
4779 (define_insn_and_split "adddi3_insn_sp32"
4780 [(set (match_operand:DI 0 "register_operand" "=r")
4781 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4782 (match_operand:DI 2 "arith_double_operand" "rHI")))
4783 (clobber (reg:CC 100))]
4784 "! TARGET_ARCH64"
4785 "#"
4786 "&& reload_completed"
4787 [(parallel [(set (reg:CC_NOOV 100)
4788 (compare:CC_NOOV (plus:SI (match_dup 4)
4789 (match_dup 5))
4790 (const_int 0)))
4791 (set (match_dup 3)
4792 (plus:SI (match_dup 4) (match_dup 5)))])
4793 (set (match_dup 6)
4794 (plus:SI (plus:SI (match_dup 7)
4795 (match_dup 8))
4796 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4797 {
4798 operands[3] = gen_lowpart (SImode, operands[0]);
4799 operands[4] = gen_lowpart (SImode, operands[1]);
4800 operands[5] = gen_lowpart (SImode, operands[2]);
4801 operands[6] = gen_highpart (SImode, operands[0]);
4802 operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
4803 #if HOST_BITS_PER_WIDE_INT == 32
4804 if (GET_CODE (operands[2]) == CONST_INT)
4805 {
4806 if (INTVAL (operands[2]) < 0)
4807 operands[8] = constm1_rtx;
4808 else
4809 operands[8] = const0_rtx;
4810 }
4811 else
4812 #endif
4813 operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
4814 }
4815 [(set_attr "length" "2")])
4816
4817 (define_split
4818 [(set (match_operand:DI 0 "register_operand" "")
4819 (minus:DI (match_operand:DI 1 "arith_double_operand" "")
4820 (match_operand:DI 2 "arith_double_operand" "")))
4821 (clobber (reg:CC 100))]
4822 "! TARGET_ARCH64 && reload_completed"
4823 [(parallel [(set (reg:CC_NOOV 100)
4824 (compare:CC_NOOV (minus:SI (match_dup 4)
4825 (match_dup 5))
4826 (const_int 0)))
4827 (set (match_dup 3)
4828 (minus:SI (match_dup 4) (match_dup 5)))])
4829 (set (match_dup 6)
4830 (minus:SI (minus:SI (match_dup 7)
4831 (match_dup 8))
4832 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4833 {
4834 operands[3] = gen_lowpart (SImode, operands[0]);
4835 operands[4] = gen_lowpart (SImode, operands[1]);
4836 operands[5] = gen_lowpart (SImode, operands[2]);
4837 operands[6] = gen_highpart (SImode, operands[0]);
4838 operands[7] = gen_highpart (SImode, operands[1]);
4839 #if HOST_BITS_PER_WIDE_INT == 32
4840 if (GET_CODE (operands[2]) == CONST_INT)
4841 {
4842 if (INTVAL (operands[2]) < 0)
4843 operands[8] = constm1_rtx;
4844 else
4845 operands[8] = const0_rtx;
4846 }
4847 else
4848 #endif
4849 operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
4850 })
4851
4852 ;; LTU here means "carry set"
4853 (define_insn "addx"
4854 [(set (match_operand:SI 0 "register_operand" "=r")
4855 (plus:SI (plus:SI (match_operand:SI 1 "arith_operand" "%r")
4856 (match_operand:SI 2 "arith_operand" "rI"))
4857 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4858 ""
4859 "addx\t%1, %2, %0"
4860 [(set_attr "type" "ialuX")])
4861
4862 (define_insn_and_split "*addx_extend_sp32"
4863 [(set (match_operand:DI 0 "register_operand" "=r")
4864 (zero_extend:DI (plus:SI (plus:SI
4865 (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4866 (match_operand:SI 2 "arith_operand" "rI"))
4867 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4868 "! TARGET_ARCH64"
4869 "#"
4870 "&& reload_completed"
4871 [(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
4872 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
4873 (set (match_dup 4) (const_int 0))]
4874 "operands[3] = gen_lowpart (SImode, operands[0]);
4875 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);"
4876 [(set_attr "length" "2")])
4877
4878 (define_insn "*addx_extend_sp64"
4879 [(set (match_operand:DI 0 "register_operand" "=r")
4880 (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4881 (match_operand:SI 2 "arith_operand" "rI"))
4882 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4883 "TARGET_ARCH64"
4884 "addx\t%r1, %2, %0"
4885 [(set_attr "type" "ialuX")])
4886
4887 (define_insn "subx"
4888 [(set (match_operand:SI 0 "register_operand" "=r")
4889 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4890 (match_operand:SI 2 "arith_operand" "rI"))
4891 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4892 ""
4893 "subx\t%r1, %2, %0"
4894 [(set_attr "type" "ialuX")])
4895
4896 (define_insn "*subx_extend_sp64"
4897 [(set (match_operand:DI 0 "register_operand" "=r")
4898 (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4899 (match_operand:SI 2 "arith_operand" "rI"))
4900 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4901 "TARGET_ARCH64"
4902 "subx\t%r1, %2, %0"
4903 [(set_attr "type" "ialuX")])
4904
4905 (define_insn_and_split "*subx_extend"
4906 [(set (match_operand:DI 0 "register_operand" "=r")
4907 (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4908 (match_operand:SI 2 "arith_operand" "rI"))
4909 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4910 "! TARGET_ARCH64"
4911 "#"
4912 "&& reload_completed"
4913 [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
4914 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
4915 (set (match_dup 4) (const_int 0))]
4916 "operands[3] = gen_lowpart (SImode, operands[0]);
4917 operands[4] = gen_highpart (SImode, operands[0]);"
4918 [(set_attr "length" "2")])
4919
4920 (define_insn_and_split ""
4921 [(set (match_operand:DI 0 "register_operand" "=r")
4922 (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4923 (match_operand:DI 2 "register_operand" "r")))
4924 (clobber (reg:CC 100))]
4925 "! TARGET_ARCH64"
4926 "#"
4927 "&& reload_completed"
4928 [(parallel [(set (reg:CC_NOOV 100)
4929 (compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
4930 (const_int 0)))
4931 (set (match_dup 5) (plus:SI (match_dup 3) (match_dup 1)))])
4932 (set (match_dup 6)
4933 (plus:SI (plus:SI (match_dup 4) (const_int 0))
4934 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4935 "operands[3] = gen_lowpart (SImode, operands[2]);
4936 operands[4] = gen_highpart (SImode, operands[2]);
4937 operands[5] = gen_lowpart (SImode, operands[0]);
4938 operands[6] = gen_highpart (SImode, operands[0]);"
4939 [(set_attr "length" "2")])
4940
4941 (define_insn "*adddi3_sp64"
4942 [(set (match_operand:DI 0 "register_operand" "=r")
4943 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4944 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4945 "TARGET_ARCH64"
4946 "add\t%1, %2, %0")
4947
4948 (define_expand "addsi3"
4949 [(set (match_operand:SI 0 "register_operand" "=r,d")
4950 (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
4951 (match_operand:SI 2 "arith_add_operand" "rI,d")))]
4952 ""
4953 {
4954 if (arith_4096_operand(operands[2], SImode))
4955 {
4956 if (GET_CODE (operands[1]) == CONST_INT)
4957 emit_insn (gen_movsi (operands[0],
4958 GEN_INT (INTVAL (operands[1]) + 4096)));
4959 else
4960 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4961 gen_rtx_MINUS (SImode, operands[1],
4962 GEN_INT(-4096))));
4963 DONE;
4964 }
4965 })
4966
4967 (define_insn "*addsi3"
4968 [(set (match_operand:SI 0 "register_operand" "=r,d")
4969 (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
4970 (match_operand:SI 2 "arith_operand" "rI,d")))]
4971 ""
4972 "@
4973 add\t%1, %2, %0
4974 fpadd32s\t%1, %2, %0"
4975 [(set_attr "type" "*,fp")])
4976
4977 (define_insn "*cmp_cc_plus"
4978 [(set (reg:CC_NOOV 100)
4979 (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
4980 (match_operand:SI 1 "arith_operand" "rI"))
4981 (const_int 0)))]
4982 ""
4983 "addcc\t%0, %1, %%g0"
4984 [(set_attr "type" "compare")])
4985
4986 (define_insn "*cmp_ccx_plus"
4987 [(set (reg:CCX_NOOV 100)
4988 (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
4989 (match_operand:DI 1 "arith_double_operand" "rHI"))
4990 (const_int 0)))]
4991 "TARGET_ARCH64"
4992 "addcc\t%0, %1, %%g0"
4993 [(set_attr "type" "compare")])
4994
4995 (define_insn "*cmp_cc_plus_set"
4996 [(set (reg:CC_NOOV 100)
4997 (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
4998 (match_operand:SI 2 "arith_operand" "rI"))
4999 (const_int 0)))
5000 (set (match_operand:SI 0 "register_operand" "=r")
5001 (plus:SI (match_dup 1) (match_dup 2)))]
5002 ""
5003 "addcc\t%1, %2, %0"
5004 [(set_attr "type" "compare")])
5005
5006 (define_insn "*cmp_ccx_plus_set"
5007 [(set (reg:CCX_NOOV 100)
5008 (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5009 (match_operand:DI 2 "arith_double_operand" "rHI"))
5010 (const_int 0)))
5011 (set (match_operand:DI 0 "register_operand" "=r")
5012 (plus:DI (match_dup 1) (match_dup 2)))]
5013 "TARGET_ARCH64"
5014 "addcc\t%1, %2, %0"
5015 [(set_attr "type" "compare")])
5016
5017 (define_expand "subdi3"
5018 [(set (match_operand:DI 0 "register_operand" "=r")
5019 (minus:DI (match_operand:DI 1 "register_operand" "r")
5020 (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
5021 ""
5022 {
5023 if (! TARGET_ARCH64)
5024 {
5025 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
5026 gen_rtx_SET (VOIDmode, operands[0],
5027 gen_rtx_MINUS (DImode, operands[1],
5028 operands[2])),
5029 gen_rtx_CLOBBER (VOIDmode,
5030 gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
5031 DONE;
5032 }
5033 if (arith_double_4096_operand(operands[2], DImode))
5034 {
5035 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5036 gen_rtx_PLUS (DImode, operands[1],
5037 GEN_INT(-4096))));
5038 DONE;
5039 }
5040 })
5041
5042 (define_insn_and_split "*subdi3_sp32"
5043 [(set (match_operand:DI 0 "register_operand" "=r")
5044 (minus:DI (match_operand:DI 1 "register_operand" "r")
5045 (match_operand:DI 2 "arith_double_operand" "rHI")))
5046 (clobber (reg:CC 100))]
5047 "! TARGET_ARCH64"
5048 "#"
5049 "&& reload_completed
5050 && (GET_CODE (operands[2]) == CONST_INT
5051 || GET_CODE (operands[2]) == CONST_DOUBLE)"
5052 [(clobber (const_int 0))]
5053 {
5054 rtx highp, lowp;
5055
5056 highp = gen_highpart_mode (SImode, DImode, operands[2]);
5057 lowp = gen_lowpart (SImode, operands[2]);
5058 if ((lowp == const0_rtx)
5059 && (operands[0] == operands[1]))
5060 {
5061 emit_insn (gen_rtx_SET (VOIDmode,
5062 gen_highpart (SImode, operands[0]),
5063 gen_rtx_MINUS (SImode,
5064 gen_highpart_mode (SImode, DImode,
5065 operands[1]),
5066 highp)));
5067 }
5068 else
5069 {
5070 emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5071 gen_lowpart (SImode, operands[1]),
5072 lowp));
5073 emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5074 gen_highpart_mode (SImode, DImode, operands[1]),
5075 highp));
5076 }
5077 DONE;
5078 }
5079 [(set_attr "length" "2")])
5080
5081 (define_split
5082 [(set (match_operand:DI 0 "register_operand" "")
5083 (minus:DI (match_operand:DI 1 "register_operand" "")
5084 (match_operand:DI 2 "register_operand" "")))
5085 (clobber (reg:CC 100))]
5086 "! TARGET_ARCH64
5087 && reload_completed"
5088 [(clobber (const_int 0))]
5089 {
5090 emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5091 gen_lowpart (SImode, operands[1]),
5092 gen_lowpart (SImode, operands[2])));
5093 emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5094 gen_highpart (SImode, operands[1]),
5095 gen_highpart (SImode, operands[2])));
5096 DONE;
5097 })
5098
5099 (define_insn_and_split ""
5100 [(set (match_operand:DI 0 "register_operand" "=r")
5101 (minus:DI (match_operand:DI 1 "register_operand" "r")
5102 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
5103 (clobber (reg:CC 100))]
5104 "! TARGET_ARCH64"
5105 "#"
5106 "&& reload_completed"
5107 [(parallel [(set (reg:CC_NOOV 100)
5108 (compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
5109 (const_int 0)))
5110 (set (match_dup 5) (minus:SI (match_dup 3) (match_dup 2)))])
5111 (set (match_dup 6)
5112 (minus:SI (minus:SI (match_dup 4) (const_int 0))
5113 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5114 "operands[3] = gen_lowpart (SImode, operands[1]);
5115 operands[4] = gen_highpart (SImode, operands[1]);
5116 operands[5] = gen_lowpart (SImode, operands[0]);
5117 operands[6] = gen_highpart (SImode, operands[0]);"
5118 [(set_attr "length" "2")])
5119
5120 (define_insn "*subdi3_sp64"
5121 [(set (match_operand:DI 0 "register_operand" "=r")
5122 (minus:DI (match_operand:DI 1 "register_operand" "r")
5123 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5124 "TARGET_ARCH64"
5125 "sub\t%1, %2, %0")
5126
5127 (define_expand "subsi3"
5128 [(set (match_operand:SI 0 "register_operand" "=r,d")
5129 (minus:SI (match_operand:SI 1 "register_operand" "r,d")
5130 (match_operand:SI 2 "arith_add_operand" "rI,d")))]
5131 ""
5132 {
5133 if (arith_4096_operand(operands[2], SImode))
5134 {
5135 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5136 gen_rtx_PLUS (SImode, operands[1],
5137 GEN_INT(-4096))));
5138 DONE;
5139 }
5140 })
5141
5142 (define_insn "*subsi3"
5143 [(set (match_operand:SI 0 "register_operand" "=r,d")
5144 (minus:SI (match_operand:SI 1 "register_operand" "r,d")
5145 (match_operand:SI 2 "arith_operand" "rI,d")))]
5146 ""
5147 "@
5148 sub\t%1, %2, %0
5149 fpsub32s\t%1, %2, %0"
5150 [(set_attr "type" "*,fp")])
5151
5152 (define_insn "*cmp_minus_cc"
5153 [(set (reg:CC_NOOV 100)
5154 (compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
5155 (match_operand:SI 1 "arith_operand" "rI"))
5156 (const_int 0)))]
5157 ""
5158 "subcc\t%r0, %1, %%g0"
5159 [(set_attr "type" "compare")])
5160
5161 (define_insn "*cmp_minus_ccx"
5162 [(set (reg:CCX_NOOV 100)
5163 (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
5164 (match_operand:DI 1 "arith_double_operand" "rHI"))
5165 (const_int 0)))]
5166 "TARGET_ARCH64"
5167 "subcc\t%0, %1, %%g0"
5168 [(set_attr "type" "compare")])
5169
5170 (define_insn "cmp_minus_cc_set"
5171 [(set (reg:CC_NOOV 100)
5172 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5173 (match_operand:SI 2 "arith_operand" "rI"))
5174 (const_int 0)))
5175 (set (match_operand:SI 0 "register_operand" "=r")
5176 (minus:SI (match_dup 1) (match_dup 2)))]
5177 ""
5178 "subcc\t%r1, %2, %0"
5179 [(set_attr "type" "compare")])
5180
5181 (define_insn "*cmp_minus_ccx_set"
5182 [(set (reg:CCX_NOOV 100)
5183 (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
5184 (match_operand:DI 2 "arith_double_operand" "rHI"))
5185 (const_int 0)))
5186 (set (match_operand:DI 0 "register_operand" "=r")
5187 (minus:DI (match_dup 1) (match_dup 2)))]
5188 "TARGET_ARCH64"
5189 "subcc\t%1, %2, %0"
5190 [(set_attr "type" "compare")])
5191 \f
5192 ;; Integer Multiply/Divide.
5193
5194 ;; The 32 bit multiply/divide instructions are deprecated on v9, but at
5195 ;; least in UltraSPARC I, II and IIi it is a win tick-wise.
5196
5197 (define_insn "mulsi3"
5198 [(set (match_operand:SI 0 "register_operand" "=r")
5199 (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5200 (match_operand:SI 2 "arith_operand" "rI")))]
5201 "TARGET_HARD_MUL"
5202 "smul\t%1, %2, %0"
5203 [(set_attr "type" "imul")])
5204
5205 (define_expand "muldi3"
5206 [(set (match_operand:DI 0 "register_operand" "=r")
5207 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5208 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5209 "TARGET_ARCH64 || TARGET_V8PLUS"
5210 {
5211 if (TARGET_V8PLUS)
5212 {
5213 emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2]));
5214 DONE;
5215 }
5216 })
5217
5218 (define_insn "*muldi3_sp64"
5219 [(set (match_operand:DI 0 "register_operand" "=r")
5220 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5221 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5222 "TARGET_ARCH64"
5223 "mulx\t%1, %2, %0"
5224 [(set_attr "type" "imul")])
5225
5226 ;; V8plus wide multiply.
5227 ;; XXX
5228 (define_insn "muldi3_v8plus"
5229 [(set (match_operand:DI 0 "register_operand" "=r,h")
5230 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
5231 (match_operand:DI 2 "arith_double_operand" "rI,rI")))
5232 (clobber (match_scratch:SI 3 "=&h,X"))
5233 (clobber (match_scratch:SI 4 "=&h,X"))]
5234 "TARGET_V8PLUS"
5235 {
5236 if (sparc_check_64 (operands[1], insn) <= 0)
5237 output_asm_insn ("srl\t%L1, 0, %L1", operands);
5238 if (which_alternative == 1)
5239 output_asm_insn ("sllx\t%H1, 32, %H1", operands);
5240 if (GET_CODE (operands[2]) == CONST_INT)
5241 {
5242 if (which_alternative == 1)
5243 return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %2, %L0\;srlx\t%L0, 32, %H0";
5244 else
5245 return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
5246 }
5247 else if (rtx_equal_p (operands[1], operands[2]))
5248 {
5249 if (which_alternative == 1)
5250 return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %H1, %L0\;srlx\t%L0, 32, %H0";
5251 else
5252 return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %3, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
5253 }
5254 if (sparc_check_64 (operands[2], insn) <= 0)
5255 output_asm_insn ("srl\t%L2, 0, %L2", operands);
5256 if (which_alternative == 1)
5257 return "or\t%L1, %H1, %H1\n\tsllx\t%H2, 32, %L1\n\tor\t%L2, %L1, %L1\n\tmulx\t%H1, %L1, %L0\;srlx\t%L0, 32, %H0";
5258 else
5259 return "sllx\t%H1, 32, %3\n\tsllx\t%H2, 32, %4\n\tor\t%L1, %3, %3\n\tor\t%L2, %4, %4\n\tmulx\t%3, %4, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
5260 }
5261 [(set_attr "type" "multi")
5262 (set_attr "length" "9,8")])
5263
5264 (define_insn "*cmp_mul_set"
5265 [(set (reg:CC 100)
5266 (compare:CC (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5267 (match_operand:SI 2 "arith_operand" "rI"))
5268 (const_int 0)))
5269 (set (match_operand:SI 0 "register_operand" "=r")
5270 (mult:SI (match_dup 1) (match_dup 2)))]
5271 "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
5272 "smulcc\t%1, %2, %0"
5273 [(set_attr "type" "imul")])
5274
5275 (define_expand "mulsidi3"
5276 [(set (match_operand:DI 0 "register_operand" "")
5277 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
5278 (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
5279 "TARGET_HARD_MUL"
5280 {
5281 if (CONSTANT_P (operands[2]))
5282 {
5283 if (TARGET_V8PLUS)
5284 emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
5285 operands[2]));
5286 else
5287 emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
5288 operands[2]));
5289 DONE;
5290 }
5291 if (TARGET_V8PLUS)
5292 {
5293 emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2]));
5294 DONE;
5295 }
5296 })
5297
5298 ;; V9 puts the 64 bit product in a 64 bit register. Only out or global
5299 ;; registers can hold 64 bit values in the V8plus environment.
5300 ;; XXX
5301 (define_insn "mulsidi3_v8plus"
5302 [(set (match_operand:DI 0 "register_operand" "=h,r")
5303 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5304 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
5305 (clobber (match_scratch:SI 3 "=X,&h"))]
5306 "TARGET_V8PLUS"
5307 "@
5308 smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5309 smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5310 [(set_attr "type" "multi")
5311 (set_attr "length" "2,3")])
5312
5313 ;; XXX
5314 (define_insn "const_mulsidi3_v8plus"
5315 [(set (match_operand:DI 0 "register_operand" "=h,r")
5316 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5317 (match_operand:SI 2 "small_int" "I,I")))
5318 (clobber (match_scratch:SI 3 "=X,&h"))]
5319 "TARGET_V8PLUS"
5320 "@
5321 smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5322 smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5323 [(set_attr "type" "multi")
5324 (set_attr "length" "2,3")])
5325
5326 ;; XXX
5327 (define_insn "*mulsidi3_sp32"
5328 [(set (match_operand:DI 0 "register_operand" "=r")
5329 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5330 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5331 "TARGET_HARD_MUL32"
5332 {
5333 return TARGET_SPARCLET
5334 ? "smuld\t%1, %2, %L0"
5335 : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
5336 }
5337 [(set (attr "type")
5338 (if_then_else (eq_attr "isa" "sparclet")
5339 (const_string "imul") (const_string "multi")))
5340 (set (attr "length")
5341 (if_then_else (eq_attr "isa" "sparclet")
5342 (const_int 1) (const_int 2)))])
5343
5344 (define_insn "*mulsidi3_sp64"
5345 [(set (match_operand:DI 0 "register_operand" "=r")
5346 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5347 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5348 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5349 "smul\t%1, %2, %0"
5350 [(set_attr "type" "imul")])
5351
5352 ;; Extra pattern, because sign_extend of a constant isn't valid.
5353
5354 ;; XXX
5355 (define_insn "const_mulsidi3_sp32"
5356 [(set (match_operand:DI 0 "register_operand" "=r")
5357 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5358 (match_operand:SI 2 "small_int" "I")))]
5359 "TARGET_HARD_MUL32"
5360 {
5361 return TARGET_SPARCLET
5362 ? "smuld\t%1, %2, %L0"
5363 : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
5364 }
5365 [(set (attr "type")
5366 (if_then_else (eq_attr "isa" "sparclet")
5367 (const_string "imul") (const_string "multi")))
5368 (set (attr "length")
5369 (if_then_else (eq_attr "isa" "sparclet")
5370 (const_int 1) (const_int 2)))])
5371
5372 (define_insn "const_mulsidi3_sp64"
5373 [(set (match_operand:DI 0 "register_operand" "=r")
5374 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5375 (match_operand:SI 2 "small_int" "I")))]
5376 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5377 "smul\t%1, %2, %0"
5378 [(set_attr "type" "imul")])
5379
5380 (define_expand "smulsi3_highpart"
5381 [(set (match_operand:SI 0 "register_operand" "")
5382 (truncate:SI
5383 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
5384 (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
5385 (const_int 32))))]
5386 "TARGET_HARD_MUL && TARGET_ARCH32"
5387 {
5388 if (CONSTANT_P (operands[2]))
5389 {
5390 if (TARGET_V8PLUS)
5391 {
5392 emit_insn (gen_const_smulsi3_highpart_v8plus (operands[0],
5393 operands[1],
5394 operands[2],
5395 GEN_INT (32)));
5396 DONE;
5397 }
5398 emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
5399 DONE;
5400 }
5401 if (TARGET_V8PLUS)
5402 {
5403 emit_insn (gen_smulsi3_highpart_v8plus (operands[0], operands[1],
5404 operands[2], GEN_INT (32)));
5405 DONE;
5406 }
5407 })
5408
5409 ;; XXX
5410 (define_insn "smulsi3_highpart_v8plus"
5411 [(set (match_operand:SI 0 "register_operand" "=h,r")
5412 (truncate:SI
5413 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5414 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5415 (match_operand:SI 3 "const_int_operand" "i,i"))))
5416 (clobber (match_scratch:SI 4 "=X,&h"))]
5417 "TARGET_V8PLUS"
5418 "@
5419 smul\t%1, %2, %0\;srlx\t%0, %3, %0
5420 smul\t%1, %2, %4\;srlx\t%4, %3, %0"
5421 [(set_attr "type" "multi")
5422 (set_attr "length" "2")])
5423
5424 ;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
5425 ;; XXX
5426 (define_insn ""
5427 [(set (match_operand:SI 0 "register_operand" "=h,r")
5428 (subreg:SI
5429 (lshiftrt:DI
5430 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5431 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5432 (match_operand:SI 3 "const_int_operand" "i,i"))
5433 4))
5434 (clobber (match_scratch:SI 4 "=X,&h"))]
5435 "TARGET_V8PLUS"
5436 "@
5437 smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5438 smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5439 [(set_attr "type" "multi")
5440 (set_attr "length" "2")])
5441
5442 ;; XXX
5443 (define_insn "const_smulsi3_highpart_v8plus"
5444 [(set (match_operand:SI 0 "register_operand" "=h,r")
5445 (truncate:SI
5446 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5447 (match_operand 2 "small_int" "i,i"))
5448 (match_operand:SI 3 "const_int_operand" "i,i"))))
5449 (clobber (match_scratch:SI 4 "=X,&h"))]
5450 "TARGET_V8PLUS"
5451 "@
5452 smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5453 smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5454 [(set_attr "type" "multi")
5455 (set_attr "length" "2")])
5456
5457 ;; XXX
5458 (define_insn "*smulsi3_highpart_sp32"
5459 [(set (match_operand:SI 0 "register_operand" "=r")
5460 (truncate:SI
5461 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5462 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
5463 (const_int 32))))]
5464 "TARGET_HARD_MUL32"
5465 "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
5466 [(set_attr "type" "multi")
5467 (set_attr "length" "2")])
5468
5469 ;; XXX
5470 (define_insn "const_smulsi3_highpart"
5471 [(set (match_operand:SI 0 "register_operand" "=r")
5472 (truncate:SI
5473 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5474 (match_operand:SI 2 "register_operand" "r"))
5475 (const_int 32))))]
5476 "TARGET_HARD_MUL32"
5477 "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
5478 [(set_attr "type" "multi")
5479 (set_attr "length" "2")])
5480
5481 (define_expand "umulsidi3"
5482 [(set (match_operand:DI 0 "register_operand" "")
5483 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5484 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
5485 "TARGET_HARD_MUL"
5486 {
5487 if (CONSTANT_P (operands[2]))
5488 {
5489 if (TARGET_V8PLUS)
5490 emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
5491 operands[2]));
5492 else
5493 emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
5494 operands[2]));
5495 DONE;
5496 }
5497 if (TARGET_V8PLUS)
5498 {
5499 emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2]));
5500 DONE;
5501 }
5502 })
5503
5504 ;; XXX
5505 (define_insn "umulsidi3_v8plus"
5506 [(set (match_operand:DI 0 "register_operand" "=h,r")
5507 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5508 (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
5509 (clobber (match_scratch:SI 3 "=X,&h"))]
5510 "TARGET_V8PLUS"
5511 "@
5512 umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5513 umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5514 [(set_attr "type" "multi")
5515 (set_attr "length" "2,3")])
5516
5517 ;; XXX
5518 (define_insn "*umulsidi3_sp32"
5519 [(set (match_operand:DI 0 "register_operand" "=r")
5520 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5521 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5522 "TARGET_HARD_MUL32"
5523 {
5524 return TARGET_SPARCLET
5525 ? "umuld\t%1, %2, %L0"
5526 : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
5527 }
5528 [(set (attr "type")
5529 (if_then_else (eq_attr "isa" "sparclet")
5530 (const_string "imul") (const_string "multi")))
5531 (set (attr "length")
5532 (if_then_else (eq_attr "isa" "sparclet")
5533 (const_int 1) (const_int 2)))])
5534
5535 (define_insn "*umulsidi3_sp64"
5536 [(set (match_operand:DI 0 "register_operand" "=r")
5537 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5538 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5539 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5540 "umul\t%1, %2, %0"
5541 [(set_attr "type" "imul")])
5542
5543 ;; Extra pattern, because sign_extend of a constant isn't valid.
5544
5545 ;; XXX
5546 (define_insn "const_umulsidi3_sp32"
5547 [(set (match_operand:DI 0 "register_operand" "=r")
5548 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5549 (match_operand:SI 2 "uns_small_int" "")))]
5550 "TARGET_HARD_MUL32"
5551 {
5552 return TARGET_SPARCLET
5553 ? "umuld\t%1, %2, %L0"
5554 : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
5555 }
5556 [(set (attr "type")
5557 (if_then_else (eq_attr "isa" "sparclet")
5558 (const_string "imul") (const_string "multi")))
5559 (set (attr "length")
5560 (if_then_else (eq_attr "isa" "sparclet")
5561 (const_int 1) (const_int 2)))])
5562
5563 (define_insn "const_umulsidi3_sp64"
5564 [(set (match_operand:DI 0 "register_operand" "=r")
5565 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5566 (match_operand:SI 2 "uns_small_int" "")))]
5567 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5568 "umul\t%1, %2, %0"
5569 [(set_attr "type" "imul")])
5570
5571 ;; XXX
5572 (define_insn "const_umulsidi3_v8plus"
5573 [(set (match_operand:DI 0 "register_operand" "=h,r")
5574 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5575 (match_operand:SI 2 "uns_small_int" "")))
5576 (clobber (match_scratch:SI 3 "=X,h"))]
5577 "TARGET_V8PLUS"
5578 "@
5579 umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5580 umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5581 [(set_attr "type" "multi")
5582 (set_attr "length" "2,3")])
5583
5584 (define_expand "umulsi3_highpart"
5585 [(set (match_operand:SI 0 "register_operand" "")
5586 (truncate:SI
5587 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5588 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
5589 (const_int 32))))]
5590 "TARGET_HARD_MUL && TARGET_ARCH32"
5591 {
5592 if (CONSTANT_P (operands[2]))
5593 {
5594 if (TARGET_V8PLUS)
5595 {
5596 emit_insn (gen_const_umulsi3_highpart_v8plus (operands[0],
5597 operands[1],
5598 operands[2],
5599 GEN_INT (32)));
5600 DONE;
5601 }
5602 emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
5603 DONE;
5604 }
5605 if (TARGET_V8PLUS)
5606 {
5607 emit_insn (gen_umulsi3_highpart_v8plus (operands[0], operands[1],
5608 operands[2], GEN_INT (32)));
5609 DONE;
5610 }
5611 })
5612
5613 ;; XXX
5614 (define_insn "umulsi3_highpart_v8plus"
5615 [(set (match_operand:SI 0 "register_operand" "=h,r")
5616 (truncate:SI
5617 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5618 (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5619 (match_operand:SI 3 "const_int_operand" "i,i"))))
5620 (clobber (match_scratch:SI 4 "=X,h"))]
5621 "TARGET_V8PLUS"
5622 "@
5623 umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5624 umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5625 [(set_attr "type" "multi")
5626 (set_attr "length" "2")])
5627
5628 ;; XXX
5629 (define_insn "const_umulsi3_highpart_v8plus"
5630 [(set (match_operand:SI 0 "register_operand" "=h,r")
5631 (truncate:SI
5632 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5633 (match_operand:SI 2 "uns_small_int" ""))
5634 (match_operand:SI 3 "const_int_operand" "i,i"))))
5635 (clobber (match_scratch:SI 4 "=X,h"))]
5636 "TARGET_V8PLUS"
5637 "@
5638 umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5639 umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5640 [(set_attr "type" "multi")
5641 (set_attr "length" "2")])
5642
5643 ;; XXX
5644 (define_insn "*umulsi3_highpart_sp32"
5645 [(set (match_operand:SI 0 "register_operand" "=r")
5646 (truncate:SI
5647 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5648 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
5649 (const_int 32))))]
5650 "TARGET_HARD_MUL32"
5651 "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
5652 [(set_attr "type" "multi")
5653 (set_attr "length" "2")])
5654
5655 ;; XXX
5656 (define_insn "const_umulsi3_highpart"
5657 [(set (match_operand:SI 0 "register_operand" "=r")
5658 (truncate:SI
5659 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5660 (match_operand:SI 2 "uns_small_int" ""))
5661 (const_int 32))))]
5662 "TARGET_HARD_MUL32"
5663 "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
5664 [(set_attr "type" "multi")
5665 (set_attr "length" "2")])
5666
5667 ;; The v8 architecture specifies that there must be 3 instructions between
5668 ;; a y register write and a use of it for correct results.
5669
5670 (define_expand "divsi3"
5671 [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
5672 (div:SI (match_operand:SI 1 "register_operand" "r,r")
5673 (match_operand:SI 2 "input_operand" "rI,m")))
5674 (clobber (match_scratch:SI 3 "=&r,&r"))])]
5675 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5676 {
5677 if (TARGET_ARCH64)
5678 {
5679 operands[3] = gen_reg_rtx(SImode);
5680 emit_insn (gen_ashrsi3 (operands[3], operands[1], GEN_INT (31)));
5681 emit_insn (gen_divsi3_sp64 (operands[0], operands[1], operands[2],
5682 operands[3]));
5683 DONE;
5684 }
5685 })
5686
5687 (define_insn "divsi3_sp32"
5688 [(set (match_operand:SI 0 "register_operand" "=r,r")
5689 (div:SI (match_operand:SI 1 "register_operand" "r,r")
5690 (match_operand:SI 2 "input_operand" "rI,m")))
5691 (clobber (match_scratch:SI 3 "=&r,&r"))]
5692 "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
5693 && TARGET_ARCH32"
5694 {
5695 if (which_alternative == 0)
5696 if (TARGET_V9)
5697 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdiv\t%1, %2, %0";
5698 else
5699 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0";
5700 else
5701 if (TARGET_V9)
5702 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0";
5703 else
5704 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0";
5705 }
5706 [(set_attr "type" "multi")
5707 (set (attr "length")
5708 (if_then_else (eq_attr "isa" "v9")
5709 (const_int 4) (const_int 6)))])
5710
5711 (define_insn "divsi3_sp64"
5712 [(set (match_operand:SI 0 "register_operand" "=r")
5713 (div:SI (match_operand:SI 1 "register_operand" "r")
5714 (match_operand:SI 2 "input_operand" "rI")))
5715 (use (match_operand:SI 3 "register_operand" "r"))]
5716 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5717 "wr\t%%g0, %3, %%y\n\tsdiv\t%1, %2, %0"
5718 [(set_attr "type" "multi")
5719 (set_attr "length" "2")])
5720
5721 (define_insn "divdi3"
5722 [(set (match_operand:DI 0 "register_operand" "=r")
5723 (div:DI (match_operand:DI 1 "register_operand" "r")
5724 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5725 "TARGET_ARCH64"
5726 "sdivx\t%1, %2, %0"
5727 [(set_attr "type" "idiv")])
5728
5729 (define_insn "*cmp_sdiv_cc_set"
5730 [(set (reg:CC 100)
5731 (compare:CC (div:SI (match_operand:SI 1 "register_operand" "r")
5732 (match_operand:SI 2 "arith_operand" "rI"))
5733 (const_int 0)))
5734 (set (match_operand:SI 0 "register_operand" "=r")
5735 (div:SI (match_dup 1) (match_dup 2)))
5736 (clobber (match_scratch:SI 3 "=&r"))]
5737 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5738 {
5739 if (TARGET_V9)
5740 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdivcc\t%1, %2, %0";
5741 else
5742 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0";
5743 }
5744 [(set_attr "type" "multi")
5745 (set (attr "length")
5746 (if_then_else (eq_attr "isa" "v9")
5747 (const_int 3) (const_int 6)))])
5748
5749 ;; XXX
5750 (define_expand "udivsi3"
5751 [(set (match_operand:SI 0 "register_operand" "")
5752 (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "")
5753 (match_operand:SI 2 "input_operand" "")))]
5754 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5755 "")
5756
5757 (define_insn "udivsi3_sp32"
5758 [(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
5759 (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
5760 (match_operand:SI 2 "input_operand" "rI,m,r")))]
5761 "(TARGET_V8
5762 || TARGET_DEPRECATED_V8_INSNS)
5763 && TARGET_ARCH32"
5764 {
5765 output_asm_insn ("wr\t%%g0, %%g0, %%y", operands);
5766 switch (which_alternative)
5767 {
5768 default:
5769 return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0";
5770 case 1:
5771 return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0";
5772 case 2:
5773 return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0";
5774 }
5775 }
5776 [(set_attr "type" "multi")
5777 (set_attr "length" "5")])
5778
5779 (define_insn "udivsi3_sp64"
5780 [(set (match_operand:SI 0 "register_operand" "=r")
5781 (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
5782 (match_operand:SI 2 "input_operand" "rI")))]
5783 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5784 "wr\t%%g0, 0, %%y\n\tudiv\t%1, %2, %0"
5785 [(set_attr "type" "multi")
5786 (set_attr "length" "2")])
5787
5788 (define_insn "udivdi3"
5789 [(set (match_operand:DI 0 "register_operand" "=r")
5790 (udiv:DI (match_operand:DI 1 "register_operand" "r")
5791 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5792 "TARGET_ARCH64"
5793 "udivx\t%1, %2, %0"
5794 [(set_attr "type" "idiv")])
5795
5796 (define_insn "*cmp_udiv_cc_set"
5797 [(set (reg:CC 100)
5798 (compare:CC (udiv:SI (match_operand:SI 1 "register_operand" "r")
5799 (match_operand:SI 2 "arith_operand" "rI"))
5800 (const_int 0)))
5801 (set (match_operand:SI 0 "register_operand" "=r")
5802 (udiv:SI (match_dup 1) (match_dup 2)))]
5803 "TARGET_V8
5804 || TARGET_DEPRECATED_V8_INSNS"
5805 {
5806 if (TARGET_V9)
5807 return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0";
5808 else
5809 return "wr\t%%g0, %%g0, %%y\n\tnop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0";
5810 }
5811 [(set_attr "type" "multi")
5812 (set (attr "length")
5813 (if_then_else (eq_attr "isa" "v9")
5814 (const_int 2) (const_int 5)))])
5815
5816 ; sparclet multiply/accumulate insns
5817
5818 (define_insn "*smacsi"
5819 [(set (match_operand:SI 0 "register_operand" "=r")
5820 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
5821 (match_operand:SI 2 "arith_operand" "rI"))
5822 (match_operand:SI 3 "register_operand" "0")))]
5823 "TARGET_SPARCLET"
5824 "smac\t%1, %2, %0"
5825 [(set_attr "type" "imul")])
5826
5827 (define_insn "*smacdi"
5828 [(set (match_operand:DI 0 "register_operand" "=r")
5829 (plus:DI (mult:DI (sign_extend:DI
5830 (match_operand:SI 1 "register_operand" "%r"))
5831 (sign_extend:DI
5832 (match_operand:SI 2 "register_operand" "r")))
5833 (match_operand:DI 3 "register_operand" "0")))]
5834 "TARGET_SPARCLET"
5835 "smacd\t%1, %2, %L0"
5836 [(set_attr "type" "imul")])
5837
5838 (define_insn "*umacdi"
5839 [(set (match_operand:DI 0 "register_operand" "=r")
5840 (plus:DI (mult:DI (zero_extend:DI
5841 (match_operand:SI 1 "register_operand" "%r"))
5842 (zero_extend:DI
5843 (match_operand:SI 2 "register_operand" "r")))
5844 (match_operand:DI 3 "register_operand" "0")))]
5845 "TARGET_SPARCLET"
5846 "umacd\t%1, %2, %L0"
5847 [(set_attr "type" "imul")])
5848 \f
5849 ;;- Boolean instructions
5850 ;; We define DImode `and' so with DImode `not' we can get
5851 ;; DImode `andn'. Other combinations are possible.
5852
5853 (define_expand "anddi3"
5854 [(set (match_operand:DI 0 "register_operand" "")
5855 (and:DI (match_operand:DI 1 "arith_double_operand" "")
5856 (match_operand:DI 2 "arith_double_operand" "")))]
5857 ""
5858 "")
5859
5860 (define_insn "*anddi3_sp32"
5861 [(set (match_operand:DI 0 "register_operand" "=r,b")
5862 (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5863 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5864 "! TARGET_ARCH64"
5865 "@
5866 #
5867 fand\t%1, %2, %0"
5868 [(set_attr "type" "*,fp")
5869 (set_attr "length" "2,*")
5870 (set_attr "fptype" "double")])
5871
5872 (define_insn "*anddi3_sp64"
5873 [(set (match_operand:DI 0 "register_operand" "=r,b")
5874 (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5875 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5876 "TARGET_ARCH64"
5877 "@
5878 and\t%1, %2, %0
5879 fand\t%1, %2, %0"
5880 [(set_attr "type" "*,fp")
5881 (set_attr "fptype" "double")])
5882
5883 (define_insn "andsi3"
5884 [(set (match_operand:SI 0 "register_operand" "=r,d")
5885 (and:SI (match_operand:SI 1 "arith_operand" "%r,d")
5886 (match_operand:SI 2 "arith_operand" "rI,d")))]
5887 ""
5888 "@
5889 and\t%1, %2, %0
5890 fands\t%1, %2, %0"
5891 [(set_attr "type" "*,fp")])
5892
5893 (define_split
5894 [(set (match_operand:SI 0 "register_operand" "")
5895 (and:SI (match_operand:SI 1 "register_operand" "")
5896 (match_operand:SI 2 "" "")))
5897 (clobber (match_operand:SI 3 "register_operand" ""))]
5898 "GET_CODE (operands[2]) == CONST_INT
5899 && !SMALL_INT32 (operands[2])
5900 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
5901 [(set (match_dup 3) (match_dup 4))
5902 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
5903 {
5904 operands[4] = GEN_INT (~INTVAL (operands[2]));
5905 })
5906
5907 ;; Split DImode logical operations requiring two instructions.
5908 (define_split
5909 [(set (match_operand:DI 0 "register_operand" "")
5910 (match_operator:DI 1 "cc_arithop" ; AND, IOR, XOR
5911 [(match_operand:DI 2 "register_operand" "")
5912 (match_operand:DI 3 "arith_double_operand" "")]))]
5913 "! TARGET_ARCH64
5914 && reload_completed
5915 && ((GET_CODE (operands[0]) == REG
5916 && REGNO (operands[0]) < 32)
5917 || (GET_CODE (operands[0]) == SUBREG
5918 && GET_CODE (SUBREG_REG (operands[0])) == REG
5919 && REGNO (SUBREG_REG (operands[0])) < 32))"
5920 [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
5921 (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
5922 {
5923 operands[4] = gen_highpart (SImode, operands[0]);
5924 operands[5] = gen_lowpart (SImode, operands[0]);
5925 operands[6] = gen_highpart (SImode, operands[2]);
5926 operands[7] = gen_lowpart (SImode, operands[2]);
5927 #if HOST_BITS_PER_WIDE_INT == 32
5928 if (GET_CODE (operands[3]) == CONST_INT)
5929 {
5930 if (INTVAL (operands[3]) < 0)
5931 operands[8] = constm1_rtx;
5932 else
5933 operands[8] = const0_rtx;
5934 }
5935 else
5936 #endif
5937 operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
5938 operands[9] = gen_lowpart (SImode, operands[3]);
5939 })
5940
5941 (define_insn_and_split "*and_not_di_sp32"
5942 [(set (match_operand:DI 0 "register_operand" "=r,b")
5943 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
5944 (match_operand:DI 2 "register_operand" "r,b")))]
5945 "! TARGET_ARCH64"
5946 "@
5947 #
5948 fandnot1\t%1, %2, %0"
5949 "&& reload_completed
5950 && ((GET_CODE (operands[0]) == REG
5951 && REGNO (operands[0]) < 32)
5952 || (GET_CODE (operands[0]) == SUBREG
5953 && GET_CODE (SUBREG_REG (operands[0])) == REG
5954 && REGNO (SUBREG_REG (operands[0])) < 32))"
5955 [(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
5956 (set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
5957 "operands[3] = gen_highpart (SImode, operands[0]);
5958 operands[4] = gen_highpart (SImode, operands[1]);
5959 operands[5] = gen_highpart (SImode, operands[2]);
5960 operands[6] = gen_lowpart (SImode, operands[0]);
5961 operands[7] = gen_lowpart (SImode, operands[1]);
5962 operands[8] = gen_lowpart (SImode, operands[2]);"
5963 [(set_attr "type" "*,fp")
5964 (set_attr "length" "2,*")
5965 (set_attr "fptype" "double")])
5966
5967 (define_insn "*and_not_di_sp64"
5968 [(set (match_operand:DI 0 "register_operand" "=r,b")
5969 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
5970 (match_operand:DI 2 "register_operand" "r,b")))]
5971 "TARGET_ARCH64"
5972 "@
5973 andn\t%2, %1, %0
5974 fandnot1\t%1, %2, %0"
5975 [(set_attr "type" "*,fp")
5976 (set_attr "fptype" "double")])
5977
5978 (define_insn "*and_not_si"
5979 [(set (match_operand:SI 0 "register_operand" "=r,d")
5980 (and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
5981 (match_operand:SI 2 "register_operand" "r,d")))]
5982 ""
5983 "@
5984 andn\t%2, %1, %0
5985 fandnot1s\t%1, %2, %0"
5986 [(set_attr "type" "*,fp")])
5987
5988 (define_expand "iordi3"
5989 [(set (match_operand:DI 0 "register_operand" "")
5990 (ior:DI (match_operand:DI 1 "arith_double_operand" "")
5991 (match_operand:DI 2 "arith_double_operand" "")))]
5992 ""
5993 "")
5994
5995 (define_insn "*iordi3_sp32"
5996 [(set (match_operand:DI 0 "register_operand" "=r,b")
5997 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5998 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5999 "! TARGET_ARCH64"
6000 "@
6001 #
6002 for\t%1, %2, %0"
6003 [(set_attr "type" "*,fp")
6004 (set_attr "length" "2,*")
6005 (set_attr "fptype" "double")])
6006
6007 (define_insn "*iordi3_sp64"
6008 [(set (match_operand:DI 0 "register_operand" "=r,b")
6009 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6010 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6011 "TARGET_ARCH64"
6012 "@
6013 or\t%1, %2, %0
6014 for\t%1, %2, %0"
6015 [(set_attr "type" "*,fp")
6016 (set_attr "fptype" "double")])
6017
6018 (define_insn "iorsi3"
6019 [(set (match_operand:SI 0 "register_operand" "=r,d")
6020 (ior:SI (match_operand:SI 1 "arith_operand" "%r,d")
6021 (match_operand:SI 2 "arith_operand" "rI,d")))]
6022 ""
6023 "@
6024 or\t%1, %2, %0
6025 fors\t%1, %2, %0"
6026 [(set_attr "type" "*,fp")])
6027
6028 (define_split
6029 [(set (match_operand:SI 0 "register_operand" "")
6030 (ior:SI (match_operand:SI 1 "register_operand" "")
6031 (match_operand:SI 2 "" "")))
6032 (clobber (match_operand:SI 3 "register_operand" ""))]
6033 "GET_CODE (operands[2]) == CONST_INT
6034 && !SMALL_INT32 (operands[2])
6035 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6036 [(set (match_dup 3) (match_dup 4))
6037 (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
6038 {
6039 operands[4] = GEN_INT (~INTVAL (operands[2]));
6040 })
6041
6042 (define_insn_and_split "*or_not_di_sp32"
6043 [(set (match_operand:DI 0 "register_operand" "=r,b")
6044 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6045 (match_operand:DI 2 "register_operand" "r,b")))]
6046 "! TARGET_ARCH64"
6047 "@
6048 #
6049 fornot1\t%1, %2, %0"
6050 "&& reload_completed
6051 && ((GET_CODE (operands[0]) == REG
6052 && REGNO (operands[0]) < 32)
6053 || (GET_CODE (operands[0]) == SUBREG
6054 && GET_CODE (SUBREG_REG (operands[0])) == REG
6055 && REGNO (SUBREG_REG (operands[0])) < 32))"
6056 [(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
6057 (set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
6058 "operands[3] = gen_highpart (SImode, operands[0]);
6059 operands[4] = gen_highpart (SImode, operands[1]);
6060 operands[5] = gen_highpart (SImode, operands[2]);
6061 operands[6] = gen_lowpart (SImode, operands[0]);
6062 operands[7] = gen_lowpart (SImode, operands[1]);
6063 operands[8] = gen_lowpart (SImode, operands[2]);"
6064 [(set_attr "type" "*,fp")
6065 (set_attr "length" "2,*")
6066 (set_attr "fptype" "double")])
6067
6068 (define_insn "*or_not_di_sp64"
6069 [(set (match_operand:DI 0 "register_operand" "=r,b")
6070 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6071 (match_operand:DI 2 "register_operand" "r,b")))]
6072 "TARGET_ARCH64"
6073 "@
6074 orn\t%2, %1, %0
6075 fornot1\t%1, %2, %0"
6076 [(set_attr "type" "*,fp")
6077 (set_attr "fptype" "double")])
6078
6079 (define_insn "*or_not_si"
6080 [(set (match_operand:SI 0 "register_operand" "=r,d")
6081 (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
6082 (match_operand:SI 2 "register_operand" "r,d")))]
6083 ""
6084 "@
6085 orn\t%2, %1, %0
6086 fornot1s\t%1, %2, %0"
6087 [(set_attr "type" "*,fp")])
6088
6089 (define_expand "xordi3"
6090 [(set (match_operand:DI 0 "register_operand" "")
6091 (xor:DI (match_operand:DI 1 "arith_double_operand" "")
6092 (match_operand:DI 2 "arith_double_operand" "")))]
6093 ""
6094 "")
6095
6096 (define_insn "*xordi3_sp32"
6097 [(set (match_operand:DI 0 "register_operand" "=r,b")
6098 (xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6099 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6100 "! TARGET_ARCH64"
6101 "@
6102 #
6103 fxor\t%1, %2, %0"
6104 [(set_attr "type" "*,fp")
6105 (set_attr "length" "2,*")
6106 (set_attr "fptype" "double")])
6107
6108 (define_insn "*xordi3_sp64"
6109 [(set (match_operand:DI 0 "register_operand" "=r,b")
6110 (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
6111 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6112 "TARGET_ARCH64"
6113 "@
6114 xor\t%r1, %2, %0
6115 fxor\t%1, %2, %0"
6116 [(set_attr "type" "*,fp")
6117 (set_attr "fptype" "double")])
6118
6119 (define_insn "*xordi3_sp64_dbl"
6120 [(set (match_operand:DI 0 "register_operand" "=r")
6121 (xor:DI (match_operand:DI 1 "register_operand" "r")
6122 (match_operand:DI 2 "const64_operand" "")))]
6123 "(TARGET_ARCH64
6124 && HOST_BITS_PER_WIDE_INT != 64)"
6125 "xor\t%1, %2, %0")
6126
6127 (define_insn "xorsi3"
6128 [(set (match_operand:SI 0 "register_operand" "=r,d")
6129 (xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d")
6130 (match_operand:SI 2 "arith_operand" "rI,d")))]
6131 ""
6132 "@
6133 xor\t%r1, %2, %0
6134 fxors\t%1, %2, %0"
6135 [(set_attr "type" "*,fp")])
6136
6137 (define_split
6138 [(set (match_operand:SI 0 "register_operand" "")
6139 (xor:SI (match_operand:SI 1 "register_operand" "")
6140 (match_operand:SI 2 "" "")))
6141 (clobber (match_operand:SI 3 "register_operand" ""))]
6142 "GET_CODE (operands[2]) == CONST_INT
6143 && !SMALL_INT32 (operands[2])
6144 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6145 [(set (match_dup 3) (match_dup 4))
6146 (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
6147 {
6148 operands[4] = GEN_INT (~INTVAL (operands[2]));
6149 })
6150
6151 (define_split
6152 [(set (match_operand:SI 0 "register_operand" "")
6153 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
6154 (match_operand:SI 2 "" ""))))
6155 (clobber (match_operand:SI 3 "register_operand" ""))]
6156 "GET_CODE (operands[2]) == CONST_INT
6157 && !SMALL_INT32 (operands[2])
6158 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6159 [(set (match_dup 3) (match_dup 4))
6160 (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
6161 {
6162 operands[4] = GEN_INT (~INTVAL (operands[2]));
6163 })
6164
6165 ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
6166 ;; Combine now canonicalizes to the rightmost expression.
6167 (define_insn_and_split "*xor_not_di_sp32"
6168 [(set (match_operand:DI 0 "register_operand" "=r,b")
6169 (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
6170 (match_operand:DI 2 "register_operand" "r,b"))))]
6171 "! TARGET_ARCH64"
6172 "@
6173 #
6174 fxnor\t%1, %2, %0"
6175 "&& reload_completed
6176 && ((GET_CODE (operands[0]) == REG
6177 && REGNO (operands[0]) < 32)
6178 || (GET_CODE (operands[0]) == SUBREG
6179 && GET_CODE (SUBREG_REG (operands[0])) == REG
6180 && REGNO (SUBREG_REG (operands[0])) < 32))"
6181 [(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
6182 (set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
6183 "operands[3] = gen_highpart (SImode, operands[0]);
6184 operands[4] = gen_highpart (SImode, operands[1]);
6185 operands[5] = gen_highpart (SImode, operands[2]);
6186 operands[6] = gen_lowpart (SImode, operands[0]);
6187 operands[7] = gen_lowpart (SImode, operands[1]);
6188 operands[8] = gen_lowpart (SImode, operands[2]);"
6189 [(set_attr "type" "*,fp")
6190 (set_attr "length" "2,*")
6191 (set_attr "fptype" "double")])
6192
6193 (define_insn "*xor_not_di_sp64"
6194 [(set (match_operand:DI 0 "register_operand" "=r,b")
6195 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
6196 (match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
6197 "TARGET_ARCH64"
6198 "@
6199 xnor\t%r1, %2, %0
6200 fxnor\t%1, %2, %0"
6201 [(set_attr "type" "*,fp")
6202 (set_attr "fptype" "double")])
6203
6204 (define_insn "*xor_not_si"
6205 [(set (match_operand:SI 0 "register_operand" "=r,d")
6206 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d")
6207 (match_operand:SI 2 "arith_operand" "rI,d"))))]
6208 ""
6209 "@
6210 xnor\t%r1, %2, %0
6211 fxnors\t%1, %2, %0"
6212 [(set_attr "type" "*,fp")])
6213
6214 ;; These correspond to the above in the case where we also (or only)
6215 ;; want to set the condition code.
6216
6217 (define_insn "*cmp_cc_arith_op"
6218 [(set (reg:CC 100)
6219 (compare:CC
6220 (match_operator:SI 2 "cc_arithop"
6221 [(match_operand:SI 0 "arith_operand" "%r")
6222 (match_operand:SI 1 "arith_operand" "rI")])
6223 (const_int 0)))]
6224 ""
6225 "%A2cc\t%0, %1, %%g0"
6226 [(set_attr "type" "compare")])
6227
6228 (define_insn "*cmp_ccx_arith_op"
6229 [(set (reg:CCX 100)
6230 (compare:CCX
6231 (match_operator:DI 2 "cc_arithop"
6232 [(match_operand:DI 0 "arith_double_operand" "%r")
6233 (match_operand:DI 1 "arith_double_operand" "rHI")])
6234 (const_int 0)))]
6235 "TARGET_ARCH64"
6236 "%A2cc\t%0, %1, %%g0"
6237 [(set_attr "type" "compare")])
6238
6239 (define_insn "*cmp_cc_arith_op_set"
6240 [(set (reg:CC 100)
6241 (compare:CC
6242 (match_operator:SI 3 "cc_arithop"
6243 [(match_operand:SI 1 "arith_operand" "%r")
6244 (match_operand:SI 2 "arith_operand" "rI")])
6245 (const_int 0)))
6246 (set (match_operand:SI 0 "register_operand" "=r")
6247 (match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
6248 "GET_CODE (operands[3]) == GET_CODE (operands[4])"
6249 "%A3cc\t%1, %2, %0"
6250 [(set_attr "type" "compare")])
6251
6252 (define_insn "*cmp_ccx_arith_op_set"
6253 [(set (reg:CCX 100)
6254 (compare:CCX
6255 (match_operator:DI 3 "cc_arithop"
6256 [(match_operand:DI 1 "arith_double_operand" "%r")
6257 (match_operand:DI 2 "arith_double_operand" "rHI")])
6258 (const_int 0)))
6259 (set (match_operand:DI 0 "register_operand" "=r")
6260 (match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
6261 "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
6262 "%A3cc\t%1, %2, %0"
6263 [(set_attr "type" "compare")])
6264
6265 (define_insn "*cmp_cc_xor_not"
6266 [(set (reg:CC 100)
6267 (compare:CC
6268 (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
6269 (match_operand:SI 1 "arith_operand" "rI")))
6270 (const_int 0)))]
6271 ""
6272 "xnorcc\t%r0, %1, %%g0"
6273 [(set_attr "type" "compare")])
6274
6275 (define_insn "*cmp_ccx_xor_not"
6276 [(set (reg:CCX 100)
6277 (compare:CCX
6278 (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
6279 (match_operand:DI 1 "arith_double_operand" "rHI")))
6280 (const_int 0)))]
6281 "TARGET_ARCH64"
6282 "xnorcc\t%r0, %1, %%g0"
6283 [(set_attr "type" "compare")])
6284
6285 (define_insn "*cmp_cc_xor_not_set"
6286 [(set (reg:CC 100)
6287 (compare:CC
6288 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
6289 (match_operand:SI 2 "arith_operand" "rI")))
6290 (const_int 0)))
6291 (set (match_operand:SI 0 "register_operand" "=r")
6292 (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
6293 ""
6294 "xnorcc\t%r1, %2, %0"
6295 [(set_attr "type" "compare")])
6296
6297 (define_insn "*cmp_ccx_xor_not_set"
6298 [(set (reg:CCX 100)
6299 (compare:CCX
6300 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
6301 (match_operand:DI 2 "arith_double_operand" "rHI")))
6302 (const_int 0)))
6303 (set (match_operand:DI 0 "register_operand" "=r")
6304 (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
6305 "TARGET_ARCH64"
6306 "xnorcc\t%r1, %2, %0"
6307 [(set_attr "type" "compare")])
6308
6309 (define_insn "*cmp_cc_arith_op_not"
6310 [(set (reg:CC 100)
6311 (compare:CC
6312 (match_operator:SI 2 "cc_arithopn"
6313 [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
6314 (match_operand:SI 1 "reg_or_0_operand" "rJ")])
6315 (const_int 0)))]
6316 ""
6317 "%B2cc\t%r1, %0, %%g0"
6318 [(set_attr "type" "compare")])
6319
6320 (define_insn "*cmp_ccx_arith_op_not"
6321 [(set (reg:CCX 100)
6322 (compare:CCX
6323 (match_operator:DI 2 "cc_arithopn"
6324 [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6325 (match_operand:DI 1 "reg_or_0_operand" "rJ")])
6326 (const_int 0)))]
6327 "TARGET_ARCH64"
6328 "%B2cc\t%r1, %0, %%g0"
6329 [(set_attr "type" "compare")])
6330
6331 (define_insn "*cmp_cc_arith_op_not_set"
6332 [(set (reg:CC 100)
6333 (compare:CC
6334 (match_operator:SI 3 "cc_arithopn"
6335 [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
6336 (match_operand:SI 2 "reg_or_0_operand" "rJ")])
6337 (const_int 0)))
6338 (set (match_operand:SI 0 "register_operand" "=r")
6339 (match_operator:SI 4 "cc_arithopn"
6340 [(not:SI (match_dup 1)) (match_dup 2)]))]
6341 "GET_CODE (operands[3]) == GET_CODE (operands[4])"
6342 "%B3cc\t%r2, %1, %0"
6343 [(set_attr "type" "compare")])
6344
6345 (define_insn "*cmp_ccx_arith_op_not_set"
6346 [(set (reg:CCX 100)
6347 (compare:CCX
6348 (match_operator:DI 3 "cc_arithopn"
6349 [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6350 (match_operand:DI 2 "reg_or_0_operand" "rJ")])
6351 (const_int 0)))
6352 (set (match_operand:DI 0 "register_operand" "=r")
6353 (match_operator:DI 4 "cc_arithopn"
6354 [(not:DI (match_dup 1)) (match_dup 2)]))]
6355 "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
6356 "%B3cc\t%r2, %1, %0"
6357 [(set_attr "type" "compare")])
6358
6359 ;; We cannot use the "neg" pseudo insn because the Sun assembler
6360 ;; does not know how to make it work for constants.
6361
6362 (define_expand "negdi2"
6363 [(set (match_operand:DI 0 "register_operand" "=r")
6364 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
6365 ""
6366 {
6367 if (! TARGET_ARCH64)
6368 {
6369 emit_insn (gen_rtx_PARALLEL
6370 (VOIDmode,
6371 gen_rtvec (2,
6372 gen_rtx_SET (VOIDmode, operand0,
6373 gen_rtx_NEG (DImode, operand1)),
6374 gen_rtx_CLOBBER (VOIDmode,
6375 gen_rtx_REG (CCmode,
6376 SPARC_ICC_REG)))));
6377 DONE;
6378 }
6379 })
6380
6381 (define_insn_and_split "*negdi2_sp32"
6382 [(set (match_operand:DI 0 "register_operand" "=r")
6383 (neg:DI (match_operand:DI 1 "register_operand" "r")))
6384 (clobber (reg:CC 100))]
6385 "TARGET_ARCH32"
6386 "#"
6387 "&& reload_completed"
6388 [(parallel [(set (reg:CC_NOOV 100)
6389 (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
6390 (const_int 0)))
6391 (set (match_dup 4) (minus:SI (const_int 0) (match_dup 5)))])
6392 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
6393 (ltu:SI (reg:CC 100) (const_int 0))))]
6394 "operands[2] = gen_highpart (SImode, operands[0]);
6395 operands[3] = gen_highpart (SImode, operands[1]);
6396 operands[4] = gen_lowpart (SImode, operands[0]);
6397 operands[5] = gen_lowpart (SImode, operands[1]);"
6398 [(set_attr "length" "2")])
6399
6400 (define_insn "*negdi2_sp64"
6401 [(set (match_operand:DI 0 "register_operand" "=r")
6402 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
6403 "TARGET_ARCH64"
6404 "sub\t%%g0, %1, %0")
6405
6406 (define_insn "negsi2"
6407 [(set (match_operand:SI 0 "register_operand" "=r")
6408 (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
6409 ""
6410 "sub\t%%g0, %1, %0")
6411
6412 (define_insn "*cmp_cc_neg"
6413 [(set (reg:CC_NOOV 100)
6414 (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
6415 (const_int 0)))]
6416 ""
6417 "subcc\t%%g0, %0, %%g0"
6418 [(set_attr "type" "compare")])
6419
6420 (define_insn "*cmp_ccx_neg"
6421 [(set (reg:CCX_NOOV 100)
6422 (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6423 (const_int 0)))]
6424 "TARGET_ARCH64"
6425 "subcc\t%%g0, %0, %%g0"
6426 [(set_attr "type" "compare")])
6427
6428 (define_insn "*cmp_cc_set_neg"
6429 [(set (reg:CC_NOOV 100)
6430 (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
6431 (const_int 0)))
6432 (set (match_operand:SI 0 "register_operand" "=r")
6433 (neg:SI (match_dup 1)))]
6434 ""
6435 "subcc\t%%g0, %1, %0"
6436 [(set_attr "type" "compare")])
6437
6438 (define_insn "*cmp_ccx_set_neg"
6439 [(set (reg:CCX_NOOV 100)
6440 (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6441 (const_int 0)))
6442 (set (match_operand:DI 0 "register_operand" "=r")
6443 (neg:DI (match_dup 1)))]
6444 "TARGET_ARCH64"
6445 "subcc\t%%g0, %1, %0"
6446 [(set_attr "type" "compare")])
6447
6448 ;; We cannot use the "not" pseudo insn because the Sun assembler
6449 ;; does not know how to make it work for constants.
6450 (define_expand "one_cmpldi2"
6451 [(set (match_operand:DI 0 "register_operand" "")
6452 (not:DI (match_operand:DI 1 "register_operand" "")))]
6453 ""
6454 "")
6455
6456 (define_insn_and_split "*one_cmpldi2_sp32"
6457 [(set (match_operand:DI 0 "register_operand" "=r,b")
6458 (not:DI (match_operand:DI 1 "register_operand" "r,b")))]
6459 "! TARGET_ARCH64"
6460 "@
6461 #
6462 fnot1\t%1, %0"
6463 "&& reload_completed
6464 && ((GET_CODE (operands[0]) == REG
6465 && REGNO (operands[0]) < 32)
6466 || (GET_CODE (operands[0]) == SUBREG
6467 && GET_CODE (SUBREG_REG (operands[0])) == REG
6468 && REGNO (SUBREG_REG (operands[0])) < 32))"
6469 [(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
6470 (set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
6471 "operands[2] = gen_highpart (SImode, operands[0]);
6472 operands[3] = gen_highpart (SImode, operands[1]);
6473 operands[4] = gen_lowpart (SImode, operands[0]);
6474 operands[5] = gen_lowpart (SImode, operands[1]);"
6475 [(set_attr "type" "*,fp")
6476 (set_attr "length" "2,*")
6477 (set_attr "fptype" "double")])
6478
6479 (define_insn "*one_cmpldi2_sp64"
6480 [(set (match_operand:DI 0 "register_operand" "=r,b")
6481 (not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
6482 "TARGET_ARCH64"
6483 "@
6484 xnor\t%%g0, %1, %0
6485 fnot1\t%1, %0"
6486 [(set_attr "type" "*,fp")
6487 (set_attr "fptype" "double")])
6488
6489 (define_insn "one_cmplsi2"
6490 [(set (match_operand:SI 0 "register_operand" "=r,d")
6491 (not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
6492 ""
6493 "@
6494 xnor\t%%g0, %1, %0
6495 fnot1s\t%1, %0"
6496 [(set_attr "type" "*,fp")])
6497
6498 (define_insn "*cmp_cc_not"
6499 [(set (reg:CC 100)
6500 (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
6501 (const_int 0)))]
6502 ""
6503 "xnorcc\t%%g0, %0, %%g0"
6504 [(set_attr "type" "compare")])
6505
6506 (define_insn "*cmp_ccx_not"
6507 [(set (reg:CCX 100)
6508 (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6509 (const_int 0)))]
6510 "TARGET_ARCH64"
6511 "xnorcc\t%%g0, %0, %%g0"
6512 [(set_attr "type" "compare")])
6513
6514 (define_insn "*cmp_cc_set_not"
6515 [(set (reg:CC 100)
6516 (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
6517 (const_int 0)))
6518 (set (match_operand:SI 0 "register_operand" "=r")
6519 (not:SI (match_dup 1)))]
6520 ""
6521 "xnorcc\t%%g0, %1, %0"
6522 [(set_attr "type" "compare")])
6523
6524 (define_insn "*cmp_ccx_set_not"
6525 [(set (reg:CCX 100)
6526 (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6527 (const_int 0)))
6528 (set (match_operand:DI 0 "register_operand" "=r")
6529 (not:DI (match_dup 1)))]
6530 "TARGET_ARCH64"
6531 "xnorcc\t%%g0, %1, %0"
6532 [(set_attr "type" "compare")])
6533
6534 (define_insn "*cmp_cc_set"
6535 [(set (match_operand:SI 0 "register_operand" "=r")
6536 (match_operand:SI 1 "register_operand" "r"))
6537 (set (reg:CC 100)
6538 (compare:CC (match_dup 1)
6539 (const_int 0)))]
6540 ""
6541 "orcc\t%1, 0, %0"
6542 [(set_attr "type" "compare")])
6543
6544 (define_insn "*cmp_ccx_set64"
6545 [(set (match_operand:DI 0 "register_operand" "=r")
6546 (match_operand:DI 1 "register_operand" "r"))
6547 (set (reg:CCX 100)
6548 (compare:CCX (match_dup 1)
6549 (const_int 0)))]
6550 "TARGET_ARCH64"
6551 "orcc\t%1, 0, %0"
6552 [(set_attr "type" "compare")])
6553 \f
6554 ;; Floating point arithmetic instructions.
6555
6556 (define_expand "addtf3"
6557 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6558 (plus:TF (match_operand:TF 1 "general_operand" "")
6559 (match_operand:TF 2 "general_operand" "")))]
6560 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6561 "emit_tfmode_binop (PLUS, operands); DONE;")
6562
6563 (define_insn "*addtf3_hq"
6564 [(set (match_operand:TF 0 "register_operand" "=e")
6565 (plus:TF (match_operand:TF 1 "register_operand" "e")
6566 (match_operand:TF 2 "register_operand" "e")))]
6567 "TARGET_FPU && TARGET_HARD_QUAD"
6568 "faddq\t%1, %2, %0"
6569 [(set_attr "type" "fp")])
6570
6571 (define_insn "adddf3"
6572 [(set (match_operand:DF 0 "register_operand" "=e")
6573 (plus:DF (match_operand:DF 1 "register_operand" "e")
6574 (match_operand:DF 2 "register_operand" "e")))]
6575 "TARGET_FPU"
6576 "faddd\t%1, %2, %0"
6577 [(set_attr "type" "fp")
6578 (set_attr "fptype" "double")])
6579
6580 (define_insn "addsf3"
6581 [(set (match_operand:SF 0 "register_operand" "=f")
6582 (plus:SF (match_operand:SF 1 "register_operand" "f")
6583 (match_operand:SF 2 "register_operand" "f")))]
6584 "TARGET_FPU"
6585 "fadds\t%1, %2, %0"
6586 [(set_attr "type" "fp")])
6587
6588 (define_expand "subtf3"
6589 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6590 (minus:TF (match_operand:TF 1 "general_operand" "")
6591 (match_operand:TF 2 "general_operand" "")))]
6592 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6593 "emit_tfmode_binop (MINUS, operands); DONE;")
6594
6595 (define_insn "*subtf3_hq"
6596 [(set (match_operand:TF 0 "register_operand" "=e")
6597 (minus:TF (match_operand:TF 1 "register_operand" "e")
6598 (match_operand:TF 2 "register_operand" "e")))]
6599 "TARGET_FPU && TARGET_HARD_QUAD"
6600 "fsubq\t%1, %2, %0"
6601 [(set_attr "type" "fp")])
6602
6603 (define_insn "subdf3"
6604 [(set (match_operand:DF 0 "register_operand" "=e")
6605 (minus:DF (match_operand:DF 1 "register_operand" "e")
6606 (match_operand:DF 2 "register_operand" "e")))]
6607 "TARGET_FPU"
6608 "fsubd\t%1, %2, %0"
6609 [(set_attr "type" "fp")
6610 (set_attr "fptype" "double")])
6611
6612 (define_insn "subsf3"
6613 [(set (match_operand:SF 0 "register_operand" "=f")
6614 (minus:SF (match_operand:SF 1 "register_operand" "f")
6615 (match_operand:SF 2 "register_operand" "f")))]
6616 "TARGET_FPU"
6617 "fsubs\t%1, %2, %0"
6618 [(set_attr "type" "fp")])
6619
6620 (define_expand "multf3"
6621 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6622 (mult:TF (match_operand:TF 1 "general_operand" "")
6623 (match_operand:TF 2 "general_operand" "")))]
6624 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6625 "emit_tfmode_binop (MULT, operands); DONE;")
6626
6627 (define_insn "*multf3_hq"
6628 [(set (match_operand:TF 0 "register_operand" "=e")
6629 (mult:TF (match_operand:TF 1 "register_operand" "e")
6630 (match_operand:TF 2 "register_operand" "e")))]
6631 "TARGET_FPU && TARGET_HARD_QUAD"
6632 "fmulq\t%1, %2, %0"
6633 [(set_attr "type" "fpmul")])
6634
6635 (define_insn "muldf3"
6636 [(set (match_operand:DF 0 "register_operand" "=e")
6637 (mult:DF (match_operand:DF 1 "register_operand" "e")
6638 (match_operand:DF 2 "register_operand" "e")))]
6639 "TARGET_FPU"
6640 "fmuld\t%1, %2, %0"
6641 [(set_attr "type" "fpmul")
6642 (set_attr "fptype" "double")])
6643
6644 (define_insn "mulsf3"
6645 [(set (match_operand:SF 0 "register_operand" "=f")
6646 (mult:SF (match_operand:SF 1 "register_operand" "f")
6647 (match_operand:SF 2 "register_operand" "f")))]
6648 "TARGET_FPU"
6649 "fmuls\t%1, %2, %0"
6650 [(set_attr "type" "fpmul")])
6651
6652 (define_insn "*muldf3_extend"
6653 [(set (match_operand:DF 0 "register_operand" "=e")
6654 (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
6655 (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
6656 "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
6657 "fsmuld\t%1, %2, %0"
6658 [(set_attr "type" "fpmul")
6659 (set_attr "fptype" "double")])
6660
6661 (define_insn "*multf3_extend"
6662 [(set (match_operand:TF 0 "register_operand" "=e")
6663 (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
6664 (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
6665 "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
6666 "fdmulq\t%1, %2, %0"
6667 [(set_attr "type" "fpmul")])
6668
6669 (define_expand "divtf3"
6670 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6671 (div:TF (match_operand:TF 1 "general_operand" "")
6672 (match_operand:TF 2 "general_operand" "")))]
6673 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6674 "emit_tfmode_binop (DIV, operands); DONE;")
6675
6676 ;; don't have timing for quad-prec. divide.
6677 (define_insn "*divtf3_hq"
6678 [(set (match_operand:TF 0 "register_operand" "=e")
6679 (div:TF (match_operand:TF 1 "register_operand" "e")
6680 (match_operand:TF 2 "register_operand" "e")))]
6681 "TARGET_FPU && TARGET_HARD_QUAD"
6682 "fdivq\t%1, %2, %0"
6683 [(set_attr "type" "fpdivd")])
6684
6685 (define_insn "divdf3"
6686 [(set (match_operand:DF 0 "register_operand" "=e")
6687 (div:DF (match_operand:DF 1 "register_operand" "e")
6688 (match_operand:DF 2 "register_operand" "e")))]
6689 "TARGET_FPU"
6690 "fdivd\t%1, %2, %0"
6691 [(set_attr "type" "fpdivd")
6692 (set_attr "fptype" "double")])
6693
6694 (define_insn "divsf3"
6695 [(set (match_operand:SF 0 "register_operand" "=f")
6696 (div:SF (match_operand:SF 1 "register_operand" "f")
6697 (match_operand:SF 2 "register_operand" "f")))]
6698 "TARGET_FPU"
6699 "fdivs\t%1, %2, %0"
6700 [(set_attr "type" "fpdivs")])
6701
6702 (define_expand "negtf2"
6703 [(set (match_operand:TF 0 "register_operand" "=e,e")
6704 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6705 "TARGET_FPU"
6706 "")
6707
6708 (define_insn_and_split "*negtf2_notv9"
6709 [(set (match_operand:TF 0 "register_operand" "=e,e")
6710 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6711 ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6712 "TARGET_FPU
6713 && ! TARGET_V9"
6714 "@
6715 fnegs\t%0, %0
6716 #"
6717 "&& reload_completed
6718 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6719 [(set (match_dup 2) (neg:SF (match_dup 3)))
6720 (set (match_dup 4) (match_dup 5))
6721 (set (match_dup 6) (match_dup 7))]
6722 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6723 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6724 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6725 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
6726 operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6727 operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6728 [(set_attr "type" "fpmove,*")
6729 (set_attr "length" "*,2")])
6730
6731 (define_insn_and_split "*negtf2_v9"
6732 [(set (match_operand:TF 0 "register_operand" "=e,e")
6733 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6734 ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6735 "TARGET_FPU && TARGET_V9"
6736 "@
6737 fnegd\t%0, %0
6738 #"
6739 "&& reload_completed
6740 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6741 [(set (match_dup 2) (neg:DF (match_dup 3)))
6742 (set (match_dup 4) (match_dup 5))]
6743 "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
6744 operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
6745 operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6746 operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6747 [(set_attr "type" "fpmove,*")
6748 (set_attr "length" "*,2")
6749 (set_attr "fptype" "double")])
6750
6751 (define_expand "negdf2"
6752 [(set (match_operand:DF 0 "register_operand" "")
6753 (neg:DF (match_operand:DF 1 "register_operand" "")))]
6754 "TARGET_FPU"
6755 "")
6756
6757 (define_insn_and_split "*negdf2_notv9"
6758 [(set (match_operand:DF 0 "register_operand" "=e,e")
6759 (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
6760 "TARGET_FPU && ! TARGET_V9"
6761 "@
6762 fnegs\t%0, %0
6763 #"
6764 "&& reload_completed
6765 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6766 [(set (match_dup 2) (neg:SF (match_dup 3)))
6767 (set (match_dup 4) (match_dup 5))]
6768 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6769 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6770 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6771 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
6772 [(set_attr "type" "fpmove,*")
6773 (set_attr "length" "*,2")])
6774
6775 (define_insn "*negdf2_v9"
6776 [(set (match_operand:DF 0 "register_operand" "=e")
6777 (neg:DF (match_operand:DF 1 "register_operand" "e")))]
6778 "TARGET_FPU && TARGET_V9"
6779 "fnegd\t%1, %0"
6780 [(set_attr "type" "fpmove")
6781 (set_attr "fptype" "double")])
6782
6783 (define_insn "negsf2"
6784 [(set (match_operand:SF 0 "register_operand" "=f")
6785 (neg:SF (match_operand:SF 1 "register_operand" "f")))]
6786 "TARGET_FPU"
6787 "fnegs\t%1, %0"
6788 [(set_attr "type" "fpmove")])
6789
6790 (define_expand "abstf2"
6791 [(set (match_operand:TF 0 "register_operand" "")
6792 (abs:TF (match_operand:TF 1 "register_operand" "")))]
6793 "TARGET_FPU"
6794 "")
6795
6796 (define_insn_and_split "*abstf2_notv9"
6797 [(set (match_operand:TF 0 "register_operand" "=e,e")
6798 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6799 ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6800 "TARGET_FPU && ! TARGET_V9"
6801 "@
6802 fabss\t%0, %0
6803 #"
6804 "&& reload_completed
6805 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6806 [(set (match_dup 2) (abs:SF (match_dup 3)))
6807 (set (match_dup 4) (match_dup 5))
6808 (set (match_dup 6) (match_dup 7))]
6809 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6810 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6811 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6812 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
6813 operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6814 operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6815 [(set_attr "type" "fpmove,*")
6816 (set_attr "length" "*,2")])
6817
6818 (define_insn "*abstf2_hq_v9"
6819 [(set (match_operand:TF 0 "register_operand" "=e,e")
6820 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6821 "TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
6822 "@
6823 fabsd\t%0, %0
6824 fabsq\t%1, %0"
6825 [(set_attr "type" "fpmove")
6826 (set_attr "fptype" "double,*")])
6827
6828 (define_insn_and_split "*abstf2_v9"
6829 [(set (match_operand:TF 0 "register_operand" "=e,e")
6830 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6831 "TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
6832 "@
6833 fabsd\t%0, %0
6834 #"
6835 "&& reload_completed
6836 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6837 [(set (match_dup 2) (abs:DF (match_dup 3)))
6838 (set (match_dup 4) (match_dup 5))]
6839 "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
6840 operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
6841 operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6842 operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6843 [(set_attr "type" "fpmove,*")
6844 (set_attr "length" "*,2")
6845 (set_attr "fptype" "double,*")])
6846
6847 (define_expand "absdf2"
6848 [(set (match_operand:DF 0 "register_operand" "")
6849 (abs:DF (match_operand:DF 1 "register_operand" "")))]
6850 "TARGET_FPU"
6851 "")
6852
6853 (define_insn_and_split "*absdf2_notv9"
6854 [(set (match_operand:DF 0 "register_operand" "=e,e")
6855 (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
6856 "TARGET_FPU && ! TARGET_V9"
6857 "@
6858 fabss\t%0, %0
6859 #"
6860 "&& reload_completed
6861 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6862 [(set (match_dup 2) (abs:SF (match_dup 3)))
6863 (set (match_dup 4) (match_dup 5))]
6864 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6865 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6866 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6867 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
6868 [(set_attr "type" "fpmove,*")
6869 (set_attr "length" "*,2")])
6870
6871 (define_insn "*absdf2_v9"
6872 [(set (match_operand:DF 0 "register_operand" "=e")
6873 (abs:DF (match_operand:DF 1 "register_operand" "e")))]
6874 "TARGET_FPU && TARGET_V9"
6875 "fabsd\t%1, %0"
6876 [(set_attr "type" "fpmove")
6877 (set_attr "fptype" "double")])
6878
6879 (define_insn "abssf2"
6880 [(set (match_operand:SF 0 "register_operand" "=f")
6881 (abs:SF (match_operand:SF 1 "register_operand" "f")))]
6882 "TARGET_FPU"
6883 "fabss\t%1, %0"
6884 [(set_attr "type" "fpmove")])
6885
6886 (define_expand "sqrttf2"
6887 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6888 (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
6889 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6890 "emit_tfmode_unop (SQRT, operands); DONE;")
6891
6892 (define_insn "*sqrttf2_hq"
6893 [(set (match_operand:TF 0 "register_operand" "=e")
6894 (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
6895 "TARGET_FPU && TARGET_HARD_QUAD"
6896 "fsqrtq\t%1, %0"
6897 [(set_attr "type" "fpsqrtd")])
6898
6899 (define_insn "sqrtdf2"
6900 [(set (match_operand:DF 0 "register_operand" "=e")
6901 (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
6902 "TARGET_FPU"
6903 "fsqrtd\t%1, %0"
6904 [(set_attr "type" "fpsqrtd")
6905 (set_attr "fptype" "double")])
6906
6907 (define_insn "sqrtsf2"
6908 [(set (match_operand:SF 0 "register_operand" "=f")
6909 (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
6910 "TARGET_FPU"
6911 "fsqrts\t%1, %0"
6912 [(set_attr "type" "fpsqrts")])
6913 \f
6914 ;;- arithmetic shift instructions
6915
6916 (define_insn "ashlsi3"
6917 [(set (match_operand:SI 0 "register_operand" "=r")
6918 (ashift:SI (match_operand:SI 1 "register_operand" "r")
6919 (match_operand:SI 2 "arith_operand" "rI")))]
6920 ""
6921 {
6922 if (operands[2] == const1_rtx)
6923 return "add\t%1, %1, %0";
6924 return "sll\t%1, %2, %0";
6925 }
6926 [(set (attr "type")
6927 (if_then_else (match_operand 2 "const1_operand" "")
6928 (const_string "ialu") (const_string "shift")))])
6929
6930 (define_expand "ashldi3"
6931 [(set (match_operand:DI 0 "register_operand" "=r")
6932 (ashift:DI (match_operand:DI 1 "register_operand" "r")
6933 (match_operand:SI 2 "arith_operand" "rI")))]
6934 "TARGET_ARCH64 || TARGET_V8PLUS"
6935 {
6936 if (! TARGET_ARCH64)
6937 {
6938 if (GET_CODE (operands[2]) == CONST_INT)
6939 FAIL;
6940 emit_insn (gen_ashldi3_v8plus (operands[0], operands[1], operands[2]));
6941 DONE;
6942 }
6943 })
6944
6945 (define_insn "*ashldi3_sp64"
6946 [(set (match_operand:DI 0 "register_operand" "=r")
6947 (ashift:DI (match_operand:DI 1 "register_operand" "r")
6948 (match_operand:SI 2 "arith_operand" "rI")))]
6949 "TARGET_ARCH64"
6950 {
6951 if (operands[2] == const1_rtx)
6952 return "add\t%1, %1, %0";
6953 return "sllx\t%1, %2, %0";
6954 }
6955 [(set (attr "type")
6956 (if_then_else (match_operand 2 "const1_operand" "")
6957 (const_string "ialu") (const_string "shift")))])
6958
6959 ;; XXX UGH!
6960 (define_insn "ashldi3_v8plus"
6961 [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
6962 (ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
6963 (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
6964 (clobber (match_scratch:SI 3 "=X,X,&h"))]
6965 "TARGET_V8PLUS"
6966 { return sparc_v8plus_shift (operands, insn, "sllx"); }
6967 [(set_attr "type" "multi")
6968 (set_attr "length" "5,5,6")])
6969
6970 ;; Optimize (1LL<<x)-1
6971 ;; XXX this also needs to be fixed to handle equal subregs
6972 ;; XXX first before we could re-enable it.
6973 ;(define_insn ""
6974 ; [(set (match_operand:DI 0 "register_operand" "=h")
6975 ; (plus:DI (ashift:DI (const_int 1)
6976 ; (match_operand:SI 1 "arith_operand" "rI"))
6977 ; (const_int -1)))]
6978 ; "0 && TARGET_V8PLUS"
6979 ;{
6980 ; if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == REGNO (operands[0]))
6981 ; return "mov\t1, %L0\;sllx\t%L0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
6982 ; return "mov\t1, %H0\;sllx\t%H0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
6983 ;}
6984 ; [(set_attr "type" "multi")
6985 ; (set_attr "length" "4")])
6986
6987 (define_insn "*cmp_cc_ashift_1"
6988 [(set (reg:CC_NOOV 100)
6989 (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
6990 (const_int 1))
6991 (const_int 0)))]
6992 ""
6993 "addcc\t%0, %0, %%g0"
6994 [(set_attr "type" "compare")])
6995
6996 (define_insn "*cmp_cc_set_ashift_1"
6997 [(set (reg:CC_NOOV 100)
6998 (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
6999 (const_int 1))
7000 (const_int 0)))
7001 (set (match_operand:SI 0 "register_operand" "=r")
7002 (ashift:SI (match_dup 1) (const_int 1)))]
7003 ""
7004 "addcc\t%1, %1, %0"
7005 [(set_attr "type" "compare")])
7006
7007 (define_insn "ashrsi3"
7008 [(set (match_operand:SI 0 "register_operand" "=r")
7009 (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
7010 (match_operand:SI 2 "arith_operand" "rI")))]
7011 ""
7012 "sra\t%1, %2, %0"
7013 [(set_attr "type" "shift")])
7014
7015 (define_insn "*ashrsi3_extend"
7016 [(set (match_operand:DI 0 "register_operand" "=r")
7017 (sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
7018 (match_operand:SI 2 "arith_operand" "r"))))]
7019 "TARGET_ARCH64"
7020 "sra\t%1, %2, %0"
7021 [(set_attr "type" "shift")])
7022
7023 ;; This handles the case as above, but with constant shift instead of
7024 ;; register. Combiner "simplifies" it for us a little bit though.
7025 (define_insn "*ashrsi3_extend2"
7026 [(set (match_operand:DI 0 "register_operand" "=r")
7027 (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
7028 (const_int 32))
7029 (match_operand:SI 2 "small_int_or_double" "n")))]
7030 "TARGET_ARCH64
7031 && ((GET_CODE (operands[2]) == CONST_INT
7032 && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64)
7033 || (GET_CODE (operands[2]) == CONST_DOUBLE
7034 && !CONST_DOUBLE_HIGH (operands[2])
7035 && CONST_DOUBLE_LOW (operands[2]) >= 32
7036 && CONST_DOUBLE_LOW (operands[2]) < 64))"
7037 {
7038 operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
7039
7040 return "sra\t%1, %2, %0";
7041 }
7042 [(set_attr "type" "shift")])
7043
7044 (define_expand "ashrdi3"
7045 [(set (match_operand:DI 0 "register_operand" "=r")
7046 (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7047 (match_operand:SI 2 "arith_operand" "rI")))]
7048 "TARGET_ARCH64 || TARGET_V8PLUS"
7049 {
7050 if (! TARGET_ARCH64)
7051 {
7052 if (GET_CODE (operands[2]) == CONST_INT)
7053 FAIL; /* prefer generic code in this case */
7054 emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
7055 DONE;
7056 }
7057 })
7058
7059 (define_insn ""
7060 [(set (match_operand:DI 0 "register_operand" "=r")
7061 (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7062 (match_operand:SI 2 "arith_operand" "rI")))]
7063 "TARGET_ARCH64"
7064 "srax\t%1, %2, %0"
7065 [(set_attr "type" "shift")])
7066
7067 ;; XXX
7068 (define_insn "ashrdi3_v8plus"
7069 [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
7070 (ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
7071 (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
7072 (clobber (match_scratch:SI 3 "=X,X,&h"))]
7073 "TARGET_V8PLUS"
7074 { return sparc_v8plus_shift (operands, insn, "srax"); }
7075 [(set_attr "type" "multi")
7076 (set_attr "length" "5,5,6")])
7077
7078 (define_insn "lshrsi3"
7079 [(set (match_operand:SI 0 "register_operand" "=r")
7080 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
7081 (match_operand:SI 2 "arith_operand" "rI")))]
7082 ""
7083 "srl\t%1, %2, %0"
7084 [(set_attr "type" "shift")])
7085
7086 ;; This handles the case where
7087 ;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
7088 ;; but combiner "simplifies" it for us.
7089 (define_insn "*lshrsi3_extend"
7090 [(set (match_operand:DI 0 "register_operand" "=r")
7091 (and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
7092 (match_operand:SI 2 "arith_operand" "r")) 0)
7093 (match_operand 3 "" "")))]
7094 "TARGET_ARCH64
7095 && ((GET_CODE (operands[3]) == CONST_DOUBLE
7096 && CONST_DOUBLE_HIGH (operands[3]) == 0
7097 && CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
7098 || (HOST_BITS_PER_WIDE_INT >= 64
7099 && GET_CODE (operands[3]) == CONST_INT
7100 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff))"
7101 "srl\t%1, %2, %0"
7102 [(set_attr "type" "shift")])
7103
7104 ;; This handles the case where
7105 ;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int >=0 < 32))
7106 ;; but combiner "simplifies" it for us.
7107 (define_insn "*lshrsi3_extend2"
7108 [(set (match_operand:DI 0 "register_operand" "=r")
7109 (zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
7110 (match_operand 2 "small_int_or_double" "n")
7111 (const_int 32)))]
7112 "TARGET_ARCH64
7113 && ((GET_CODE (operands[2]) == CONST_INT
7114 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7115 || (GET_CODE (operands[2]) == CONST_DOUBLE
7116 && CONST_DOUBLE_HIGH (operands[2]) == 0
7117 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7118 {
7119 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
7120
7121 return "srl\t%1, %2, %0";
7122 }
7123 [(set_attr "type" "shift")])
7124
7125 (define_expand "lshrdi3"
7126 [(set (match_operand:DI 0 "register_operand" "=r")
7127 (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7128 (match_operand:SI 2 "arith_operand" "rI")))]
7129 "TARGET_ARCH64 || TARGET_V8PLUS"
7130 {
7131 if (! TARGET_ARCH64)
7132 {
7133 if (GET_CODE (operands[2]) == CONST_INT)
7134 FAIL;
7135 emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
7136 DONE;
7137 }
7138 })
7139
7140 (define_insn ""
7141 [(set (match_operand:DI 0 "register_operand" "=r")
7142 (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7143 (match_operand:SI 2 "arith_operand" "rI")))]
7144 "TARGET_ARCH64"
7145 "srlx\t%1, %2, %0"
7146 [(set_attr "type" "shift")])
7147
7148 ;; XXX
7149 (define_insn "lshrdi3_v8plus"
7150 [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
7151 (lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
7152 (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
7153 (clobber (match_scratch:SI 3 "=X,X,&h"))]
7154 "TARGET_V8PLUS"
7155 { return sparc_v8plus_shift (operands, insn, "srlx"); }
7156 [(set_attr "type" "multi")
7157 (set_attr "length" "5,5,6")])
7158
7159 (define_insn ""
7160 [(set (match_operand:SI 0 "register_operand" "=r")
7161 (ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7162 (const_int 32)) 4)
7163 (match_operand:SI 2 "small_int_or_double" "n")))]
7164 "TARGET_ARCH64
7165 && ((GET_CODE (operands[2]) == CONST_INT
7166 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7167 || (GET_CODE (operands[2]) == CONST_DOUBLE
7168 && !CONST_DOUBLE_HIGH (operands[2])
7169 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7170 {
7171 operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
7172
7173 return "srax\t%1, %2, %0";
7174 }
7175 [(set_attr "type" "shift")])
7176
7177 (define_insn ""
7178 [(set (match_operand:SI 0 "register_operand" "=r")
7179 (lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7180 (const_int 32)) 4)
7181 (match_operand:SI 2 "small_int_or_double" "n")))]
7182 "TARGET_ARCH64
7183 && ((GET_CODE (operands[2]) == CONST_INT
7184 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7185 || (GET_CODE (operands[2]) == CONST_DOUBLE
7186 && !CONST_DOUBLE_HIGH (operands[2])
7187 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7188 {
7189 operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
7190
7191 return "srlx\t%1, %2, %0";
7192 }
7193 [(set_attr "type" "shift")])
7194
7195 (define_insn ""
7196 [(set (match_operand:SI 0 "register_operand" "=r")
7197 (ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7198 (match_operand:SI 2 "small_int_or_double" "n")) 4)
7199 (match_operand:SI 3 "small_int_or_double" "n")))]
7200 "TARGET_ARCH64
7201 && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
7202 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
7203 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
7204 && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
7205 {
7206 operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
7207
7208 return "srax\t%1, %2, %0";
7209 }
7210 [(set_attr "type" "shift")])
7211
7212 (define_insn ""
7213 [(set (match_operand:SI 0 "register_operand" "=r")
7214 (lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7215 (match_operand:SI 2 "small_int_or_double" "n")) 4)
7216 (match_operand:SI 3 "small_int_or_double" "n")))]
7217 "TARGET_ARCH64
7218 && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
7219 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
7220 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
7221 && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
7222 {
7223 operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
7224
7225 return "srlx\t%1, %2, %0";
7226 }
7227 [(set_attr "type" "shift")])
7228 \f
7229 ;; Unconditional and other jump instructions
7230 ;; On the SPARC, by setting the annul bit on an unconditional branch, the
7231 ;; following insn is never executed. This saves us a nop. Dbx does not
7232 ;; handle such branches though, so we only use them when optimizing.
7233 (define_insn "jump"
7234 [(set (pc) (label_ref (match_operand 0 "" "")))]
7235 ""
7236 {
7237 /* TurboSPARC is reported to have problems with
7238 with
7239 foo: b,a foo
7240 i.e. an empty loop with the annul bit set. The workaround is to use
7241 foo: b foo; nop
7242 instead. */
7243
7244 if (! TARGET_V9 && flag_delayed_branch
7245 && (INSN_ADDRESSES (INSN_UID (operands[0]))
7246 == INSN_ADDRESSES (INSN_UID (insn))))
7247 return "b\t%l0%#";
7248 else
7249 return TARGET_V9 ? "ba,pt%*\t%%xcc, %l0%(" : "b%*\t%l0%(";
7250 }
7251 [(set_attr "type" "uncond_branch")])
7252
7253 (define_expand "tablejump"
7254 [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
7255 (use (label_ref (match_operand 1 "" "")))])]
7256 ""
7257 {
7258 if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
7259 abort ();
7260
7261 /* In pic mode, our address differences are against the base of the
7262 table. Add that base value back in; CSE ought to be able to combine
7263 the two address loads. */
7264 if (flag_pic)
7265 {
7266 rtx tmp, tmp2;
7267 tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
7268 tmp2 = operands[0];
7269 if (CASE_VECTOR_MODE != Pmode)
7270 tmp2 = gen_rtx_SIGN_EXTEND (Pmode, tmp2);
7271 tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
7272 operands[0] = memory_address (Pmode, tmp);
7273 }
7274 })
7275
7276 (define_insn "*tablejump_sp32"
7277 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
7278 (use (label_ref (match_operand 1 "" "")))]
7279 "! TARGET_ARCH64"
7280 "jmp\t%a0%#"
7281 [(set_attr "type" "uncond_branch")])
7282
7283 (define_insn "*tablejump_sp64"
7284 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
7285 (use (label_ref (match_operand 1 "" "")))]
7286 "TARGET_ARCH64"
7287 "jmp\t%a0%#"
7288 [(set_attr "type" "uncond_branch")])
7289
7290 ;; This pattern recognizes the "instruction" that appears in
7291 ;; a function call that wants a structure value,
7292 ;; to inform the called function if compiled with Sun CC.
7293 ;(define_insn "*unimp_insn"
7294 ; [(match_operand:SI 0 "immediate_operand" "")]
7295 ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
7296 ; "unimp\t%0"
7297 ; [(set_attr "type" "marker")])
7298
7299 ;;- jump to subroutine
7300 (define_expand "call"
7301 ;; Note that this expression is not used for generating RTL.
7302 ;; All the RTL is generated explicitly below.
7303 [(call (match_operand 0 "call_operand" "")
7304 (match_operand 3 "" "i"))]
7305 ;; operands[2] is next_arg_register
7306 ;; operands[3] is struct_value_size_rtx.
7307 ""
7308 {
7309 rtx fn_rtx, nregs_rtx;
7310
7311 if (GET_MODE (operands[0]) != FUNCTION_MODE)
7312 abort ();
7313
7314 if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
7315 {
7316 /* This is really a PIC sequence. We want to represent
7317 it as a funny jump so its delay slots can be filled.
7318
7319 ??? But if this really *is* a CALL, will not it clobber the
7320 call-clobbered registers? We lose this if it is a JUMP_INSN.
7321 Why cannot we have delay slots filled if it were a CALL? */
7322
7323 if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
7324 emit_jump_insn
7325 (gen_rtx_PARALLEL
7326 (VOIDmode,
7327 gen_rtvec (3,
7328 gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
7329 operands[3],
7330 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7331 else
7332 emit_jump_insn
7333 (gen_rtx_PARALLEL
7334 (VOIDmode,
7335 gen_rtvec (2,
7336 gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
7337 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7338 goto finish_call;
7339 }
7340
7341 fn_rtx = operands[0];
7342
7343 /* Count the number of parameter registers being used by this call.
7344 if that argument is NULL, it means we are using them all, which
7345 means 6 on the sparc. */
7346 #if 0
7347 if (operands[2])
7348 nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
7349 else
7350 nregs_rtx = GEN_INT (6);
7351 #else
7352 nregs_rtx = const0_rtx;
7353 #endif
7354
7355 if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
7356 emit_call_insn
7357 (gen_rtx_PARALLEL
7358 (VOIDmode,
7359 gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
7360 operands[3],
7361 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7362 else
7363 emit_call_insn
7364 (gen_rtx_PARALLEL
7365 (VOIDmode,
7366 gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
7367 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7368
7369 finish_call:
7370 #if 0
7371 /* If this call wants a structure value,
7372 emit an unimp insn to let the called function know about this. */
7373 if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
7374 {
7375 rtx insn = emit_insn (operands[3]);
7376 SCHED_GROUP_P (insn) = 1;
7377 }
7378 #endif
7379
7380 DONE;
7381 })
7382
7383 ;; We can't use the same pattern for these two insns, because then registers
7384 ;; in the address may not be properly reloaded.
7385
7386 (define_insn "*call_address_sp32"
7387 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7388 (match_operand 1 "" ""))
7389 (clobber (reg:SI 15))]
7390 ;;- Do not use operand 1 for most machines.
7391 "! TARGET_ARCH64"
7392 "call\t%a0, %1%#"
7393 [(set_attr "type" "call")])
7394
7395 (define_insn "*call_symbolic_sp32"
7396 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7397 (match_operand 1 "" ""))
7398 (clobber (reg:SI 15))]
7399 ;;- Do not use operand 1 for most machines.
7400 "! TARGET_ARCH64"
7401 "call\t%a0, %1%#"
7402 [(set_attr "type" "call")])
7403
7404 (define_insn "*call_address_sp64"
7405 [(call (mem:DI (match_operand:DI 0 "address_operand" "p"))
7406 (match_operand 1 "" ""))
7407 (clobber (reg:DI 15))]
7408 ;;- Do not use operand 1 for most machines.
7409 "TARGET_ARCH64"
7410 "call\t%a0, %1%#"
7411 [(set_attr "type" "call")])
7412
7413 (define_insn "*call_symbolic_sp64"
7414 [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
7415 (match_operand 1 "" ""))
7416 (clobber (reg:DI 15))]
7417 ;;- Do not use operand 1 for most machines.
7418 "TARGET_ARCH64"
7419 "call\t%a0, %1%#"
7420 [(set_attr "type" "call")])
7421
7422 ;; This is a call that wants a structure value.
7423 ;; There is no such critter for v9 (??? we may need one anyway).
7424 (define_insn "*call_address_struct_value_sp32"
7425 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7426 (match_operand 1 "" ""))
7427 (match_operand 2 "immediate_operand" "")
7428 (clobber (reg:SI 15))]
7429 ;;- Do not use operand 1 for most machines.
7430 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
7431 "call\t%a0, %1\n\tnop\n\tunimp\t%2"
7432 [(set_attr "type" "call_no_delay_slot")
7433 (set_attr "length" "3")])
7434
7435 ;; This is a call that wants a structure value.
7436 ;; There is no such critter for v9 (??? we may need one anyway).
7437 (define_insn "*call_symbolic_struct_value_sp32"
7438 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7439 (match_operand 1 "" ""))
7440 (match_operand 2 "immediate_operand" "")
7441 (clobber (reg:SI 15))]
7442 ;;- Do not use operand 1 for most machines.
7443 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
7444 "call\t%a0, %1\n\tnop\n\tunimp\t%2"
7445 [(set_attr "type" "call_no_delay_slot")
7446 (set_attr "length" "3")])
7447
7448 ;; This is a call that may want a structure value. This is used for
7449 ;; untyped_calls.
7450 (define_insn "*call_address_untyped_struct_value_sp32"
7451 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7452 (match_operand 1 "" ""))
7453 (match_operand 2 "immediate_operand" "")
7454 (clobber (reg:SI 15))]
7455 ;;- Do not use operand 1 for most machines.
7456 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
7457 "call\t%a0, %1\n\tnop\n\tnop"
7458 [(set_attr "type" "call_no_delay_slot")
7459 (set_attr "length" "3")])
7460
7461 ;; This is a call that wants a structure value.
7462 (define_insn "*call_symbolic_untyped_struct_value_sp32"
7463 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7464 (match_operand 1 "" ""))
7465 (match_operand 2 "immediate_operand" "")
7466 (clobber (reg:SI 15))]
7467 ;;- Do not use operand 1 for most machines.
7468 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
7469 "call\t%a0, %1\n\tnop\n\tnop"
7470 [(set_attr "type" "call_no_delay_slot")
7471 (set_attr "length" "3")])
7472
7473 (define_expand "call_value"
7474 ;; Note that this expression is not used for generating RTL.
7475 ;; All the RTL is generated explicitly below.
7476 [(set (match_operand 0 "register_operand" "=rf")
7477 (call (match_operand 1 "" "")
7478 (match_operand 4 "" "")))]
7479 ;; operand 2 is stack_size_rtx
7480 ;; operand 3 is next_arg_register
7481 ""
7482 {
7483 rtx fn_rtx, nregs_rtx;
7484 rtvec vec;
7485
7486 if (GET_MODE (operands[1]) != FUNCTION_MODE)
7487 abort ();
7488
7489 fn_rtx = operands[1];
7490
7491 #if 0
7492 if (operands[3])
7493 nregs_rtx = GEN_INT (REGNO (operands[3]) - 8);
7494 else
7495 nregs_rtx = GEN_INT (6);
7496 #else
7497 nregs_rtx = const0_rtx;
7498 #endif
7499
7500 vec = gen_rtvec (2,
7501 gen_rtx_SET (VOIDmode, operands[0],
7502 gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
7503 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
7504
7505 emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
7506
7507 DONE;
7508 })
7509
7510 (define_insn "*call_value_address_sp32"
7511 [(set (match_operand 0 "" "=rf")
7512 (call (mem:SI (match_operand:SI 1 "address_operand" "p"))
7513 (match_operand 2 "" "")))
7514 (clobber (reg:SI 15))]
7515 ;;- Do not use operand 2 for most machines.
7516 "! TARGET_ARCH64"
7517 "call\t%a1, %2%#"
7518 [(set_attr "type" "call")])
7519
7520 (define_insn "*call_value_symbolic_sp32"
7521 [(set (match_operand 0 "" "=rf")
7522 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
7523 (match_operand 2 "" "")))
7524 (clobber (reg:SI 15))]
7525 ;;- Do not use operand 2 for most machines.
7526 "! TARGET_ARCH64"
7527 "call\t%a1, %2%#"
7528 [(set_attr "type" "call")])
7529
7530 (define_insn "*call_value_address_sp64"
7531 [(set (match_operand 0 "" "")
7532 (call (mem:DI (match_operand:DI 1 "address_operand" "p"))
7533 (match_operand 2 "" "")))
7534 (clobber (reg:DI 15))]
7535 ;;- Do not use operand 2 for most machines.
7536 "TARGET_ARCH64"
7537 "call\t%a1, %2%#"
7538 [(set_attr "type" "call")])
7539
7540 (define_insn "*call_value_symbolic_sp64"
7541 [(set (match_operand 0 "" "")
7542 (call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
7543 (match_operand 2 "" "")))
7544 (clobber (reg:DI 15))]
7545 ;;- Do not use operand 2 for most machines.
7546 "TARGET_ARCH64"
7547 "call\t%a1, %2%#"
7548 [(set_attr "type" "call")])
7549
7550 (define_expand "untyped_call"
7551 [(parallel [(call (match_operand 0 "" "")
7552 (const_int 0))
7553 (match_operand 1 "" "")
7554 (match_operand 2 "" "")])]
7555 ""
7556 {
7557 int i;
7558
7559 /* Pass constm1 to indicate that it may expect a structure value, but
7560 we don't know what size it is. */
7561 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));
7562
7563 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7564 {
7565 rtx set = XVECEXP (operands[2], 0, i);
7566 emit_move_insn (SET_DEST (set), SET_SRC (set));
7567 }
7568
7569 /* The optimizer does not know that the call sets the function value
7570 registers we stored in the result block. We avoid problems by
7571 claiming that all hard registers are used and clobbered at this
7572 point. */
7573 emit_insn (gen_blockage ());
7574
7575 DONE;
7576 })
7577
7578 ;;- tail calls
7579 (define_expand "sibcall"
7580 [(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
7581 (return)])]
7582 ""
7583 "")
7584
7585 (define_insn "*sibcall_symbolic_sp32"
7586 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7587 (match_operand 1 "" ""))
7588 (return)]
7589 "! TARGET_ARCH64"
7590 "* return output_sibcall(insn, operands[0]);"
7591 [(set_attr "type" "sibcall")])
7592
7593 (define_insn "*sibcall_symbolic_sp64"
7594 [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
7595 (match_operand 1 "" ""))
7596 (return)]
7597 "TARGET_ARCH64"
7598 "* return output_sibcall(insn, operands[0]);"
7599 [(set_attr "type" "sibcall")])
7600
7601 (define_expand "sibcall_value"
7602 [(parallel [(set (match_operand 0 "register_operand" "=rf")
7603 (call (match_operand 1 "" "") (const_int 0)))
7604 (return)])]
7605 ""
7606 "")
7607
7608 (define_insn "*sibcall_value_symbolic_sp32"
7609 [(set (match_operand 0 "" "=rf")
7610 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
7611 (match_operand 2 "" "")))
7612 (return)]
7613 "! TARGET_ARCH64"
7614 "* return output_sibcall(insn, operands[1]);"
7615 [(set_attr "type" "sibcall")])
7616
7617 (define_insn "*sibcall_value_symbolic_sp64"
7618 [(set (match_operand 0 "" "")
7619 (call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
7620 (match_operand 2 "" "")))
7621 (return)]
7622 "TARGET_ARCH64"
7623 "* return output_sibcall(insn, operands[1]);"
7624 [(set_attr "type" "sibcall")])
7625
7626 (define_expand "sibcall_epilogue"
7627 [(const_int 0)]
7628 ""
7629 "DONE;")
7630
7631 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7632 ;; all of memory. This blocks insns from being moved across this point.
7633
7634 (define_insn "blockage"
7635 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7636 ""
7637 ""
7638 [(set_attr "length" "0")])
7639
7640 ;; Prepare to return any type including a structure value.
7641
7642 (define_expand "untyped_return"
7643 [(match_operand:BLK 0 "memory_operand" "")
7644 (match_operand 1 "" "")]
7645 ""
7646 {
7647 rtx valreg1 = gen_rtx_REG (DImode, 24);
7648 rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
7649 rtx result = operands[0];
7650
7651 if (! TARGET_ARCH64)
7652 {
7653 rtx rtnreg = gen_rtx_REG (SImode, (current_function_uses_only_leaf_regs
7654 ? 15 : 31));
7655 rtx value = gen_reg_rtx (SImode);
7656
7657 /* Fetch the instruction where we will return to and see if it's an unimp
7658 instruction (the most significant 10 bits will be zero). If so,
7659 update the return address to skip the unimp instruction. */
7660 emit_move_insn (value,
7661 gen_rtx_MEM (SImode, plus_constant (rtnreg, 8)));
7662 emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
7663 emit_insn (gen_update_return (rtnreg, value));
7664 }
7665
7666 /* Reload the function value registers. */
7667 emit_move_insn (valreg1, adjust_address (result, DImode, 0));
7668 emit_move_insn (valreg2,
7669 adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8));
7670
7671 /* Put USE insns before the return. */
7672 emit_insn (gen_rtx_USE (VOIDmode, valreg1));
7673 emit_insn (gen_rtx_USE (VOIDmode, valreg2));
7674
7675 /* Construct the return. */
7676 expand_null_return ();
7677
7678 DONE;
7679 })
7680
7681 ;; This is a bit of a hack. We're incrementing a fixed register (%i7),
7682 ;; and parts of the compiler don't want to believe that the add is needed.
7683
7684 (define_insn "update_return"
7685 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
7686 (match_operand:SI 1 "register_operand" "r")] UNSPEC_UPDATE_RETURN)]
7687 "! TARGET_ARCH64"
7688 "cmp\t%1, 0\;be,a\t.+8\;add\t%0, 4, %0"
7689 [(set_attr "type" "multi")
7690 (set_attr "length" "3")])
7691 \f
7692 (define_insn "nop"
7693 [(const_int 0)]
7694 ""
7695 "nop")
7696
7697 (define_expand "indirect_jump"
7698 [(set (pc) (match_operand 0 "address_operand" "p"))]
7699 ""
7700 "")
7701
7702 (define_insn "*branch_sp32"
7703 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
7704 "! TARGET_ARCH64"
7705 "jmp\t%a0%#"
7706 [(set_attr "type" "uncond_branch")])
7707
7708 (define_insn "*branch_sp64"
7709 [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
7710 "TARGET_ARCH64"
7711 "jmp\t%a0%#"
7712 [(set_attr "type" "uncond_branch")])
7713
7714 ;; ??? Doesn't work with -mflat.
7715 (define_expand "nonlocal_goto"
7716 [(match_operand:SI 0 "general_operand" "")
7717 (match_operand:SI 1 "general_operand" "")
7718 (match_operand:SI 2 "general_operand" "")
7719 (match_operand:SI 3 "" "")]
7720 ""
7721 {
7722 #if 0
7723 rtx chain = operands[0];
7724 #endif
7725 rtx lab = operands[1];
7726 rtx stack = operands[2];
7727 rtx fp = operands[3];
7728 rtx labreg;
7729
7730 /* Trap instruction to flush all the register windows. */
7731 emit_insn (gen_flush_register_windows ());
7732
7733 /* Load the fp value for the containing fn into %fp. This is needed
7734 because STACK refers to %fp. Note that virtual register instantiation
7735 fails if the virtual %fp isn't set from a register. */
7736 if (GET_CODE (fp) != REG)
7737 fp = force_reg (Pmode, fp);
7738 emit_move_insn (virtual_stack_vars_rtx, fp);
7739
7740 /* Find the containing function's current nonlocal goto handler,
7741 which will do any cleanups and then jump to the label. */
7742 labreg = gen_rtx_REG (Pmode, 8);
7743 emit_move_insn (labreg, lab);
7744
7745 /* Restore %fp from stack pointer value for containing function.
7746 The restore insn that follows will move this to %sp,
7747 and reload the appropriate value into %fp. */
7748 emit_move_insn (hard_frame_pointer_rtx, stack);
7749
7750 /* USE of frame_pointer_rtx added for consistency; not clear if
7751 really needed. */
7752 /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
7753 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
7754
7755 #if 0
7756 /* Return, restoring reg window and jumping to goto handler. */
7757 if (TARGET_V9 && GET_CODE (chain) == CONST_INT
7758 && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
7759 {
7760 emit_jump_insn (gen_goto_handler_and_restore_v9 (labreg,
7761 static_chain_rtx,
7762 chain));
7763 emit_barrier ();
7764 DONE;
7765 }
7766 /* Put in the static chain register the nonlocal label address. */
7767 emit_move_insn (static_chain_rtx, chain);
7768 #endif
7769
7770 emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
7771 emit_jump_insn (gen_goto_handler_and_restore (labreg));
7772 emit_barrier ();
7773 DONE;
7774 })
7775
7776 ;; Special trap insn to flush register windows.
7777 (define_insn "flush_register_windows"
7778 [(unspec_volatile [(const_int 0)] UNSPECV_FLUSHW)]
7779 ""
7780 { return TARGET_V9 ? "flushw" : "ta\t3"; }
7781 [(set_attr "type" "flushw")])
7782
7783 (define_insn "goto_handler_and_restore"
7784 [(unspec_volatile [(match_operand 0 "register_operand" "=r")] UNSPECV_GOTO)]
7785 "GET_MODE (operands[0]) == Pmode"
7786 "jmp\t%0+0\n\trestore"
7787 [(set_attr "type" "multi")
7788 (set_attr "length" "2")])
7789
7790 ;;(define_insn "goto_handler_and_restore_v9"
7791 ;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
7792 ;; (match_operand:SI 1 "register_operand" "=r,r")
7793 ;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
7794 ;; "TARGET_V9 && ! TARGET_ARCH64"
7795 ;; "@
7796 ;; return\t%0+0\n\tmov\t%2, %Y1
7797 ;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
7798 ;; [(set_attr "type" "multi")
7799 ;; (set_attr "length" "2,3")])
7800 ;;
7801 ;;(define_insn "*goto_handler_and_restore_v9_sp64"
7802 ;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
7803 ;; (match_operand:DI 1 "register_operand" "=r,r")
7804 ;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
7805 ;; "TARGET_V9 && TARGET_ARCH64"
7806 ;; "@
7807 ;; return\t%0+0\n\tmov\t%2, %Y1
7808 ;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
7809 ;; [(set_attr "type" "multi")
7810 ;; (set_attr "length" "2,3")])
7811
7812 ;; For __builtin_setjmp we need to flush register windows iff the function
7813 ;; calls alloca as well, because otherwise the register window might be
7814 ;; saved after %sp adjustement and thus setjmp would crash
7815 (define_expand "builtin_setjmp_setup"
7816 [(match_operand 0 "register_operand" "r")]
7817 ""
7818 {
7819 emit_insn (gen_do_builtin_setjmp_setup ());
7820 DONE;
7821 })
7822
7823 (define_insn "do_builtin_setjmp_setup"
7824 [(unspec_volatile [(const_int 0)] UNSPECV_SETJMP)]
7825 ""
7826 {
7827 if (! current_function_calls_alloca)
7828 return "";
7829 if (! TARGET_V9 || TARGET_FLAT)
7830 return "\tta\t3\n";
7831 fputs ("\tflushw\n", asm_out_file);
7832 if (flag_pic)
7833 fprintf (asm_out_file, "\tst%c\t%%l7, [%%sp+%d]\n",
7834 TARGET_ARCH64 ? 'x' : 'w',
7835 SPARC_STACK_BIAS + 7 * UNITS_PER_WORD);
7836 fprintf (asm_out_file, "\tst%c\t%%fp, [%%sp+%d]\n",
7837 TARGET_ARCH64 ? 'x' : 'w',
7838 SPARC_STACK_BIAS + 14 * UNITS_PER_WORD);
7839 fprintf (asm_out_file, "\tst%c\t%%i7, [%%sp+%d]\n",
7840 TARGET_ARCH64 ? 'x' : 'w',
7841 SPARC_STACK_BIAS + 15 * UNITS_PER_WORD);
7842 return "";
7843 }
7844 [(set_attr "type" "multi")
7845 (set (attr "length")
7846 (cond [(eq_attr "current_function_calls_alloca" "false")
7847 (const_int 0)
7848 (eq_attr "flat" "true")
7849 (const_int 1)
7850 (eq_attr "isa" "!v9")
7851 (const_int 1)
7852 (eq_attr "pic" "true")
7853 (const_int 4)] (const_int 3)))])
7854
7855 ;; Pattern for use after a setjmp to store FP and the return register
7856 ;; into the stack area.
7857
7858 (define_expand "setjmp"
7859 [(const_int 0)]
7860 ""
7861 {
7862 if (TARGET_ARCH64)
7863 emit_insn (gen_setjmp_64 ());
7864 else
7865 emit_insn (gen_setjmp_32 ());
7866 DONE;
7867 })
7868
7869 (define_expand "setjmp_32"
7870 [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
7871 (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
7872 ""
7873 { operands[0] = frame_pointer_rtx; })
7874
7875 (define_expand "setjmp_64"
7876 [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
7877 (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
7878 ""
7879 { operands[0] = frame_pointer_rtx; })
7880
7881 ;; Special pattern for the FLUSH instruction.
7882
7883 ; We do SImode and DImode versions of this to quiet down genrecog's complaints
7884 ; of the define_insn otherwise missing a mode. We make "flush", aka
7885 ; gen_flush, the default one since sparc_initialize_trampoline uses
7886 ; it on SImode mem values.
7887
7888 (define_insn "flush"
7889 [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
7890 ""
7891 { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
7892 [(set_attr "type" "iflush")])
7893
7894 (define_insn "flushdi"
7895 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
7896 ""
7897 { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
7898 [(set_attr "type" "iflush")])
7899
7900 \f
7901 ;; find first set.
7902
7903 ;; The scan instruction searches from the most significant bit while ffs
7904 ;; searches from the least significant bit. The bit index and treatment of
7905 ;; zero also differ. It takes at least 7 instructions to get the proper
7906 ;; result. Here is an obvious 8 instruction sequence.
7907
7908 ;; XXX
7909 (define_insn "ffssi2"
7910 [(set (match_operand:SI 0 "register_operand" "=&r")
7911 (ffs:SI (match_operand:SI 1 "register_operand" "r")))
7912 (clobber (match_scratch:SI 2 "=&r"))]
7913 "TARGET_SPARCLITE || TARGET_SPARCLET"
7914 {
7915 return "sub\t%%g0, %1, %0\;and\t%0, %1, %0\;scan\t%0, 0, %0\;mov\t32, %2\;sub\t%2, %0, %0\;sra\t%0, 31, %2\;and\t%2, 31, %2\;add\t%2, %0, %0";
7916 }
7917 [(set_attr "type" "multi")
7918 (set_attr "length" "8")])
7919
7920 ;; ??? This should be a define expand, so that the extra instruction have
7921 ;; a chance of being optimized away.
7922
7923 ;; Disabled because none of the UltraSPARCs implement popc. The HAL R1
7924 ;; does, but no one uses that and we don't have a switch for it.
7925 ;
7926 ;(define_insn "ffsdi2"
7927 ; [(set (match_operand:DI 0 "register_operand" "=&r")
7928 ; (ffs:DI (match_operand:DI 1 "register_operand" "r")))
7929 ; (clobber (match_scratch:DI 2 "=&r"))]
7930 ; "TARGET_ARCH64"
7931 ; "neg\t%1, %2\;xnor\t%1, %2, %2\;popc\t%2, %0\;movzr\t%1, 0, %0"
7932 ; [(set_attr "type" "multi")
7933 ; (set_attr "length" "4")])
7934
7935
7936 \f
7937 ;; Peepholes go at the end.
7938
7939 ;; Optimize consecutive loads or stores into ldd and std when possible.
7940 ;; The conditions in which we do this are very restricted and are
7941 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
7942
7943 (define_peephole2
7944 [(set (match_operand:SI 0 "memory_operand" "")
7945 (const_int 0))
7946 (set (match_operand:SI 1 "memory_operand" "")
7947 (const_int 0))]
7948 "TARGET_V9
7949 && mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
7950 [(set (match_dup 0)
7951 (const_int 0))]
7952 "operands[0] = change_address (operands[0], DImode, NULL);")
7953
7954 (define_peephole2
7955 [(set (match_operand:SI 0 "memory_operand" "")
7956 (const_int 0))
7957 (set (match_operand:SI 1 "memory_operand" "")
7958 (const_int 0))]
7959 "TARGET_V9
7960 && mems_ok_for_ldd_peep (operands[1], operands[0], NULL_RTX)"
7961 [(set (match_dup 1)
7962 (const_int 0))]
7963 "operands[1] = change_address (operands[1], DImode, NULL);")
7964
7965 (define_peephole2
7966 [(set (match_operand:SI 0 "register_operand" "")
7967 (match_operand:SI 1 "memory_operand" ""))
7968 (set (match_operand:SI 2 "register_operand" "")
7969 (match_operand:SI 3 "memory_operand" ""))]
7970 "registers_ok_for_ldd_peep (operands[0], operands[2])
7971 && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
7972 [(set (match_dup 0)
7973 (match_dup 1))]
7974 "operands[1] = change_address (operands[1], DImode, NULL);
7975 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));")
7976
7977 (define_peephole2
7978 [(set (match_operand:SI 0 "memory_operand" "")
7979 (match_operand:SI 1 "register_operand" ""))
7980 (set (match_operand:SI 2 "memory_operand" "")
7981 (match_operand:SI 3 "register_operand" ""))]
7982 "registers_ok_for_ldd_peep (operands[1], operands[3])
7983 && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
7984 [(set (match_dup 0)
7985 (match_dup 1))]
7986 "operands[0] = change_address (operands[0], DImode, NULL);
7987 operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));")
7988
7989 (define_peephole2
7990 [(set (match_operand:SF 0 "register_operand" "")
7991 (match_operand:SF 1 "memory_operand" ""))
7992 (set (match_operand:SF 2 "register_operand" "")
7993 (match_operand:SF 3 "memory_operand" ""))]
7994 "registers_ok_for_ldd_peep (operands[0], operands[2])
7995 && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
7996 [(set (match_dup 0)
7997 (match_dup 1))]
7998 "operands[1] = change_address (operands[1], DFmode, NULL);
7999 operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));")
8000
8001 (define_peephole2
8002 [(set (match_operand:SF 0 "memory_operand" "")
8003 (match_operand:SF 1 "register_operand" ""))
8004 (set (match_operand:SF 2 "memory_operand" "")
8005 (match_operand:SF 3 "register_operand" ""))]
8006 "registers_ok_for_ldd_peep (operands[1], operands[3])
8007 && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
8008 [(set (match_dup 0)
8009 (match_dup 1))]
8010 "operands[0] = change_address (operands[0], DFmode, NULL);
8011 operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));")
8012
8013 (define_peephole2
8014 [(set (match_operand:SI 0 "register_operand" "")
8015 (match_operand:SI 1 "memory_operand" ""))
8016 (set (match_operand:SI 2 "register_operand" "")
8017 (match_operand:SI 3 "memory_operand" ""))]
8018 "registers_ok_for_ldd_peep (operands[2], operands[0])
8019 && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
8020 [(set (match_dup 2)
8021 (match_dup 3))]
8022 "operands[3] = change_address (operands[3], DImode, NULL);
8023 operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));")
8024
8025 (define_peephole2
8026 [(set (match_operand:SI 0 "memory_operand" "")
8027 (match_operand:SI 1 "register_operand" ""))
8028 (set (match_operand:SI 2 "memory_operand" "")
8029 (match_operand:SI 3 "register_operand" ""))]
8030 "registers_ok_for_ldd_peep (operands[3], operands[1])
8031 && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
8032 [(set (match_dup 2)
8033 (match_dup 3))]
8034 "operands[2] = change_address (operands[2], DImode, NULL);
8035 operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
8036 ")
8037
8038 (define_peephole2
8039 [(set (match_operand:SF 0 "register_operand" "")
8040 (match_operand:SF 1 "memory_operand" ""))
8041 (set (match_operand:SF 2 "register_operand" "")
8042 (match_operand:SF 3 "memory_operand" ""))]
8043 "registers_ok_for_ldd_peep (operands[2], operands[0])
8044 && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
8045 [(set (match_dup 2)
8046 (match_dup 3))]
8047 "operands[3] = change_address (operands[3], DFmode, NULL);
8048 operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));")
8049
8050 (define_peephole2
8051 [(set (match_operand:SF 0 "memory_operand" "")
8052 (match_operand:SF 1 "register_operand" ""))
8053 (set (match_operand:SF 2 "memory_operand" "")
8054 (match_operand:SF 3 "register_operand" ""))]
8055 "registers_ok_for_ldd_peep (operands[3], operands[1])
8056 && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
8057 [(set (match_dup 2)
8058 (match_dup 3))]
8059 "operands[2] = change_address (operands[2], DFmode, NULL);
8060 operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));")
8061
8062 ;; Optimize the case of following a reg-reg move with a test
8063 ;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
8064 ;; This can result from a float to fix conversion.
8065
8066 (define_peephole2
8067 [(set (match_operand:SI 0 "register_operand" "")
8068 (match_operand:SI 1 "register_operand" ""))
8069 (set (reg:CC 100)
8070 (compare:CC (match_operand:SI 2 "register_operand" "")
8071 (const_int 0)))]
8072 "(rtx_equal_p (operands[2], operands[0])
8073 || rtx_equal_p (operands[2], operands[1]))
8074 && ! SPARC_FP_REG_P (REGNO (operands[0]))
8075 && ! SPARC_FP_REG_P (REGNO (operands[1]))"
8076 [(parallel [(set (match_dup 0) (match_dup 1))
8077 (set (reg:CC 100)
8078 (compare:CC (match_dup 1) (const_int 0)))])]
8079 "")
8080
8081 (define_peephole2
8082 [(set (match_operand:DI 0 "register_operand" "")
8083 (match_operand:DI 1 "register_operand" ""))
8084 (set (reg:CCX 100)
8085 (compare:CCX (match_operand:DI 2 "register_operand" "")
8086 (const_int 0)))]
8087 "TARGET_ARCH64
8088 && (rtx_equal_p (operands[2], operands[0])
8089 || rtx_equal_p (operands[2], operands[1]))
8090 && ! SPARC_FP_REG_P (REGNO (operands[0]))
8091 && ! SPARC_FP_REG_P (REGNO (operands[1]))"
8092 [(parallel [(set (match_dup 0) (match_dup 1))
8093 (set (reg:CCX 100)
8094 (compare:CCX (match_dup 1) (const_int 0)))])]
8095 "")
8096
8097 ;; Return peepholes. These are generated by sparc_nonflat_function_epilogue
8098 ;; who then immediately calls final_scan_insn.
8099
8100 (define_insn "*return_qi"
8101 [(set (match_operand:QI 0 "restore_operand" "")
8102 (match_operand:QI 1 "arith_operand" "rI"))
8103 (return)]
8104 "sparc_emitting_epilogue"
8105 {
8106 if (! TARGET_ARCH64 && current_function_returns_struct)
8107 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8108 else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8109 || IN_OR_GLOBAL_P (operands[1])))
8110 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8111 else
8112 return "ret\n\trestore %%g0, %1, %Y0";
8113 }
8114 [(set_attr "type" "multi")
8115 (set_attr "length" "2")])
8116
8117 (define_insn "*return_hi"
8118 [(set (match_operand:HI 0 "restore_operand" "")
8119 (match_operand:HI 1 "arith_operand" "rI"))
8120 (return)]
8121 "sparc_emitting_epilogue"
8122 {
8123 if (! TARGET_ARCH64 && current_function_returns_struct)
8124 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8125 else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8126 || IN_OR_GLOBAL_P (operands[1])))
8127 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8128 else
8129 return "ret\;restore %%g0, %1, %Y0";
8130 }
8131 [(set_attr "type" "multi")
8132 (set_attr "length" "2")])
8133
8134 (define_insn "*return_si"
8135 [(set (match_operand:SI 0 "restore_operand" "")
8136 (match_operand:SI 1 "arith_operand" "rI"))
8137 (return)]
8138 "sparc_emitting_epilogue"
8139 {
8140 if (! TARGET_ARCH64 && current_function_returns_struct)
8141 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8142 else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8143 || IN_OR_GLOBAL_P (operands[1])))
8144 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8145 else
8146 return "ret\;restore %%g0, %1, %Y0";
8147 }
8148 [(set_attr "type" "multi")
8149 (set_attr "length" "2")])
8150
8151 (define_insn "*return_sf_no_fpu"
8152 [(set (match_operand:SF 0 "restore_operand" "=r")
8153 (match_operand:SF 1 "register_operand" "r"))
8154 (return)]
8155 "sparc_emitting_epilogue"
8156 {
8157 if (! TARGET_ARCH64 && current_function_returns_struct)
8158 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8159 else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
8160 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8161 else
8162 return "ret\;restore %%g0, %1, %Y0";
8163 }
8164 [(set_attr "type" "multi")
8165 (set_attr "length" "2")])
8166
8167 (define_insn "*return_df_no_fpu"
8168 [(set (match_operand:DF 0 "restore_operand" "=r")
8169 (match_operand:DF 1 "register_operand" "r"))
8170 (return)]
8171 "sparc_emitting_epilogue && TARGET_ARCH64"
8172 {
8173 if (IN_OR_GLOBAL_P (operands[1]))
8174 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8175 else
8176 return "ret\;restore %%g0, %1, %Y0";
8177 }
8178 [(set_attr "type" "multi")
8179 (set_attr "length" "2")])
8180
8181 (define_insn "*return_addsi"
8182 [(set (match_operand:SI 0 "restore_operand" "")
8183 (plus:SI (match_operand:SI 1 "register_operand" "r")
8184 (match_operand:SI 2 "arith_operand" "rI")))
8185 (return)]
8186 "sparc_emitting_epilogue"
8187 {
8188 if (! TARGET_ARCH64 && current_function_returns_struct)
8189 return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
8190 /* If operands are global or in registers, can use return */
8191 else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
8192 && (GET_CODE (operands[2]) == CONST_INT
8193 || IN_OR_GLOBAL_P (operands[2])))
8194 return "return\t%%i7+8\n\tadd\t%Y1, %Y2, %Y0";
8195 else
8196 return "ret\;restore %r1, %2, %Y0";
8197 }
8198 [(set_attr "type" "multi")
8199 (set_attr "length" "2")])
8200
8201 (define_insn "*return_losum_si"
8202 [(set (match_operand:SI 0 "restore_operand" "")
8203 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
8204 (match_operand:SI 2 "immediate_operand" "in")))
8205 (return)]
8206 "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
8207 {
8208 if (! TARGET_ARCH64 && current_function_returns_struct)
8209 return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
8210 /* If operands are global or in registers, can use return */
8211 else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
8212 return "return\t%%i7+8\n\tor\t%Y1, %%lo(%a2), %Y0";
8213 else
8214 return "ret\;restore %r1, %%lo(%a2), %Y0";
8215 }
8216 [(set_attr "type" "multi")
8217 (set_attr "length" "2")])
8218
8219 (define_insn "*return_di"
8220 [(set (match_operand:DI 0 "restore_operand" "")
8221 (match_operand:DI 1 "arith_double_operand" "rHI"))
8222 (return)]
8223 "sparc_emitting_epilogue && TARGET_ARCH64"
8224 "ret\;restore %%g0, %1, %Y0"
8225 [(set_attr "type" "multi")
8226 (set_attr "length" "2")])
8227
8228 (define_insn "*return_adddi"
8229 [(set (match_operand:DI 0 "restore_operand" "")
8230 (plus:DI (match_operand:DI 1 "arith_operand" "%r")
8231 (match_operand:DI 2 "arith_double_operand" "rHI")))
8232 (return)]
8233 "sparc_emitting_epilogue && TARGET_ARCH64"
8234 "ret\;restore %r1, %2, %Y0"
8235 [(set_attr "type" "multi")
8236 (set_attr "length" "2")])
8237
8238 (define_insn "*return_losum_di"
8239 [(set (match_operand:DI 0 "restore_operand" "")
8240 (lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
8241 (match_operand:DI 2 "immediate_operand" "in")))
8242 (return)]
8243 "sparc_emitting_epilogue && TARGET_ARCH64 && ! TARGET_CM_MEDMID"
8244 "ret\;restore %r1, %%lo(%a2), %Y0"
8245 [(set_attr "type" "multi")
8246 (set_attr "length" "2")])
8247
8248 (define_insn "*return_sf"
8249 [(set (reg:SF 32)
8250 (match_operand:SF 0 "register_operand" "f"))
8251 (return)]
8252 "sparc_emitting_epilogue"
8253 "ret\;fmovs\t%0, %%f0"
8254 [(set_attr "type" "multi")
8255 (set_attr "length" "2")])
8256
8257 ;; Now peepholes to do a call followed by a jump.
8258
8259 (define_peephole
8260 [(parallel [(set (match_operand 0 "" "")
8261 (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
8262 (match_operand 2 "" "")))
8263 (clobber (reg:SI 15))])
8264 (set (pc) (label_ref (match_operand 3 "" "")))]
8265 "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
8266 && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
8267 && sparc_cpu != PROCESSOR_ULTRASPARC
8268 && sparc_cpu != PROCESSOR_ULTRASPARC3"
8269 "call\t%a1, %2\n\tadd\t%%o7, (%l3-.-4), %%o7")
8270
8271 (define_peephole
8272 [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
8273 (match_operand 1 "" ""))
8274 (clobber (reg:SI 15))])
8275 (set (pc) (label_ref (match_operand 2 "" "")))]
8276 "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
8277 && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
8278 && sparc_cpu != PROCESSOR_ULTRASPARC
8279 && sparc_cpu != PROCESSOR_ULTRASPARC3"
8280 "call\t%a0, %1\n\tadd\t%%o7, (%l2-.-4), %%o7")
8281
8282 ;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
8283 ;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
8284 ;; ??? operations. With DFA we might be able to model this, but it requires a lot of
8285 ;; ??? state.
8286 (define_expand "prefetch"
8287 [(match_operand 0 "address_operand" "")
8288 (match_operand 1 "const_int_operand" "")
8289 (match_operand 2 "const_int_operand" "")]
8290 "TARGET_V9"
8291 {
8292 if (TARGET_ARCH64)
8293 emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
8294 else
8295 emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
8296 DONE;
8297 })
8298
8299 (define_insn "prefetch_64"
8300 [(prefetch (match_operand:DI 0 "address_operand" "p")
8301 (match_operand:DI 1 "const_int_operand" "n")
8302 (match_operand:DI 2 "const_int_operand" "n"))]
8303 ""
8304 {
8305 static const char * const prefetch_instr[2][2] = {
8306 {
8307 "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
8308 "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
8309 },
8310 {
8311 "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
8312 "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
8313 }
8314 };
8315 int read_or_write = INTVAL (operands[1]);
8316 int locality = INTVAL (operands[2]);
8317
8318 if (read_or_write != 0 && read_or_write != 1)
8319 abort ();
8320 if (locality < 0 || locality > 3)
8321 abort ();
8322 return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
8323 }
8324 [(set_attr "type" "load")])
8325
8326 (define_insn "prefetch_32"
8327 [(prefetch (match_operand:SI 0 "address_operand" "p")
8328 (match_operand:SI 1 "const_int_operand" "n")
8329 (match_operand:SI 2 "const_int_operand" "n"))]
8330 ""
8331 {
8332 static const char * const prefetch_instr[2][2] = {
8333 {
8334 "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
8335 "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
8336 },
8337 {
8338 "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
8339 "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
8340 }
8341 };
8342 int read_or_write = INTVAL (operands[1]);
8343 int locality = INTVAL (operands[2]);
8344
8345 if (read_or_write != 0 && read_or_write != 1)
8346 abort ();
8347 if (locality < 0 || locality > 3)
8348 abort ();
8349 return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
8350 }
8351 [(set_attr "type" "load")])
8352 \f
8353 (define_expand "prologue"
8354 [(const_int 1)]
8355 "flag_pic && current_function_uses_pic_offset_table"
8356 {
8357 load_pic_register ();
8358 DONE;
8359 })
8360
8361 ;; We need to reload %l7 for -mflat -fpic,
8362 ;; otherwise %l7 should be preserved simply
8363 ;; by loading the function's register window
8364 (define_expand "exception_receiver"
8365 [(const_int 0)]
8366 "TARGET_FLAT && flag_pic"
8367 {
8368 load_pic_register ();
8369 DONE;
8370 })
8371
8372 ;; Likewise
8373 (define_expand "builtin_setjmp_receiver"
8374 [(label_ref (match_operand 0 "" ""))]
8375 "TARGET_FLAT && flag_pic"
8376 {
8377 load_pic_register ();
8378 DONE;
8379 })
8380 \f
8381 (define_insn "trap"
8382 [(trap_if (const_int 1) (const_int 5))]
8383 ""
8384 "ta\t5"
8385 [(set_attr "type" "trap")])
8386
8387 (define_expand "conditional_trap"
8388 [(trap_if (match_operator 0 "noov_compare_op"
8389 [(match_dup 2) (match_dup 3)])
8390 (match_operand:SI 1 "arith_operand" ""))]
8391 ""
8392 "operands[2] = gen_compare_reg (GET_CODE (operands[0]),
8393 sparc_compare_op0, sparc_compare_op1);
8394 operands[3] = const0_rtx;")
8395
8396 (define_insn ""
8397 [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
8398 (match_operand:SI 1 "arith_operand" "rM"))]
8399 ""
8400 "t%C0\t%1"
8401 [(set_attr "type" "trap")])
8402
8403 (define_insn ""
8404 [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
8405 (match_operand:SI 1 "arith_operand" "rM"))]
8406 "TARGET_V9"
8407 "t%C0\t%%xcc, %1"
8408 [(set_attr "type" "trap")])