cypress.md: Replace Sparc with SPARC.
[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 !arch64.
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")
2066 (match_operand:DI 1 "input_operand"
2067 " J,J,U,T,r,o,i,r, f, T, o, f, f"))]
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 [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
2085 (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2")])
2086
2087 (define_insn "*movdi_insn_sp32"
2088 [(set (match_operand:DI 0 "nonimmediate_operand"
2089 "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
2090 (match_operand:DI 1 "input_operand"
2091 " J,U,T,r,o,i,r, f, T, o, f, f"))]
2092 "! TARGET_ARCH64
2093 && (register_operand (operands[0], DImode)
2094 || register_operand (operands[1], DImode))"
2095 "@
2096 #
2097 std\t%1, %0
2098 ldd\t%1, %0
2099 #
2100 #
2101 #
2102 #
2103 std\t%1, %0
2104 ldd\t%1, %0
2105 #
2106 #
2107 #"
2108 [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
2109 (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
2110
2111 ;; The following are generated by sparc_emit_set_const64
2112 (define_insn "*movdi_sp64_dbl"
2113 [(set (match_operand:DI 0 "register_operand" "=r")
2114 (match_operand:DI 1 "const64_operand" ""))]
2115 "(TARGET_ARCH64
2116 && HOST_BITS_PER_WIDE_INT != 64)"
2117 "mov\t%1, %0")
2118
2119 ;; This is needed to show CSE exactly which bits are set
2120 ;; in a 64-bit register by sethi instructions.
2121 (define_insn "*movdi_const64_special"
2122 [(set (match_operand:DI 0 "register_operand" "=r")
2123 (match_operand:DI 1 "const64_high_operand" ""))]
2124 "TARGET_ARCH64"
2125 "sethi\t%%hi(%a1), %0")
2126
2127 (define_insn "*movdi_insn_sp64_novis"
2128 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
2129 (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e"))]
2130 "TARGET_ARCH64 && ! TARGET_VIS
2131 && (register_operand (operands[0], DImode)
2132 || reg_or_0_operand (operands[1], DImode))"
2133 "@
2134 mov\t%1, %0
2135 sethi\t%%hi(%a1), %0
2136 clr\t%0
2137 ldx\t%1, %0
2138 stx\t%r1, %0
2139 fmovd\t%1, %0
2140 ldd\t%1, %0
2141 std\t%1, %0"
2142 [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore")
2143 (set_attr "fptype" "*,*,*,*,*,double,*,*")])
2144
2145 (define_insn "*movdi_insn_sp64_vis"
2146 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b")
2147 (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e,J"))]
2148 "TARGET_ARCH64 && TARGET_VIS &&
2149 (register_operand (operands[0], DImode)
2150 || reg_or_0_operand (operands[1], DImode))"
2151 "@
2152 mov\t%1, %0
2153 sethi\t%%hi(%a1), %0
2154 clr\t%0
2155 ldx\t%1, %0
2156 stx\t%r1, %0
2157 fmovd\t%1, %0
2158 ldd\t%1, %0
2159 std\t%1, %0
2160 fzero\t%0"
2161 [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fpmove")
2162 (set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
2163
2164 (define_expand "movdi_pic_label_ref"
2165 [(set (match_dup 3) (high:DI
2166 (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2167 (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
2168 (set (match_dup 4) (lo_sum:DI (match_dup 3)
2169 (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
2170 (set (match_operand:DI 0 "register_operand" "=r")
2171 (minus:DI (match_dup 5) (match_dup 4)))]
2172 "TARGET_ARCH64 && flag_pic"
2173 {
2174 current_function_uses_pic_offset_table = 1;
2175 operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
2176 if (no_new_pseudos)
2177 {
2178 operands[3] = operands[0];
2179 operands[4] = operands[0];
2180 }
2181 else
2182 {
2183 operands[3] = gen_reg_rtx (DImode);
2184 operands[4] = gen_reg_rtx (DImode);
2185 }
2186 operands[5] = pic_offset_table_rtx;
2187 })
2188
2189 (define_insn "*movdi_high_pic_label_ref"
2190 [(set (match_operand:DI 0 "register_operand" "=r")
2191 (high:DI
2192 (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2193 (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2194 "TARGET_ARCH64 && flag_pic"
2195 "sethi\t%%hi(%a2-(%a1-.)), %0")
2196
2197 (define_insn "*movdi_lo_sum_pic_label_ref"
2198 [(set (match_operand:DI 0 "register_operand" "=r")
2199 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2200 (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
2201 (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2202 "TARGET_ARCH64 && flag_pic"
2203 "or\t%1, %%lo(%a3-(%a2-.)), %0")
2204
2205 ;; SPARC-v9 code model support insns. See sparc_emit_set_symbolic_const64
2206 ;; in sparc.c to see what is going on here... PIC stuff comes first.
2207
2208 (define_insn "movdi_lo_sum_pic"
2209 [(set (match_operand:DI 0 "register_operand" "=r")
2210 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2211 (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
2212 "TARGET_ARCH64 && flag_pic"
2213 "or\t%1, %%lo(%a2), %0")
2214
2215 (define_insn "movdi_high_pic"
2216 [(set (match_operand:DI 0 "register_operand" "=r")
2217 (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
2218 "TARGET_ARCH64 && flag_pic && check_pic (1)"
2219 "sethi\t%%hi(%a1), %0")
2220
2221 (define_insn "*sethi_di_medlow_embmedany_pic"
2222 [(set (match_operand:DI 0 "register_operand" "=r")
2223 (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
2224 "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
2225 "sethi\t%%hi(%a1), %0")
2226
2227 (define_insn "*sethi_di_medlow"
2228 [(set (match_operand:DI 0 "register_operand" "=r")
2229 (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
2230 "TARGET_CM_MEDLOW && check_pic (1)"
2231 "sethi\t%%hi(%a1), %0")
2232
2233 (define_insn "*losum_di_medlow"
2234 [(set (match_operand:DI 0 "register_operand" "=r")
2235 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2236 (match_operand:DI 2 "symbolic_operand" "")))]
2237 "TARGET_CM_MEDLOW"
2238 "or\t%1, %%lo(%a2), %0")
2239
2240 (define_insn "seth44"
2241 [(set (match_operand:DI 0 "register_operand" "=r")
2242 (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
2243 "TARGET_CM_MEDMID"
2244 "sethi\t%%h44(%a1), %0")
2245
2246 (define_insn "setm44"
2247 [(set (match_operand:DI 0 "register_operand" "=r")
2248 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2249 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
2250 "TARGET_CM_MEDMID"
2251 "or\t%1, %%m44(%a2), %0")
2252
2253 (define_insn "setl44"
2254 [(set (match_operand:DI 0 "register_operand" "=r")
2255 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2256 (match_operand:DI 2 "symbolic_operand" "")))]
2257 "TARGET_CM_MEDMID"
2258 "or\t%1, %%l44(%a2), %0")
2259
2260 (define_insn "sethh"
2261 [(set (match_operand:DI 0 "register_operand" "=r")
2262 (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
2263 "TARGET_CM_MEDANY"
2264 "sethi\t%%hh(%a1), %0")
2265
2266 (define_insn "setlm"
2267 [(set (match_operand:DI 0 "register_operand" "=r")
2268 (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
2269 "TARGET_CM_MEDANY"
2270 "sethi\t%%lm(%a1), %0")
2271
2272 (define_insn "sethm"
2273 [(set (match_operand:DI 0 "register_operand" "=r")
2274 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2275 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
2276 "TARGET_CM_MEDANY"
2277 "or\t%1, %%hm(%a2), %0")
2278
2279 (define_insn "setlo"
2280 [(set (match_operand:DI 0 "register_operand" "=r")
2281 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2282 (match_operand:DI 2 "symbolic_operand" "")))]
2283 "TARGET_CM_MEDANY"
2284 "or\t%1, %%lo(%a2), %0")
2285
2286 (define_insn "embmedany_sethi"
2287 [(set (match_operand:DI 0 "register_operand" "=r")
2288 (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
2289 "TARGET_CM_EMBMEDANY && check_pic (1)"
2290 "sethi\t%%hi(%a1), %0")
2291
2292 (define_insn "embmedany_losum"
2293 [(set (match_operand:DI 0 "register_operand" "=r")
2294 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2295 (match_operand:DI 2 "data_segment_operand" "")))]
2296 "TARGET_CM_EMBMEDANY"
2297 "add\t%1, %%lo(%a2), %0")
2298
2299 (define_insn "embmedany_brsum"
2300 [(set (match_operand:DI 0 "register_operand" "=r")
2301 (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
2302 "TARGET_CM_EMBMEDANY"
2303 "add\t%1, %_, %0")
2304
2305 (define_insn "embmedany_textuhi"
2306 [(set (match_operand:DI 0 "register_operand" "=r")
2307 (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
2308 "TARGET_CM_EMBMEDANY && check_pic (1)"
2309 "sethi\t%%uhi(%a1), %0")
2310
2311 (define_insn "embmedany_texthi"
2312 [(set (match_operand:DI 0 "register_operand" "=r")
2313 (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
2314 "TARGET_CM_EMBMEDANY && check_pic (1)"
2315 "sethi\t%%hi(%a1), %0")
2316
2317 (define_insn "embmedany_textulo"
2318 [(set (match_operand:DI 0 "register_operand" "=r")
2319 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2320 (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
2321 "TARGET_CM_EMBMEDANY"
2322 "or\t%1, %%ulo(%a2), %0")
2323
2324 (define_insn "embmedany_textlo"
2325 [(set (match_operand:DI 0 "register_operand" "=r")
2326 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2327 (match_operand:DI 2 "text_segment_operand" "")))]
2328 "TARGET_CM_EMBMEDANY"
2329 "or\t%1, %%lo(%a2), %0")
2330
2331 ;; Now some patterns to help reload out a bit.
2332 (define_expand "reload_indi"
2333 [(parallel [(match_operand:DI 0 "register_operand" "=r")
2334 (match_operand:DI 1 "immediate_operand" "")
2335 (match_operand:TI 2 "register_operand" "=&r")])]
2336 "(TARGET_CM_MEDANY
2337 || TARGET_CM_EMBMEDANY)
2338 && ! flag_pic"
2339 {
2340 sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2341 DONE;
2342 })
2343
2344 (define_expand "reload_outdi"
2345 [(parallel [(match_operand:DI 0 "register_operand" "=r")
2346 (match_operand:DI 1 "immediate_operand" "")
2347 (match_operand:TI 2 "register_operand" "=&r")])]
2348 "(TARGET_CM_MEDANY
2349 || TARGET_CM_EMBMEDANY)
2350 && ! flag_pic"
2351 {
2352 sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2353 DONE;
2354 })
2355
2356 ;; Split up putting CONSTs and REGs into DI regs when !arch64
2357 (define_split
2358 [(set (match_operand:DI 0 "register_operand" "")
2359 (match_operand:DI 1 "const_int_operand" ""))]
2360 "! TARGET_ARCH64 && reload_completed"
2361 [(clobber (const_int 0))]
2362 {
2363 #if HOST_BITS_PER_WIDE_INT == 32
2364 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2365 (INTVAL (operands[1]) < 0) ?
2366 constm1_rtx :
2367 const0_rtx));
2368 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2369 operands[1]));
2370 #else
2371 unsigned int low, high;
2372
2373 low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
2374 high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
2375 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
2376
2377 /* Slick... but this trick loses if this subreg constant part
2378 can be done in one insn. */
2379 if (low == high && (low & 0x3ff) != 0 && low + 0x1000 >= 0x2000)
2380 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2381 gen_highpart (SImode, operands[0])));
2382 else
2383 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
2384 #endif
2385 DONE;
2386 })
2387
2388 (define_split
2389 [(set (match_operand:DI 0 "register_operand" "")
2390 (match_operand:DI 1 "const_double_operand" ""))]
2391 "! TARGET_ARCH64 && reload_completed"
2392 [(clobber (const_int 0))]
2393 {
2394 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2395 GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
2396
2397 /* Slick... but this trick loses if this subreg constant part
2398 can be done in one insn. */
2399 if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
2400 && !(SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
2401 || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
2402 {
2403 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2404 gen_highpart (SImode, operands[0])));
2405 }
2406 else
2407 {
2408 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2409 GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
2410 }
2411 DONE;
2412 })
2413
2414 (define_split
2415 [(set (match_operand:DI 0 "register_operand" "")
2416 (match_operand:DI 1 "register_operand" ""))]
2417 "! TARGET_ARCH64 && reload_completed"
2418 [(clobber (const_int 0))]
2419 {
2420 rtx set_dest = operands[0];
2421 rtx set_src = operands[1];
2422 rtx dest1, dest2;
2423 rtx src1, src2;
2424
2425 dest1 = gen_highpart (SImode, set_dest);
2426 dest2 = gen_lowpart (SImode, set_dest);
2427 src1 = gen_highpart (SImode, set_src);
2428 src2 = gen_lowpart (SImode, set_src);
2429
2430 /* Now emit using the real source and destination we found, swapping
2431 the order if we detect overlap. */
2432 if (reg_overlap_mentioned_p (dest1, src2))
2433 {
2434 emit_insn (gen_movsi (dest2, src2));
2435 emit_insn (gen_movsi (dest1, src1));
2436 }
2437 else
2438 {
2439 emit_insn (gen_movsi (dest1, src1));
2440 emit_insn (gen_movsi (dest2, src2));
2441 }
2442 DONE;
2443 })
2444
2445 ;; Now handle the cases of memory moves from/to non-even
2446 ;; DI mode register pairs.
2447 (define_split
2448 [(set (match_operand:DI 0 "register_operand" "")
2449 (match_operand:DI 1 "memory_operand" ""))]
2450 "(! TARGET_ARCH64
2451 && reload_completed
2452 && sparc_splitdi_legitimate (operands[0], operands[1]))"
2453 [(clobber (const_int 0))]
2454 {
2455 rtx word0 = adjust_address (operands[1], SImode, 0);
2456 rtx word1 = adjust_address (operands[1], SImode, 4);
2457 rtx high_part = gen_highpart (SImode, operands[0]);
2458 rtx low_part = gen_lowpart (SImode, operands[0]);
2459
2460 if (reg_overlap_mentioned_p (high_part, word1))
2461 {
2462 emit_insn (gen_movsi (low_part, word1));
2463 emit_insn (gen_movsi (high_part, word0));
2464 }
2465 else
2466 {
2467 emit_insn (gen_movsi (high_part, word0));
2468 emit_insn (gen_movsi (low_part, word1));
2469 }
2470 DONE;
2471 })
2472
2473 (define_split
2474 [(set (match_operand:DI 0 "memory_operand" "")
2475 (match_operand:DI 1 "register_operand" ""))]
2476 "(! TARGET_ARCH64
2477 && reload_completed
2478 && sparc_splitdi_legitimate (operands[1], operands[0]))"
2479 [(clobber (const_int 0))]
2480 {
2481 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
2482 gen_highpart (SImode, operands[1])));
2483 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
2484 gen_lowpart (SImode, operands[1])));
2485 DONE;
2486 })
2487
2488 (define_split
2489 [(set (match_operand:DI 0 "memory_operand" "")
2490 (const_int 0))]
2491 "reload_completed
2492 && (! TARGET_V9
2493 || (! TARGET_ARCH64
2494 && ! mem_min_alignment (operands[0], 8)))
2495 && offsettable_memref_p (operands[0])"
2496 [(clobber (const_int 0))]
2497 {
2498 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
2499 emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
2500 DONE;
2501 })
2502 \f
2503 ;; Floating point move insns
2504
2505 (define_insn "*movsf_insn_novis"
2506 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
2507 (match_operand:SF 1 "input_operand" "f,G,Q,*rR,S,m,m,f,*rG"))]
2508 "(TARGET_FPU && ! TARGET_VIS)
2509 && (register_operand (operands[0], SFmode)
2510 || register_operand (operands[1], SFmode)
2511 || fp_zero_operand (operands[1], SFmode))"
2512 {
2513 if (GET_CODE (operands[1]) == CONST_DOUBLE
2514 && (which_alternative == 2
2515 || which_alternative == 3
2516 || which_alternative == 4))
2517 {
2518 REAL_VALUE_TYPE r;
2519 long i;
2520
2521 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2522 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2523 operands[1] = GEN_INT (i);
2524 }
2525
2526 switch (which_alternative)
2527 {
2528 case 0:
2529 return "fmovs\t%1, %0";
2530 case 1:
2531 return "clr\t%0";
2532 case 2:
2533 return "sethi\t%%hi(%a1), %0";
2534 case 3:
2535 return "mov\t%1, %0";
2536 case 4:
2537 return "#";
2538 case 5:
2539 case 6:
2540 return "ld\t%1, %0";
2541 case 7:
2542 case 8:
2543 return "st\t%r1, %0";
2544 default:
2545 abort();
2546 }
2547 }
2548 [(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")])
2549
2550 (define_insn "*movsf_insn_vis"
2551 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
2552 (match_operand:SF 1 "input_operand" "f,G,G,Q,*rR,S,m,m,f,*rG"))]
2553 "(TARGET_FPU && TARGET_VIS)
2554 && (register_operand (operands[0], SFmode)
2555 || register_operand (operands[1], SFmode)
2556 || fp_zero_operand (operands[1], SFmode))"
2557 {
2558 if (GET_CODE (operands[1]) == CONST_DOUBLE
2559 && (which_alternative == 3
2560 || which_alternative == 4
2561 || which_alternative == 5))
2562 {
2563 REAL_VALUE_TYPE r;
2564 long i;
2565
2566 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2567 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2568 operands[1] = GEN_INT (i);
2569 }
2570
2571 switch (which_alternative)
2572 {
2573 case 0:
2574 return "fmovs\t%1, %0";
2575 case 1:
2576 return "fzeros\t%0";
2577 case 2:
2578 return "clr\t%0";
2579 case 3:
2580 return "sethi\t%%hi(%a1), %0";
2581 case 4:
2582 return "mov\t%1, %0";
2583 case 5:
2584 return "#";
2585 case 6:
2586 case 7:
2587 return "ld\t%1, %0";
2588 case 8:
2589 case 9:
2590 return "st\t%r1, %0";
2591 default:
2592 abort();
2593 }
2594 }
2595 [(set_attr "type" "fpmove,fpmove,*,*,*,*,load,fpload,fpstore,store")])
2596
2597 ;; Exactly the same as above, except that all `f' cases are deleted.
2598 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2599 ;; when -mno-fpu.
2600
2601 (define_insn "*movsf_no_f_insn"
2602 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,r,m")
2603 (match_operand:SF 1 "input_operand" "G,Q,rR,S,m,rG"))]
2604 "! TARGET_FPU
2605 && (register_operand (operands[0], SFmode)
2606 || register_operand (operands[1], SFmode)
2607 || fp_zero_operand (operands[1], SFmode))"
2608 {
2609 if (GET_CODE (operands[1]) == CONST_DOUBLE
2610 && (which_alternative == 1
2611 || which_alternative == 2
2612 || which_alternative == 3))
2613 {
2614 REAL_VALUE_TYPE r;
2615 long i;
2616
2617 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2618 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2619 operands[1] = GEN_INT (i);
2620 }
2621
2622 switch (which_alternative)
2623 {
2624 case 0:
2625 return "clr\t%0";
2626 case 1:
2627 return "sethi\t%%hi(%a1), %0";
2628 case 2:
2629 return "mov\t%1, %0";
2630 case 3:
2631 return "#";
2632 case 4:
2633 return "ld\t%1, %0";
2634 case 5:
2635 return "st\t%r1, %0";
2636 default:
2637 abort();
2638 }
2639 }
2640 [(set_attr "type" "*,*,*,*,load,store")])
2641
2642 (define_insn "*movsf_lo_sum"
2643 [(set (match_operand:SF 0 "register_operand" "=r")
2644 (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
2645 (match_operand:SF 2 "const_double_operand" "S")))]
2646 "fp_high_losum_p (operands[2])"
2647 {
2648 REAL_VALUE_TYPE r;
2649 long i;
2650
2651 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
2652 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2653 operands[2] = GEN_INT (i);
2654 return "or\t%1, %%lo(%a2), %0";
2655 })
2656
2657 (define_insn "*movsf_high"
2658 [(set (match_operand:SF 0 "register_operand" "=r")
2659 (high:SF (match_operand:SF 1 "const_double_operand" "S")))]
2660 "fp_high_losum_p (operands[1])"
2661 {
2662 REAL_VALUE_TYPE r;
2663 long i;
2664
2665 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2666 REAL_VALUE_TO_TARGET_SINGLE (r, i);
2667 operands[1] = GEN_INT (i);
2668 return "sethi\t%%hi(%1), %0";
2669 })
2670
2671 (define_split
2672 [(set (match_operand:SF 0 "register_operand" "")
2673 (match_operand:SF 1 "const_double_operand" ""))]
2674 "fp_high_losum_p (operands[1])
2675 && (GET_CODE (operands[0]) == REG
2676 && REGNO (operands[0]) < 32)"
2677 [(set (match_dup 0) (high:SF (match_dup 1)))
2678 (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
2679
2680 (define_expand "movsf"
2681 [(set (match_operand:SF 0 "general_operand" "")
2682 (match_operand:SF 1 "general_operand" ""))]
2683 ""
2684 {
2685 /* Force SFmode constants into memory. */
2686 if (GET_CODE (operands[0]) == REG
2687 && CONSTANT_P (operands[1]))
2688 {
2689 /* emit_group_store will send such bogosity to us when it is
2690 not storing directly into memory. So fix this up to avoid
2691 crashes in output_constant_pool. */
2692 if (operands [1] == const0_rtx)
2693 operands[1] = CONST0_RTX (SFmode);
2694
2695 if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
2696 goto movsf_is_ok;
2697
2698 /* We are able to build any SF constant in integer registers
2699 with at most 2 instructions. */
2700 if (REGNO (operands[0]) < 32)
2701 goto movsf_is_ok;
2702
2703 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2704 operands[1]));
2705 }
2706
2707 /* Handle sets of MEM first. */
2708 if (GET_CODE (operands[0]) == MEM)
2709 {
2710 if (register_operand (operands[1], SFmode)
2711 || fp_zero_operand (operands[1], SFmode))
2712 goto movsf_is_ok;
2713
2714 if (! reload_in_progress)
2715 {
2716 operands[0] = validize_mem (operands[0]);
2717 operands[1] = force_reg (SFmode, operands[1]);
2718 }
2719 }
2720
2721 /* Fixup PIC cases. */
2722 if (flag_pic)
2723 {
2724 if (CONSTANT_P (operands[1])
2725 && pic_address_needs_scratch (operands[1]))
2726 operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
2727
2728 if (symbolic_operand (operands[1], SFmode))
2729 {
2730 operands[1] = legitimize_pic_address (operands[1],
2731 SFmode,
2732 (reload_in_progress ?
2733 operands[0] :
2734 NULL_RTX));
2735 }
2736 }
2737
2738 movsf_is_ok:
2739 ;
2740 })
2741
2742 (define_expand "movdf"
2743 [(set (match_operand:DF 0 "general_operand" "")
2744 (match_operand:DF 1 "general_operand" ""))]
2745 ""
2746 {
2747 /* Force DFmode constants into memory. */
2748 if (GET_CODE (operands[0]) == REG
2749 && CONSTANT_P (operands[1]))
2750 {
2751 /* emit_group_store will send such bogosity to us when it is
2752 not storing directly into memory. So fix this up to avoid
2753 crashes in output_constant_pool. */
2754 if (operands [1] == const0_rtx)
2755 operands[1] = CONST0_RTX (DFmode);
2756
2757 if ((TARGET_VIS || REGNO (operands[0]) < 32)
2758 && fp_zero_operand (operands[1], DFmode))
2759 goto movdf_is_ok;
2760
2761 /* We are able to build any DF constant in integer registers. */
2762 if (REGNO (operands[0]) < 32
2763 && (reload_completed || reload_in_progress))
2764 goto movdf_is_ok;
2765
2766 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2767 operands[1]));
2768 }
2769
2770 /* Handle MEM cases first. */
2771 if (GET_CODE (operands[0]) == MEM)
2772 {
2773 if (register_operand (operands[1], DFmode)
2774 || fp_zero_operand (operands[1], DFmode))
2775 goto movdf_is_ok;
2776
2777 if (! reload_in_progress)
2778 {
2779 operands[0] = validize_mem (operands[0]);
2780 operands[1] = force_reg (DFmode, operands[1]);
2781 }
2782 }
2783
2784 /* Fixup PIC cases. */
2785 if (flag_pic)
2786 {
2787 if (CONSTANT_P (operands[1])
2788 && pic_address_needs_scratch (operands[1]))
2789 operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
2790
2791 if (symbolic_operand (operands[1], DFmode))
2792 {
2793 operands[1] = legitimize_pic_address (operands[1],
2794 DFmode,
2795 (reload_in_progress ?
2796 operands[0] :
2797 NULL_RTX));
2798 }
2799 }
2800
2801 movdf_is_ok:
2802 ;
2803 })
2804
2805 ;; Be careful, fmovd does not exist when !v9.
2806 (define_insn "*movdf_insn_sp32"
2807 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
2808 (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
2809 "TARGET_FPU
2810 && ! TARGET_V9
2811 && (register_operand (operands[0], DFmode)
2812 || register_operand (operands[1], DFmode)
2813 || fp_zero_operand (operands[1], DFmode))"
2814 "@
2815 ldd\t%1, %0
2816 std\t%1, %0
2817 ldd\t%1, %0
2818 std\t%1, %0
2819 #
2820 #
2821 #
2822 #
2823 #
2824 #"
2825 [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
2826 (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
2827
2828 (define_insn "*movdf_no_e_insn_sp32"
2829 [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
2830 (match_operand:DF 1 "input_operand" "T,U,G,ro,r"))]
2831 "! TARGET_FPU
2832 && ! TARGET_V9
2833 && ! TARGET_ARCH64
2834 && (register_operand (operands[0], DFmode)
2835 || register_operand (operands[1], DFmode)
2836 || fp_zero_operand (operands[1], DFmode))"
2837 "@
2838 ldd\t%1, %0
2839 std\t%1, %0
2840 #
2841 #
2842 #"
2843 [(set_attr "type" "load,store,*,*,*")
2844 (set_attr "length" "*,*,2,2,2")])
2845
2846 (define_insn "*movdf_no_e_insn_v9_sp32"
2847 [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
2848 (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
2849 "! TARGET_FPU
2850 && TARGET_V9
2851 && ! TARGET_ARCH64
2852 && (register_operand (operands[0], DFmode)
2853 || register_operand (operands[1], DFmode)
2854 || fp_zero_operand (operands[1], DFmode))"
2855 "@
2856 ldd\t%1, %0
2857 std\t%1, %0
2858 stx\t%r1, %0
2859 #
2860 #"
2861 [(set_attr "type" "load,store,store,*,*")
2862 (set_attr "length" "*,*,*,2,2")])
2863
2864 ;; We have available v9 double floats but not 64-bit
2865 ;; integer registers and no VIS.
2866 (define_insn "*movdf_insn_v9only_novis"
2867 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
2868 (match_operand:DF 1 "input_operand" "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
2869 "TARGET_FPU
2870 && TARGET_V9
2871 && ! TARGET_VIS
2872 && ! TARGET_ARCH64
2873 && (register_operand (operands[0], DFmode)
2874 || register_operand (operands[1], DFmode)
2875 || fp_zero_operand (operands[1], DFmode))"
2876 "@
2877 fmovd\t%1, %0
2878 ldd\t%1, %0
2879 stx\t%r1, %0
2880 std\t%1, %0
2881 ldd\t%1, %0
2882 std\t%1, %0
2883 #
2884 #
2885 #"
2886 [(set_attr "type" "fpmove,load,store,store,load,store,*,*,*")
2887 (set_attr "length" "*,*,*,*,*,*,2,2,2")
2888 (set_attr "fptype" "double,*,*,*,*,*,*,*,*")])
2889
2890 ;; We have available v9 double floats but not 64-bit
2891 ;; integer registers but we have VIS.
2892 (define_insn "*movdf_insn_v9only_vis"
2893 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
2894 (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
2895 "TARGET_FPU
2896 && TARGET_VIS
2897 && ! TARGET_ARCH64
2898 && (register_operand (operands[0], DFmode)
2899 || register_operand (operands[1], DFmode)
2900 || fp_zero_operand (operands[1], DFmode))"
2901 "@
2902 fzero\t%0
2903 fmovd\t%1, %0
2904 ldd\t%1, %0
2905 stx\t%r1, %0
2906 std\t%1, %0
2907 ldd\t%1, %0
2908 std\t%1, %0
2909 #
2910 #
2911 #"
2912 [(set_attr "type" "fpmove,fpmove,load,store,store,load,store,*,*,*")
2913 (set_attr "length" "*,*,*,*,*,*,*,2,2,2")
2914 (set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
2915
2916 ;; We have available both v9 double floats and 64-bit
2917 ;; integer registers. No VIS though.
2918 (define_insn "*movdf_insn_sp64_novis"
2919 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,W,*r,*r,m,*r")
2920 (match_operand:DF 1 "input_operand" "e,W#F,e,*rG,m,*rG,F"))]
2921 "TARGET_FPU
2922 && ! TARGET_VIS
2923 && TARGET_ARCH64
2924 && (register_operand (operands[0], DFmode)
2925 || register_operand (operands[1], DFmode)
2926 || fp_zero_operand (operands[1], DFmode))"
2927 "@
2928 fmovd\t%1, %0
2929 ldd\t%1, %0
2930 std\t%1, %0
2931 mov\t%r1, %0
2932 ldx\t%1, %0
2933 stx\t%r1, %0
2934 #"
2935 [(set_attr "type" "fpmove,load,store,*,load,store,*")
2936 (set_attr "length" "*,*,*,*,*,*,2")
2937 (set_attr "fptype" "double,*,*,*,*,*,*")])
2938
2939 ;; We have available both v9 double floats and 64-bit
2940 ;; integer registers. And we have VIS.
2941 (define_insn "*movdf_insn_sp64_vis"
2942 [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r")
2943 (match_operand:DF 1 "input_operand" "G,e,W#F,e,*rG,m,*rG,F"))]
2944 "TARGET_FPU
2945 && TARGET_VIS
2946 && TARGET_ARCH64
2947 && (register_operand (operands[0], DFmode)
2948 || register_operand (operands[1], DFmode)
2949 || fp_zero_operand (operands[1], DFmode))"
2950 "@
2951 fzero\t%0
2952 fmovd\t%1, %0
2953 ldd\t%1, %0
2954 std\t%1, %0
2955 mov\t%r1, %0
2956 ldx\t%1, %0
2957 stx\t%r1, %0
2958 #"
2959 [(set_attr "type" "fpmove,fpmove,load,store,*,load,store,*")
2960 (set_attr "length" "*,*,*,*,*,*,*,2")
2961 (set_attr "fptype" "double,double,*,*,*,*,*,*")])
2962
2963 (define_insn "*movdf_no_e_insn_sp64"
2964 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
2965 (match_operand:DF 1 "input_operand" "r,m,rG"))]
2966 "! TARGET_FPU
2967 && TARGET_ARCH64
2968 && (register_operand (operands[0], DFmode)
2969 || register_operand (operands[1], DFmode)
2970 || fp_zero_operand (operands[1], DFmode))"
2971 "@
2972 mov\t%1, %0
2973 ldx\t%1, %0
2974 stx\t%r1, %0"
2975 [(set_attr "type" "*,load,store")])
2976
2977 (define_split
2978 [(set (match_operand:DF 0 "register_operand" "")
2979 (match_operand:DF 1 "const_double_operand" ""))]
2980 "TARGET_FPU
2981 && (GET_CODE (operands[0]) == REG
2982 && REGNO (operands[0]) < 32)
2983 && ! fp_zero_operand(operands[1], DFmode)
2984 && reload_completed"
2985 [(clobber (const_int 0))]
2986 {
2987 REAL_VALUE_TYPE r;
2988 long l[2];
2989
2990 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2991 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
2992 operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
2993
2994 if (TARGET_ARCH64)
2995 {
2996 #if HOST_BITS_PER_WIDE_INT == 64
2997 HOST_WIDE_INT val;
2998
2999 val = ((HOST_WIDE_INT)(unsigned long)l[1] |
3000 ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
3001 emit_insn (gen_movdi (operands[0], GEN_INT (val)));
3002 #else
3003 emit_insn (gen_movdi (operands[0],
3004 immed_double_const (l[1], l[0], DImode)));
3005 #endif
3006 }
3007 else
3008 {
3009 emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
3010 GEN_INT (l[0])));
3011
3012 /* Slick... but this trick loses if this subreg constant part
3013 can be done in one insn. */
3014 if (l[1] == l[0]
3015 && !(SPARC_SETHI32_P (l[0])
3016 || SPARC_SIMM13_P (l[0])))
3017 {
3018 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3019 gen_highpart (SImode, operands[0])));
3020 }
3021 else
3022 {
3023 emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3024 GEN_INT (l[1])));
3025 }
3026 }
3027 DONE;
3028 })
3029
3030 ;; Ok, now the splits to handle all the multi insn and
3031 ;; mis-aligned memory address cases.
3032 ;; In these splits please take note that we must be
3033 ;; careful when V9 but not ARCH64 because the integer
3034 ;; register DFmode cases must be handled.
3035 (define_split
3036 [(set (match_operand:DF 0 "register_operand" "")
3037 (match_operand:DF 1 "register_operand" ""))]
3038 "(! TARGET_V9
3039 || (! TARGET_ARCH64
3040 && ((GET_CODE (operands[0]) == REG
3041 && REGNO (operands[0]) < 32)
3042 || (GET_CODE (operands[0]) == SUBREG
3043 && GET_CODE (SUBREG_REG (operands[0])) == REG
3044 && REGNO (SUBREG_REG (operands[0])) < 32))))
3045 && reload_completed"
3046 [(clobber (const_int 0))]
3047 {
3048 rtx set_dest = operands[0];
3049 rtx set_src = operands[1];
3050 rtx dest1, dest2;
3051 rtx src1, src2;
3052
3053 dest1 = gen_highpart (SFmode, set_dest);
3054 dest2 = gen_lowpart (SFmode, set_dest);
3055 src1 = gen_highpart (SFmode, set_src);
3056 src2 = gen_lowpart (SFmode, set_src);
3057
3058 /* Now emit using the real source and destination we found, swapping
3059 the order if we detect overlap. */
3060 if (reg_overlap_mentioned_p (dest1, src2))
3061 {
3062 emit_insn (gen_movsf (dest2, src2));
3063 emit_insn (gen_movsf (dest1, src1));
3064 }
3065 else
3066 {
3067 emit_insn (gen_movsf (dest1, src1));
3068 emit_insn (gen_movsf (dest2, src2));
3069 }
3070 DONE;
3071 })
3072
3073 (define_split
3074 [(set (match_operand:DF 0 "register_operand" "")
3075 (match_operand:DF 1 "memory_operand" ""))]
3076 "reload_completed
3077 && ! TARGET_ARCH64
3078 && (((REGNO (operands[0]) % 2) != 0)
3079 || ! mem_min_alignment (operands[1], 8))
3080 && offsettable_memref_p (operands[1])"
3081 [(clobber (const_int 0))]
3082 {
3083 rtx word0 = adjust_address (operands[1], SFmode, 0);
3084 rtx word1 = adjust_address (operands[1], SFmode, 4);
3085
3086 if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
3087 {
3088 emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3089 word1));
3090 emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3091 word0));
3092 }
3093 else
3094 {
3095 emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3096 word0));
3097 emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3098 word1));
3099 }
3100 DONE;
3101 })
3102
3103 (define_split
3104 [(set (match_operand:DF 0 "memory_operand" "")
3105 (match_operand:DF 1 "register_operand" ""))]
3106 "reload_completed
3107 && ! TARGET_ARCH64
3108 && (((REGNO (operands[1]) % 2) != 0)
3109 || ! mem_min_alignment (operands[0], 8))
3110 && offsettable_memref_p (operands[0])"
3111 [(clobber (const_int 0))]
3112 {
3113 rtx word0 = adjust_address (operands[0], SFmode, 0);
3114 rtx word1 = adjust_address (operands[0], SFmode, 4);
3115
3116 emit_insn (gen_movsf (word0,
3117 gen_highpart (SFmode, operands[1])));
3118 emit_insn (gen_movsf (word1,
3119 gen_lowpart (SFmode, operands[1])));
3120 DONE;
3121 })
3122
3123 (define_split
3124 [(set (match_operand:DF 0 "memory_operand" "")
3125 (match_operand:DF 1 "fp_zero_operand" ""))]
3126 "reload_completed
3127 && (! TARGET_V9
3128 || (! TARGET_ARCH64
3129 && ! mem_min_alignment (operands[0], 8)))
3130 && offsettable_memref_p (operands[0])"
3131 [(clobber (const_int 0))]
3132 {
3133 rtx dest1, dest2;
3134
3135 dest1 = adjust_address (operands[0], SFmode, 0);
3136 dest2 = adjust_address (operands[0], SFmode, 4);
3137
3138 emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
3139 emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
3140 DONE;
3141 })
3142
3143 (define_split
3144 [(set (match_operand:DF 0 "register_operand" "")
3145 (match_operand:DF 1 "fp_zero_operand" ""))]
3146 "reload_completed
3147 && ! TARGET_ARCH64
3148 && ((GET_CODE (operands[0]) == REG
3149 && REGNO (operands[0]) < 32)
3150 || (GET_CODE (operands[0]) == SUBREG
3151 && GET_CODE (SUBREG_REG (operands[0])) == REG
3152 && REGNO (SUBREG_REG (operands[0])) < 32))"
3153 [(clobber (const_int 0))]
3154 {
3155 rtx set_dest = operands[0];
3156 rtx dest1, dest2;
3157
3158 dest1 = gen_highpart (SFmode, set_dest);
3159 dest2 = gen_lowpart (SFmode, set_dest);
3160 emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
3161 emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
3162 DONE;
3163 })
3164
3165 (define_expand "movtf"
3166 [(set (match_operand:TF 0 "general_operand" "")
3167 (match_operand:TF 1 "general_operand" ""))]
3168 ""
3169 {
3170 /* Force TFmode constants into memory. */
3171 if (GET_CODE (operands[0]) == REG
3172 && CONSTANT_P (operands[1]))
3173 {
3174 /* emit_group_store will send such bogosity to us when it is
3175 not storing directly into memory. So fix this up to avoid
3176 crashes in output_constant_pool. */
3177 if (operands [1] == const0_rtx)
3178 operands[1] = CONST0_RTX (TFmode);
3179
3180 if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
3181 goto movtf_is_ok;
3182
3183 operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
3184 operands[1]));
3185 }
3186
3187 /* Handle MEM cases first, note that only v9 guarentees
3188 full 16-byte alignment for quads. */
3189 if (GET_CODE (operands[0]) == MEM)
3190 {
3191 if (register_operand (operands[1], TFmode)
3192 || fp_zero_operand (operands[1], TFmode))
3193 goto movtf_is_ok;
3194
3195 if (! reload_in_progress)
3196 {
3197 operands[0] = validize_mem (operands[0]);
3198 operands[1] = force_reg (TFmode, operands[1]);
3199 }
3200 }
3201
3202 /* Fixup PIC cases. */
3203 if (flag_pic)
3204 {
3205 if (CONSTANT_P (operands[1])
3206 && pic_address_needs_scratch (operands[1]))
3207 operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
3208
3209 if (symbolic_operand (operands[1], TFmode))
3210 {
3211 operands[1] = legitimize_pic_address (operands[1],
3212 TFmode,
3213 (reload_in_progress ?
3214 operands[0] :
3215 NULL_RTX));
3216 }
3217 }
3218
3219 movtf_is_ok:
3220 ;
3221 })
3222
3223 ;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
3224 ;; we must split them all. :-(
3225 (define_insn "*movtf_insn_sp32"
3226 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
3227 (match_operand:TF 1 "input_operand" "oe,GeUr,o,roG"))]
3228 "TARGET_FPU
3229 && ! TARGET_VIS
3230 && ! TARGET_ARCH64
3231 && (register_operand (operands[0], TFmode)
3232 || register_operand (operands[1], TFmode)
3233 || fp_zero_operand (operands[1], TFmode))"
3234 "#"
3235 [(set_attr "length" "4")])
3236
3237 (define_insn "*movtf_insn_vis_sp32"
3238 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
3239 (match_operand:TF 1 "input_operand" "Goe,GeUr,o,roG"))]
3240 "TARGET_FPU
3241 && TARGET_VIS
3242 && ! TARGET_ARCH64
3243 && (register_operand (operands[0], TFmode)
3244 || register_operand (operands[1], TFmode)
3245 || fp_zero_operand (operands[1], TFmode))"
3246 "#"
3247 [(set_attr "length" "4")])
3248
3249 ;; Exactly the same as above, except that all `e' cases are deleted.
3250 ;; This is necessary to prevent reload from ever trying to use a `e' reg
3251 ;; when -mno-fpu.
3252
3253 (define_insn "*movtf_no_e_insn_sp32"
3254 [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
3255 (match_operand:TF 1 "input_operand" "G,o,U,roG,r"))]
3256 "! TARGET_FPU
3257 && ! TARGET_ARCH64
3258 && (register_operand (operands[0], TFmode)
3259 || register_operand (operands[1], TFmode)
3260 || fp_zero_operand (operands[1], TFmode))"
3261 "#"
3262 [(set_attr "length" "4")])
3263
3264 ;; Now handle the float reg cases directly when arch64,
3265 ;; hard_quad, and proper reg number alignment are all true.
3266 (define_insn "*movtf_insn_hq_sp64"
3267 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,o,r")
3268 (match_operand:TF 1 "input_operand" "e,m,e,Gr,roG"))]
3269 "TARGET_FPU
3270 && ! TARGET_VIS
3271 && TARGET_ARCH64
3272 && TARGET_HARD_QUAD
3273 && (register_operand (operands[0], TFmode)
3274 || register_operand (operands[1], TFmode)
3275 || fp_zero_operand (operands[1], TFmode))"
3276 "@
3277 fmovq\t%1, %0
3278 ldq\t%1, %0
3279 stq\t%1, %0
3280 #
3281 #"
3282 [(set_attr "type" "fpmove,fpload,fpstore,*,*")
3283 (set_attr "length" "*,*,*,2,2")])
3284
3285 (define_insn "*movtf_insn_hq_vis_sp64"
3286 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,eo,r,o")
3287 (match_operand:TF 1 "input_operand" "e,m,e,G,roG,r"))]
3288 "TARGET_FPU
3289 && TARGET_VIS
3290 && TARGET_ARCH64
3291 && TARGET_HARD_QUAD
3292 && (register_operand (operands[0], TFmode)
3293 || register_operand (operands[1], TFmode)
3294 || fp_zero_operand (operands[1], TFmode))"
3295 "@
3296 fmovq\t%1, %0
3297 ldq\t%1, %0
3298 stq\t%1, %0
3299 #
3300 #
3301 #"
3302 [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
3303 (set_attr "length" "*,*,*,2,2,2")])
3304
3305 ;; Now we allow the integer register cases even when
3306 ;; only arch64 is true.
3307 (define_insn "*movtf_insn_sp64"
3308 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
3309 (match_operand:TF 1 "input_operand" "oe,Ger,orG"))]
3310 "TARGET_FPU
3311 && ! TARGET_VIS
3312 && TARGET_ARCH64
3313 && ! TARGET_HARD_QUAD
3314 && (register_operand (operands[0], TFmode)
3315 || register_operand (operands[1], TFmode)
3316 || fp_zero_operand (operands[1], TFmode))"
3317 "#"
3318 [(set_attr "length" "2")])
3319
3320 (define_insn "*movtf_insn_vis_sp64"
3321 [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
3322 (match_operand:TF 1 "input_operand" "Goe,Ger,orG"))]
3323 "TARGET_FPU
3324 && TARGET_VIS
3325 && TARGET_ARCH64
3326 && ! TARGET_HARD_QUAD
3327 && (register_operand (operands[0], TFmode)
3328 || register_operand (operands[1], TFmode)
3329 || fp_zero_operand (operands[1], TFmode))"
3330 "#"
3331 [(set_attr "length" "2")])
3332
3333 (define_insn "*movtf_no_e_insn_sp64"
3334 [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
3335 (match_operand:TF 1 "input_operand" "orG,rG"))]
3336 "! TARGET_FPU
3337 && TARGET_ARCH64
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 ;; Now all the splits to handle multi-insn TF mode moves.
3345 (define_split
3346 [(set (match_operand:TF 0 "register_operand" "")
3347 (match_operand:TF 1 "register_operand" ""))]
3348 "reload_completed
3349 && (! TARGET_ARCH64
3350 || (TARGET_FPU
3351 && ! TARGET_HARD_QUAD)
3352 || ! fp_register_operand (operands[0], TFmode))"
3353 [(clobber (const_int 0))]
3354 {
3355 rtx set_dest = operands[0];
3356 rtx set_src = operands[1];
3357 rtx dest1, dest2;
3358 rtx src1, src2;
3359
3360 dest1 = gen_df_reg (set_dest, 0);
3361 dest2 = gen_df_reg (set_dest, 1);
3362 src1 = gen_df_reg (set_src, 0);
3363 src2 = gen_df_reg (set_src, 1);
3364
3365 /* Now emit using the real source and destination we found, swapping
3366 the order if we detect overlap. */
3367 if (reg_overlap_mentioned_p (dest1, src2))
3368 {
3369 emit_insn (gen_movdf (dest2, src2));
3370 emit_insn (gen_movdf (dest1, src1));
3371 }
3372 else
3373 {
3374 emit_insn (gen_movdf (dest1, src1));
3375 emit_insn (gen_movdf (dest2, src2));
3376 }
3377 DONE;
3378 })
3379
3380 (define_split
3381 [(set (match_operand:TF 0 "nonimmediate_operand" "")
3382 (match_operand:TF 1 "fp_zero_operand" ""))]
3383 "reload_completed"
3384 [(clobber (const_int 0))]
3385 {
3386 rtx set_dest = operands[0];
3387 rtx dest1, dest2;
3388
3389 switch (GET_CODE (set_dest))
3390 {
3391 case REG:
3392 dest1 = gen_df_reg (set_dest, 0);
3393 dest2 = gen_df_reg (set_dest, 1);
3394 break;
3395 case MEM:
3396 dest1 = adjust_address (set_dest, DFmode, 0);
3397 dest2 = adjust_address (set_dest, DFmode, 8);
3398 break;
3399 default:
3400 abort ();
3401 }
3402
3403 emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
3404 emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
3405 DONE;
3406 })
3407
3408 (define_split
3409 [(set (match_operand:TF 0 "register_operand" "")
3410 (match_operand:TF 1 "memory_operand" ""))]
3411 "(reload_completed
3412 && offsettable_memref_p (operands[1])
3413 && (! TARGET_ARCH64
3414 || ! TARGET_HARD_QUAD
3415 || ! fp_register_operand (operands[0], TFmode)))"
3416 [(clobber (const_int 0))]
3417 {
3418 rtx word0 = adjust_address (operands[1], DFmode, 0);
3419 rtx word1 = adjust_address (operands[1], DFmode, 8);
3420 rtx set_dest, dest1, dest2;
3421
3422 set_dest = operands[0];
3423
3424 dest1 = gen_df_reg (set_dest, 0);
3425 dest2 = gen_df_reg (set_dest, 1);
3426
3427 /* Now output, ordering such that we don't clobber any registers
3428 mentioned in the address. */
3429 if (reg_overlap_mentioned_p (dest1, word1))
3430
3431 {
3432 emit_insn (gen_movdf (dest2, word1));
3433 emit_insn (gen_movdf (dest1, word0));
3434 }
3435 else
3436 {
3437 emit_insn (gen_movdf (dest1, word0));
3438 emit_insn (gen_movdf (dest2, word1));
3439 }
3440 DONE;
3441 })
3442
3443 (define_split
3444 [(set (match_operand:TF 0 "memory_operand" "")
3445 (match_operand:TF 1 "register_operand" ""))]
3446 "(reload_completed
3447 && offsettable_memref_p (operands[0])
3448 && (! TARGET_ARCH64
3449 || ! TARGET_HARD_QUAD
3450 || ! fp_register_operand (operands[1], TFmode)))"
3451 [(clobber (const_int 0))]
3452 {
3453 rtx set_src = operands[1];
3454
3455 emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
3456 gen_df_reg (set_src, 0)));
3457 emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
3458 gen_df_reg (set_src, 1)));
3459 DONE;
3460 })
3461 \f
3462 ;; SPARC V9 conditional move instructions.
3463
3464 ;; We can handle larger constants here for some flavors, but for now we keep
3465 ;; it simple and only allow those constants supported by all flavours.
3466 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
3467 ;; 3 contains the constant if one is present, but we handle either for
3468 ;; generality (sparc.c puts a constant in operand 2).
3469
3470 (define_expand "movqicc"
3471 [(set (match_operand:QI 0 "register_operand" "")
3472 (if_then_else:QI (match_operand 1 "comparison_operator" "")
3473 (match_operand:QI 2 "arith10_operand" "")
3474 (match_operand:QI 3 "arith10_operand" "")))]
3475 "TARGET_V9"
3476 {
3477 enum rtx_code code = GET_CODE (operands[1]);
3478
3479 if (GET_MODE (sparc_compare_op0) == DImode
3480 && ! TARGET_ARCH64)
3481 FAIL;
3482
3483 if (sparc_compare_op1 == const0_rtx
3484 && GET_CODE (sparc_compare_op0) == REG
3485 && GET_MODE (sparc_compare_op0) == DImode
3486 && v9_regcmp_p (code))
3487 {
3488 operands[1] = gen_rtx_fmt_ee (code, DImode,
3489 sparc_compare_op0, sparc_compare_op1);
3490 }
3491 else
3492 {
3493 rtx cc_reg = gen_compare_reg (code,
3494 sparc_compare_op0, sparc_compare_op1);
3495 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3496 }
3497 })
3498
3499 (define_expand "movhicc"
3500 [(set (match_operand:HI 0 "register_operand" "")
3501 (if_then_else:HI (match_operand 1 "comparison_operator" "")
3502 (match_operand:HI 2 "arith10_operand" "")
3503 (match_operand:HI 3 "arith10_operand" "")))]
3504 "TARGET_V9"
3505 {
3506 enum rtx_code code = GET_CODE (operands[1]);
3507
3508 if (GET_MODE (sparc_compare_op0) == DImode
3509 && ! TARGET_ARCH64)
3510 FAIL;
3511
3512 if (sparc_compare_op1 == const0_rtx
3513 && GET_CODE (sparc_compare_op0) == REG
3514 && GET_MODE (sparc_compare_op0) == DImode
3515 && v9_regcmp_p (code))
3516 {
3517 operands[1] = gen_rtx_fmt_ee (code, DImode,
3518 sparc_compare_op0, sparc_compare_op1);
3519 }
3520 else
3521 {
3522 rtx cc_reg = gen_compare_reg (code,
3523 sparc_compare_op0, sparc_compare_op1);
3524 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3525 }
3526 })
3527
3528 (define_expand "movsicc"
3529 [(set (match_operand:SI 0 "register_operand" "")
3530 (if_then_else:SI (match_operand 1 "comparison_operator" "")
3531 (match_operand:SI 2 "arith10_operand" "")
3532 (match_operand:SI 3 "arith10_operand" "")))]
3533 "TARGET_V9"
3534 {
3535 enum rtx_code code = GET_CODE (operands[1]);
3536 enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
3537
3538 if (sparc_compare_op1 == const0_rtx
3539 && GET_CODE (sparc_compare_op0) == REG
3540 && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
3541 {
3542 operands[1] = gen_rtx_fmt_ee (code, op0_mode,
3543 sparc_compare_op0, sparc_compare_op1);
3544 }
3545 else
3546 {
3547 rtx cc_reg = gen_compare_reg (code,
3548 sparc_compare_op0, sparc_compare_op1);
3549 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3550 cc_reg, const0_rtx);
3551 }
3552 })
3553
3554 (define_expand "movdicc"
3555 [(set (match_operand:DI 0 "register_operand" "")
3556 (if_then_else:DI (match_operand 1 "comparison_operator" "")
3557 (match_operand:DI 2 "arith10_double_operand" "")
3558 (match_operand:DI 3 "arith10_double_operand" "")))]
3559 "TARGET_ARCH64"
3560 {
3561 enum rtx_code code = GET_CODE (operands[1]);
3562
3563 if (sparc_compare_op1 == const0_rtx
3564 && GET_CODE (sparc_compare_op0) == REG
3565 && GET_MODE (sparc_compare_op0) == DImode
3566 && v9_regcmp_p (code))
3567 {
3568 operands[1] = gen_rtx_fmt_ee (code, DImode,
3569 sparc_compare_op0, sparc_compare_op1);
3570 }
3571 else
3572 {
3573 rtx cc_reg = gen_compare_reg (code,
3574 sparc_compare_op0, sparc_compare_op1);
3575 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3576 cc_reg, const0_rtx);
3577 }
3578 })
3579
3580 (define_expand "movsfcc"
3581 [(set (match_operand:SF 0 "register_operand" "")
3582 (if_then_else:SF (match_operand 1 "comparison_operator" "")
3583 (match_operand:SF 2 "register_operand" "")
3584 (match_operand:SF 3 "register_operand" "")))]
3585 "TARGET_V9 && TARGET_FPU"
3586 {
3587 enum rtx_code code = GET_CODE (operands[1]);
3588
3589 if (GET_MODE (sparc_compare_op0) == DImode
3590 && ! TARGET_ARCH64)
3591 FAIL;
3592
3593 if (sparc_compare_op1 == const0_rtx
3594 && GET_CODE (sparc_compare_op0) == REG
3595 && GET_MODE (sparc_compare_op0) == DImode
3596 && v9_regcmp_p (code))
3597 {
3598 operands[1] = gen_rtx_fmt_ee (code, DImode,
3599 sparc_compare_op0, sparc_compare_op1);
3600 }
3601 else
3602 {
3603 rtx cc_reg = gen_compare_reg (code,
3604 sparc_compare_op0, sparc_compare_op1);
3605 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3606 }
3607 })
3608
3609 (define_expand "movdfcc"
3610 [(set (match_operand:DF 0 "register_operand" "")
3611 (if_then_else:DF (match_operand 1 "comparison_operator" "")
3612 (match_operand:DF 2 "register_operand" "")
3613 (match_operand:DF 3 "register_operand" "")))]
3614 "TARGET_V9 && TARGET_FPU"
3615 {
3616 enum rtx_code code = GET_CODE (operands[1]);
3617
3618 if (GET_MODE (sparc_compare_op0) == DImode
3619 && ! TARGET_ARCH64)
3620 FAIL;
3621
3622 if (sparc_compare_op1 == const0_rtx
3623 && GET_CODE (sparc_compare_op0) == REG
3624 && GET_MODE (sparc_compare_op0) == DImode
3625 && v9_regcmp_p (code))
3626 {
3627 operands[1] = gen_rtx_fmt_ee (code, DImode,
3628 sparc_compare_op0, sparc_compare_op1);
3629 }
3630 else
3631 {
3632 rtx cc_reg = gen_compare_reg (code,
3633 sparc_compare_op0, sparc_compare_op1);
3634 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3635 }
3636 })
3637
3638 (define_expand "movtfcc"
3639 [(set (match_operand:TF 0 "register_operand" "")
3640 (if_then_else:TF (match_operand 1 "comparison_operator" "")
3641 (match_operand:TF 2 "register_operand" "")
3642 (match_operand:TF 3 "register_operand" "")))]
3643 "TARGET_V9 && TARGET_FPU"
3644 {
3645 enum rtx_code code = GET_CODE (operands[1]);
3646
3647 if (GET_MODE (sparc_compare_op0) == DImode
3648 && ! TARGET_ARCH64)
3649 FAIL;
3650
3651 if (sparc_compare_op1 == const0_rtx
3652 && GET_CODE (sparc_compare_op0) == REG
3653 && GET_MODE (sparc_compare_op0) == DImode
3654 && v9_regcmp_p (code))
3655 {
3656 operands[1] = gen_rtx_fmt_ee (code, DImode,
3657 sparc_compare_op0, sparc_compare_op1);
3658 }
3659 else
3660 {
3661 rtx cc_reg = gen_compare_reg (code,
3662 sparc_compare_op0, sparc_compare_op1);
3663 operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3664 }
3665 })
3666
3667 ;; Conditional move define_insns.
3668
3669 (define_insn "*movqi_cc_sp64"
3670 [(set (match_operand:QI 0 "register_operand" "=r,r")
3671 (if_then_else:QI (match_operator 1 "comparison_operator"
3672 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3673 (const_int 0)])
3674 (match_operand:QI 3 "arith11_operand" "rL,0")
3675 (match_operand:QI 4 "arith11_operand" "0,rL")))]
3676 "TARGET_V9"
3677 "@
3678 mov%C1\t%x2, %3, %0
3679 mov%c1\t%x2, %4, %0"
3680 [(set_attr "type" "cmove")])
3681
3682 (define_insn "*movhi_cc_sp64"
3683 [(set (match_operand:HI 0 "register_operand" "=r,r")
3684 (if_then_else:HI (match_operator 1 "comparison_operator"
3685 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3686 (const_int 0)])
3687 (match_operand:HI 3 "arith11_operand" "rL,0")
3688 (match_operand:HI 4 "arith11_operand" "0,rL")))]
3689 "TARGET_V9"
3690 "@
3691 mov%C1\t%x2, %3, %0
3692 mov%c1\t%x2, %4, %0"
3693 [(set_attr "type" "cmove")])
3694
3695 (define_insn "*movsi_cc_sp64"
3696 [(set (match_operand:SI 0 "register_operand" "=r,r")
3697 (if_then_else:SI (match_operator 1 "comparison_operator"
3698 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3699 (const_int 0)])
3700 (match_operand:SI 3 "arith11_operand" "rL,0")
3701 (match_operand:SI 4 "arith11_operand" "0,rL")))]
3702 "TARGET_V9"
3703 "@
3704 mov%C1\t%x2, %3, %0
3705 mov%c1\t%x2, %4, %0"
3706 [(set_attr "type" "cmove")])
3707
3708 ;; ??? The constraints of operands 3,4 need work.
3709 (define_insn "*movdi_cc_sp64"
3710 [(set (match_operand:DI 0 "register_operand" "=r,r")
3711 (if_then_else:DI (match_operator 1 "comparison_operator"
3712 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3713 (const_int 0)])
3714 (match_operand:DI 3 "arith11_double_operand" "rLH,0")
3715 (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
3716 "TARGET_ARCH64"
3717 "@
3718 mov%C1\t%x2, %3, %0
3719 mov%c1\t%x2, %4, %0"
3720 [(set_attr "type" "cmove")])
3721
3722 (define_insn "*movdi_cc_sp64_trunc"
3723 [(set (match_operand:SI 0 "register_operand" "=r,r")
3724 (if_then_else:SI (match_operator 1 "comparison_operator"
3725 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3726 (const_int 0)])
3727 (match_operand:SI 3 "arith11_double_operand" "rLH,0")
3728 (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
3729 "TARGET_ARCH64"
3730 "@
3731 mov%C1\t%x2, %3, %0
3732 mov%c1\t%x2, %4, %0"
3733 [(set_attr "type" "cmove")])
3734
3735 (define_insn "*movsf_cc_sp64"
3736 [(set (match_operand:SF 0 "register_operand" "=f,f")
3737 (if_then_else:SF (match_operator 1 "comparison_operator"
3738 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3739 (const_int 0)])
3740 (match_operand:SF 3 "register_operand" "f,0")
3741 (match_operand:SF 4 "register_operand" "0,f")))]
3742 "TARGET_V9 && TARGET_FPU"
3743 "@
3744 fmovs%C1\t%x2, %3, %0
3745 fmovs%c1\t%x2, %4, %0"
3746 [(set_attr "type" "fpcmove")])
3747
3748 (define_insn "movdf_cc_sp64"
3749 [(set (match_operand:DF 0 "register_operand" "=e,e")
3750 (if_then_else:DF (match_operator 1 "comparison_operator"
3751 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3752 (const_int 0)])
3753 (match_operand:DF 3 "register_operand" "e,0")
3754 (match_operand:DF 4 "register_operand" "0,e")))]
3755 "TARGET_V9 && TARGET_FPU"
3756 "@
3757 fmovd%C1\t%x2, %3, %0
3758 fmovd%c1\t%x2, %4, %0"
3759 [(set_attr "type" "fpcmove")
3760 (set_attr "fptype" "double")])
3761
3762 (define_insn "*movtf_cc_hq_sp64"
3763 [(set (match_operand:TF 0 "register_operand" "=e,e")
3764 (if_then_else:TF (match_operator 1 "comparison_operator"
3765 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3766 (const_int 0)])
3767 (match_operand:TF 3 "register_operand" "e,0")
3768 (match_operand:TF 4 "register_operand" "0,e")))]
3769 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3770 "@
3771 fmovq%C1\t%x2, %3, %0
3772 fmovq%c1\t%x2, %4, %0"
3773 [(set_attr "type" "fpcmove")])
3774
3775 (define_insn_and_split "*movtf_cc_sp64"
3776 [(set (match_operand:TF 0 "register_operand" "=e,e")
3777 (if_then_else:TF (match_operator 1 "comparison_operator"
3778 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3779 (const_int 0)])
3780 (match_operand:TF 3 "register_operand" "e,0")
3781 (match_operand:TF 4 "register_operand" "0,e")))]
3782 "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
3783 "#"
3784 "&& reload_completed"
3785 [(clobber (const_int 0))]
3786 {
3787 rtx set_dest = operands[0];
3788 rtx set_srca = operands[3];
3789 rtx set_srcb = operands[4];
3790 int third = rtx_equal_p (set_dest, set_srca);
3791 rtx dest1, dest2;
3792 rtx srca1, srca2, srcb1, srcb2;
3793
3794 dest1 = gen_df_reg (set_dest, 0);
3795 dest2 = gen_df_reg (set_dest, 1);
3796 srca1 = gen_df_reg (set_srca, 0);
3797 srca2 = gen_df_reg (set_srca, 1);
3798 srcb1 = gen_df_reg (set_srcb, 0);
3799 srcb2 = gen_df_reg (set_srcb, 1);
3800
3801 /* Now emit using the real source and destination we found, swapping
3802 the order if we detect overlap. */
3803 if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3804 || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3805 {
3806 emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3807 emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3808 }
3809 else
3810 {
3811 emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3812 emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3813 }
3814 DONE;
3815 }
3816 [(set_attr "length" "2")])
3817
3818 (define_insn "*movqi_cc_reg_sp64"
3819 [(set (match_operand:QI 0 "register_operand" "=r,r")
3820 (if_then_else:QI (match_operator 1 "v9_regcmp_op"
3821 [(match_operand:DI 2 "register_operand" "r,r")
3822 (const_int 0)])
3823 (match_operand:QI 3 "arith10_operand" "rM,0")
3824 (match_operand:QI 4 "arith10_operand" "0,rM")))]
3825 "TARGET_ARCH64"
3826 "@
3827 movr%D1\t%2, %r3, %0
3828 movr%d1\t%2, %r4, %0"
3829 [(set_attr "type" "cmove")])
3830
3831 (define_insn "*movhi_cc_reg_sp64"
3832 [(set (match_operand:HI 0 "register_operand" "=r,r")
3833 (if_then_else:HI (match_operator 1 "v9_regcmp_op"
3834 [(match_operand:DI 2 "register_operand" "r,r")
3835 (const_int 0)])
3836 (match_operand:HI 3 "arith10_operand" "rM,0")
3837 (match_operand:HI 4 "arith10_operand" "0,rM")))]
3838 "TARGET_ARCH64"
3839 "@
3840 movr%D1\t%2, %r3, %0
3841 movr%d1\t%2, %r4, %0"
3842 [(set_attr "type" "cmove")])
3843
3844 (define_insn "*movsi_cc_reg_sp64"
3845 [(set (match_operand:SI 0 "register_operand" "=r,r")
3846 (if_then_else:SI (match_operator 1 "v9_regcmp_op"
3847 [(match_operand:DI 2 "register_operand" "r,r")
3848 (const_int 0)])
3849 (match_operand:SI 3 "arith10_operand" "rM,0")
3850 (match_operand:SI 4 "arith10_operand" "0,rM")))]
3851 "TARGET_ARCH64"
3852 "@
3853 movr%D1\t%2, %r3, %0
3854 movr%d1\t%2, %r4, %0"
3855 [(set_attr "type" "cmove")])
3856
3857 ;; ??? The constraints of operands 3,4 need work.
3858 (define_insn "*movdi_cc_reg_sp64"
3859 [(set (match_operand:DI 0 "register_operand" "=r,r")
3860 (if_then_else:DI (match_operator 1 "v9_regcmp_op"
3861 [(match_operand:DI 2 "register_operand" "r,r")
3862 (const_int 0)])
3863 (match_operand:DI 3 "arith10_double_operand" "rMH,0")
3864 (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
3865 "TARGET_ARCH64"
3866 "@
3867 movr%D1\t%2, %r3, %0
3868 movr%d1\t%2, %r4, %0"
3869 [(set_attr "type" "cmove")])
3870
3871 (define_insn "*movdi_cc_reg_sp64_trunc"
3872 [(set (match_operand:SI 0 "register_operand" "=r,r")
3873 (if_then_else:SI (match_operator 1 "v9_regcmp_op"
3874 [(match_operand:DI 2 "register_operand" "r,r")
3875 (const_int 0)])
3876 (match_operand:SI 3 "arith10_double_operand" "rMH,0")
3877 (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
3878 "TARGET_ARCH64"
3879 "@
3880 movr%D1\t%2, %r3, %0
3881 movr%d1\t%2, %r4, %0"
3882 [(set_attr "type" "cmove")])
3883
3884 (define_insn "*movsf_cc_reg_sp64"
3885 [(set (match_operand:SF 0 "register_operand" "=f,f")
3886 (if_then_else:SF (match_operator 1 "v9_regcmp_op"
3887 [(match_operand:DI 2 "register_operand" "r,r")
3888 (const_int 0)])
3889 (match_operand:SF 3 "register_operand" "f,0")
3890 (match_operand:SF 4 "register_operand" "0,f")))]
3891 "TARGET_ARCH64 && TARGET_FPU"
3892 "@
3893 fmovrs%D1\t%2, %3, %0
3894 fmovrs%d1\t%2, %4, %0"
3895 [(set_attr "type" "fpcrmove")])
3896
3897 (define_insn "movdf_cc_reg_sp64"
3898 [(set (match_operand:DF 0 "register_operand" "=e,e")
3899 (if_then_else:DF (match_operator 1 "v9_regcmp_op"
3900 [(match_operand:DI 2 "register_operand" "r,r")
3901 (const_int 0)])
3902 (match_operand:DF 3 "register_operand" "e,0")
3903 (match_operand:DF 4 "register_operand" "0,e")))]
3904 "TARGET_ARCH64 && TARGET_FPU"
3905 "@
3906 fmovrd%D1\t%2, %3, %0
3907 fmovrd%d1\t%2, %4, %0"
3908 [(set_attr "type" "fpcrmove")
3909 (set_attr "fptype" "double")])
3910
3911 (define_insn "*movtf_cc_reg_hq_sp64"
3912 [(set (match_operand:TF 0 "register_operand" "=e,e")
3913 (if_then_else:TF (match_operator 1 "v9_regcmp_op"
3914 [(match_operand:DI 2 "register_operand" "r,r")
3915 (const_int 0)])
3916 (match_operand:TF 3 "register_operand" "e,0")
3917 (match_operand:TF 4 "register_operand" "0,e")))]
3918 "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3919 "@
3920 fmovrq%D1\t%2, %3, %0
3921 fmovrq%d1\t%2, %4, %0"
3922 [(set_attr "type" "fpcrmove")])
3923
3924 (define_insn_and_split "*movtf_cc_reg_sp64"
3925 [(set (match_operand:TF 0 "register_operand" "=e,e")
3926 (if_then_else:TF (match_operator 1 "v9_regcmp_op"
3927 [(match_operand:DI 2 "register_operand" "r,r")
3928 (const_int 0)])
3929 (match_operand:TF 3 "register_operand" "e,0")
3930 (match_operand:TF 4 "register_operand" "0,e")))]
3931 "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
3932 "#"
3933 "&& reload_completed"
3934 [(clobber (const_int 0))]
3935 {
3936 rtx set_dest = operands[0];
3937 rtx set_srca = operands[3];
3938 rtx set_srcb = operands[4];
3939 int third = rtx_equal_p (set_dest, set_srca);
3940 rtx dest1, dest2;
3941 rtx srca1, srca2, srcb1, srcb2;
3942
3943 dest1 = gen_df_reg (set_dest, 0);
3944 dest2 = gen_df_reg (set_dest, 1);
3945 srca1 = gen_df_reg (set_srca, 0);
3946 srca2 = gen_df_reg (set_srca, 1);
3947 srcb1 = gen_df_reg (set_srcb, 0);
3948 srcb2 = gen_df_reg (set_srcb, 1);
3949
3950 /* Now emit using the real source and destination we found, swapping
3951 the order if we detect overlap. */
3952 if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3953 || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3954 {
3955 emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3956 emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3957 }
3958 else
3959 {
3960 emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3961 emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3962 }
3963 DONE;
3964 }
3965 [(set_attr "length" "2")])
3966
3967 \f
3968 ;;- zero extension instructions
3969
3970 ;; These patterns originally accepted general_operands, however, slightly
3971 ;; better code is generated by only accepting register_operands, and then
3972 ;; letting combine generate the ldu[hb] insns.
3973
3974 (define_expand "zero_extendhisi2"
3975 [(set (match_operand:SI 0 "register_operand" "")
3976 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
3977 ""
3978 {
3979 rtx temp = gen_reg_rtx (SImode);
3980 rtx shift_16 = GEN_INT (16);
3981 int op1_subbyte = 0;
3982
3983 if (GET_CODE (operand1) == SUBREG)
3984 {
3985 op1_subbyte = SUBREG_BYTE (operand1);
3986 op1_subbyte /= GET_MODE_SIZE (SImode);
3987 op1_subbyte *= GET_MODE_SIZE (SImode);
3988 operand1 = XEXP (operand1, 0);
3989 }
3990
3991 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
3992 shift_16));
3993 emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
3994 DONE;
3995 })
3996
3997 (define_insn "*zero_extendhisi2_insn"
3998 [(set (match_operand:SI 0 "register_operand" "=r")
3999 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4000 ""
4001 "lduh\t%1, %0"
4002 [(set_attr "type" "load")
4003 (set_attr "us3load_type" "3cycle")])
4004
4005 (define_expand "zero_extendqihi2"
4006 [(set (match_operand:HI 0 "register_operand" "")
4007 (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
4008 ""
4009 "")
4010
4011 (define_insn "*zero_extendqihi2_insn"
4012 [(set (match_operand:HI 0 "register_operand" "=r,r")
4013 (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
4014 "GET_CODE (operands[1]) != CONST_INT"
4015 "@
4016 and\t%1, 0xff, %0
4017 ldub\t%1, %0"
4018 [(set_attr "type" "*,load")
4019 (set_attr "us3load_type" "*,3cycle")])
4020
4021 (define_expand "zero_extendqisi2"
4022 [(set (match_operand:SI 0 "register_operand" "")
4023 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4024 ""
4025 "")
4026
4027 (define_insn "*zero_extendqisi2_insn"
4028 [(set (match_operand:SI 0 "register_operand" "=r,r")
4029 (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
4030 "GET_CODE (operands[1]) != CONST_INT"
4031 "@
4032 and\t%1, 0xff, %0
4033 ldub\t%1, %0"
4034 [(set_attr "type" "*,load")
4035 (set_attr "us3load_type" "*,3cycle")])
4036
4037 (define_expand "zero_extendqidi2"
4038 [(set (match_operand:DI 0 "register_operand" "")
4039 (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
4040 "TARGET_ARCH64"
4041 "")
4042
4043 (define_insn "*zero_extendqidi2_insn"
4044 [(set (match_operand:DI 0 "register_operand" "=r,r")
4045 (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
4046 "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4047 "@
4048 and\t%1, 0xff, %0
4049 ldub\t%1, %0"
4050 [(set_attr "type" "*,load")
4051 (set_attr "us3load_type" "*,3cycle")])
4052
4053 (define_expand "zero_extendhidi2"
4054 [(set (match_operand:DI 0 "register_operand" "")
4055 (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
4056 "TARGET_ARCH64"
4057 {
4058 rtx temp = gen_reg_rtx (DImode);
4059 rtx shift_48 = GEN_INT (48);
4060 int op1_subbyte = 0;
4061
4062 if (GET_CODE (operand1) == SUBREG)
4063 {
4064 op1_subbyte = SUBREG_BYTE (operand1);
4065 op1_subbyte /= GET_MODE_SIZE (DImode);
4066 op1_subbyte *= GET_MODE_SIZE (DImode);
4067 operand1 = XEXP (operand1, 0);
4068 }
4069
4070 emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4071 shift_48));
4072 emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
4073 DONE;
4074 })
4075
4076 (define_insn "*zero_extendhidi2_insn"
4077 [(set (match_operand:DI 0 "register_operand" "=r")
4078 (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4079 "TARGET_ARCH64"
4080 "lduh\t%1, %0"
4081 [(set_attr "type" "load")
4082 (set_attr "us3load_type" "3cycle")])
4083
4084
4085 ;; ??? Write truncdisi pattern using sra?
4086
4087 (define_expand "zero_extendsidi2"
4088 [(set (match_operand:DI 0 "register_operand" "")
4089 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
4090 ""
4091 "")
4092
4093 (define_insn "*zero_extendsidi2_insn_sp64"
4094 [(set (match_operand:DI 0 "register_operand" "=r,r")
4095 (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4096 "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4097 "@
4098 srl\t%1, 0, %0
4099 lduw\t%1, %0"
4100 [(set_attr "type" "shift,load")])
4101
4102 (define_insn_and_split "*zero_extendsidi2_insn_sp32"
4103 [(set (match_operand:DI 0 "register_operand" "=r")
4104 (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
4105 "! TARGET_ARCH64"
4106 "#"
4107 "&& reload_completed"
4108 [(set (match_dup 2) (match_dup 3))
4109 (set (match_dup 4) (match_dup 5))]
4110 {
4111 rtx dest1, dest2;
4112
4113 dest1 = gen_highpart (SImode, operands[0]);
4114 dest2 = gen_lowpart (SImode, operands[0]);
4115
4116 /* Swap the order in case of overlap. */
4117 if (REGNO (dest1) == REGNO (operands[1]))
4118 {
4119 operands[2] = dest2;
4120 operands[3] = operands[1];
4121 operands[4] = dest1;
4122 operands[5] = const0_rtx;
4123 }
4124 else
4125 {
4126 operands[2] = dest1;
4127 operands[3] = const0_rtx;
4128 operands[4] = dest2;
4129 operands[5] = operands[1];
4130 }
4131 }
4132 [(set_attr "length" "2")])
4133
4134 ;; Simplify comparisons of extended values.
4135
4136 (define_insn "*cmp_zero_extendqisi2"
4137 [(set (reg:CC 100)
4138 (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
4139 (const_int 0)))]
4140 ""
4141 "andcc\t%0, 0xff, %%g0"
4142 [(set_attr "type" "compare")])
4143
4144 (define_insn "*cmp_zero_qi"
4145 [(set (reg:CC 100)
4146 (compare:CC (match_operand:QI 0 "register_operand" "r")
4147 (const_int 0)))]
4148 ""
4149 "andcc\t%0, 0xff, %%g0"
4150 [(set_attr "type" "compare")])
4151
4152 (define_insn "*cmp_zero_extendqisi2_set"
4153 [(set (reg:CC 100)
4154 (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
4155 (const_int 0)))
4156 (set (match_operand:SI 0 "register_operand" "=r")
4157 (zero_extend:SI (match_dup 1)))]
4158 ""
4159 "andcc\t%1, 0xff, %0"
4160 [(set_attr "type" "compare")])
4161
4162 (define_insn "*cmp_zero_extendqisi2_andcc_set"
4163 [(set (reg:CC 100)
4164 (compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
4165 (const_int 255))
4166 (const_int 0)))
4167 (set (match_operand:SI 0 "register_operand" "=r")
4168 (zero_extend:SI (subreg:QI (match_dup 1) 0)))]
4169 ""
4170 "andcc\t%1, 0xff, %0"
4171 [(set_attr "type" "compare")])
4172
4173 (define_insn "*cmp_zero_extendqidi2"
4174 [(set (reg:CCX 100)
4175 (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
4176 (const_int 0)))]
4177 "TARGET_ARCH64"
4178 "andcc\t%0, 0xff, %%g0"
4179 [(set_attr "type" "compare")])
4180
4181 (define_insn "*cmp_zero_qi_sp64"
4182 [(set (reg:CCX 100)
4183 (compare:CCX (match_operand:QI 0 "register_operand" "r")
4184 (const_int 0)))]
4185 "TARGET_ARCH64"
4186 "andcc\t%0, 0xff, %%g0"
4187 [(set_attr "type" "compare")])
4188
4189 (define_insn "*cmp_zero_extendqidi2_set"
4190 [(set (reg:CCX 100)
4191 (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
4192 (const_int 0)))
4193 (set (match_operand:DI 0 "register_operand" "=r")
4194 (zero_extend:DI (match_dup 1)))]
4195 "TARGET_ARCH64"
4196 "andcc\t%1, 0xff, %0"
4197 [(set_attr "type" "compare")])
4198
4199 (define_insn "*cmp_zero_extendqidi2_andcc_set"
4200 [(set (reg:CCX 100)
4201 (compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
4202 (const_int 255))
4203 (const_int 0)))
4204 (set (match_operand:DI 0 "register_operand" "=r")
4205 (zero_extend:DI (subreg:QI (match_dup 1) 0)))]
4206 "TARGET_ARCH64"
4207 "andcc\t%1, 0xff, %0"
4208 [(set_attr "type" "compare")])
4209
4210 ;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
4211
4212 (define_insn "*cmp_siqi_trunc"
4213 [(set (reg:CC 100)
4214 (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
4215 (const_int 0)))]
4216 ""
4217 "andcc\t%0, 0xff, %%g0"
4218 [(set_attr "type" "compare")])
4219
4220 (define_insn "*cmp_siqi_trunc_set"
4221 [(set (reg:CC 100)
4222 (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
4223 (const_int 0)))
4224 (set (match_operand:QI 0 "register_operand" "=r")
4225 (subreg:QI (match_dup 1) 3))]
4226 ""
4227 "andcc\t%1, 0xff, %0"
4228 [(set_attr "type" "compare")])
4229
4230 (define_insn "*cmp_diqi_trunc"
4231 [(set (reg:CC 100)
4232 (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
4233 (const_int 0)))]
4234 "TARGET_ARCH64"
4235 "andcc\t%0, 0xff, %%g0"
4236 [(set_attr "type" "compare")])
4237
4238 (define_insn "*cmp_diqi_trunc_set"
4239 [(set (reg:CC 100)
4240 (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
4241 (const_int 0)))
4242 (set (match_operand:QI 0 "register_operand" "=r")
4243 (subreg:QI (match_dup 1) 7))]
4244 "TARGET_ARCH64"
4245 "andcc\t%1, 0xff, %0"
4246 [(set_attr "type" "compare")])
4247 \f
4248 ;;- sign extension instructions
4249
4250 ;; These patterns originally accepted general_operands, however, slightly
4251 ;; better code is generated by only accepting register_operands, and then
4252 ;; letting combine generate the lds[hb] insns.
4253
4254 (define_expand "extendhisi2"
4255 [(set (match_operand:SI 0 "register_operand" "")
4256 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4257 ""
4258 {
4259 rtx temp = gen_reg_rtx (SImode);
4260 rtx shift_16 = GEN_INT (16);
4261 int op1_subbyte = 0;
4262
4263 if (GET_CODE (operand1) == SUBREG)
4264 {
4265 op1_subbyte = SUBREG_BYTE (operand1);
4266 op1_subbyte /= GET_MODE_SIZE (SImode);
4267 op1_subbyte *= GET_MODE_SIZE (SImode);
4268 operand1 = XEXP (operand1, 0);
4269 }
4270
4271 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4272 shift_16));
4273 emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
4274 DONE;
4275 })
4276
4277 (define_insn "*sign_extendhisi2_insn"
4278 [(set (match_operand:SI 0 "register_operand" "=r")
4279 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4280 ""
4281 "ldsh\t%1, %0"
4282 [(set_attr "type" "sload")
4283 (set_attr "us3load_type" "3cycle")])
4284
4285 (define_expand "extendqihi2"
4286 [(set (match_operand:HI 0 "register_operand" "")
4287 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
4288 ""
4289 {
4290 rtx temp = gen_reg_rtx (SImode);
4291 rtx shift_24 = GEN_INT (24);
4292 int op1_subbyte = 0;
4293 int op0_subbyte = 0;
4294
4295 if (GET_CODE (operand1) == SUBREG)
4296 {
4297 op1_subbyte = SUBREG_BYTE (operand1);
4298 op1_subbyte /= GET_MODE_SIZE (SImode);
4299 op1_subbyte *= GET_MODE_SIZE (SImode);
4300 operand1 = XEXP (operand1, 0);
4301 }
4302 if (GET_CODE (operand0) == SUBREG)
4303 {
4304 op0_subbyte = SUBREG_BYTE (operand0);
4305 op0_subbyte /= GET_MODE_SIZE (SImode);
4306 op0_subbyte *= GET_MODE_SIZE (SImode);
4307 operand0 = XEXP (operand0, 0);
4308 }
4309 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4310 shift_24));
4311 if (GET_MODE (operand0) != SImode)
4312 operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
4313 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4314 DONE;
4315 })
4316
4317 (define_insn "*sign_extendqihi2_insn"
4318 [(set (match_operand:HI 0 "register_operand" "=r")
4319 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
4320 ""
4321 "ldsb\t%1, %0"
4322 [(set_attr "type" "sload")
4323 (set_attr "us3load_type" "3cycle")])
4324
4325 (define_expand "extendqisi2"
4326 [(set (match_operand:SI 0 "register_operand" "")
4327 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4328 ""
4329 {
4330 rtx temp = gen_reg_rtx (SImode);
4331 rtx shift_24 = GEN_INT (24);
4332 int op1_subbyte = 0;
4333
4334 if (GET_CODE (operand1) == SUBREG)
4335 {
4336 op1_subbyte = SUBREG_BYTE (operand1);
4337 op1_subbyte /= GET_MODE_SIZE (SImode);
4338 op1_subbyte *= GET_MODE_SIZE (SImode);
4339 operand1 = XEXP (operand1, 0);
4340 }
4341
4342 emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4343 shift_24));
4344 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4345 DONE;
4346 })
4347
4348 (define_insn "*sign_extendqisi2_insn"
4349 [(set (match_operand:SI 0 "register_operand" "=r")
4350 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4351 ""
4352 "ldsb\t%1, %0"
4353 [(set_attr "type" "sload")
4354 (set_attr "us3load_type" "3cycle")])
4355
4356 (define_expand "extendqidi2"
4357 [(set (match_operand:DI 0 "register_operand" "")
4358 (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
4359 "TARGET_ARCH64"
4360 {
4361 rtx temp = gen_reg_rtx (DImode);
4362 rtx shift_56 = GEN_INT (56);
4363 int op1_subbyte = 0;
4364
4365 if (GET_CODE (operand1) == SUBREG)
4366 {
4367 op1_subbyte = SUBREG_BYTE (operand1);
4368 op1_subbyte /= GET_MODE_SIZE (DImode);
4369 op1_subbyte *= GET_MODE_SIZE (DImode);
4370 operand1 = XEXP (operand1, 0);
4371 }
4372
4373 emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4374 shift_56));
4375 emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
4376 DONE;
4377 })
4378
4379 (define_insn "*sign_extendqidi2_insn"
4380 [(set (match_operand:DI 0 "register_operand" "=r")
4381 (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
4382 "TARGET_ARCH64"
4383 "ldsb\t%1, %0"
4384 [(set_attr "type" "sload")
4385 (set_attr "us3load_type" "3cycle")])
4386
4387 (define_expand "extendhidi2"
4388 [(set (match_operand:DI 0 "register_operand" "")
4389 (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
4390 "TARGET_ARCH64"
4391 {
4392 rtx temp = gen_reg_rtx (DImode);
4393 rtx shift_48 = GEN_INT (48);
4394 int op1_subbyte = 0;
4395
4396 if (GET_CODE (operand1) == SUBREG)
4397 {
4398 op1_subbyte = SUBREG_BYTE (operand1);
4399 op1_subbyte /= GET_MODE_SIZE (DImode);
4400 op1_subbyte *= GET_MODE_SIZE (DImode);
4401 operand1 = XEXP (operand1, 0);
4402 }
4403
4404 emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4405 shift_48));
4406 emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
4407 DONE;
4408 })
4409
4410 (define_insn "*sign_extendhidi2_insn"
4411 [(set (match_operand:DI 0 "register_operand" "=r")
4412 (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4413 "TARGET_ARCH64"
4414 "ldsh\t%1, %0"
4415 [(set_attr "type" "sload")
4416 (set_attr "us3load_type" "3cycle")])
4417
4418 (define_expand "extendsidi2"
4419 [(set (match_operand:DI 0 "register_operand" "")
4420 (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
4421 "TARGET_ARCH64"
4422 "")
4423
4424 (define_insn "*sign_extendsidi2_insn"
4425 [(set (match_operand:DI 0 "register_operand" "=r,r")
4426 (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4427 "TARGET_ARCH64"
4428 "@
4429 sra\t%1, 0, %0
4430 ldsw\t%1, %0"
4431 [(set_attr "type" "shift,sload")
4432 (set_attr "us3load_type" "*,3cycle")])
4433 \f
4434 ;; Special pattern for optimizing bit-field compares. This is needed
4435 ;; because combine uses this as a canonical form.
4436
4437 (define_insn "*cmp_zero_extract"
4438 [(set (reg:CC 100)
4439 (compare:CC
4440 (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
4441 (match_operand:SI 1 "small_int_or_double" "n")
4442 (match_operand:SI 2 "small_int_or_double" "n"))
4443 (const_int 0)))]
4444 "(GET_CODE (operands[2]) == CONST_INT
4445 && INTVAL (operands[2]) > 19)
4446 || (GET_CODE (operands[2]) == CONST_DOUBLE
4447 && CONST_DOUBLE_LOW (operands[2]) > 19)"
4448 {
4449 int len = (GET_CODE (operands[1]) == CONST_INT
4450 ? INTVAL (operands[1])
4451 : CONST_DOUBLE_LOW (operands[1]));
4452 int pos = 32 -
4453 (GET_CODE (operands[2]) == CONST_INT
4454 ? INTVAL (operands[2])
4455 : CONST_DOUBLE_LOW (operands[2])) - len;
4456 HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
4457
4458 operands[1] = GEN_INT (mask);
4459 return "andcc\t%0, %1, %%g0";
4460 }
4461 [(set_attr "type" "compare")])
4462
4463 (define_insn "*cmp_zero_extract_sp64"
4464 [(set (reg:CCX 100)
4465 (compare:CCX
4466 (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
4467 (match_operand:SI 1 "small_int_or_double" "n")
4468 (match_operand:SI 2 "small_int_or_double" "n"))
4469 (const_int 0)))]
4470 "TARGET_ARCH64
4471 && ((GET_CODE (operands[2]) == CONST_INT
4472 && INTVAL (operands[2]) > 51)
4473 || (GET_CODE (operands[2]) == CONST_DOUBLE
4474 && CONST_DOUBLE_LOW (operands[2]) > 51))"
4475 {
4476 int len = (GET_CODE (operands[1]) == CONST_INT
4477 ? INTVAL (operands[1])
4478 : CONST_DOUBLE_LOW (operands[1]));
4479 int pos = 64 -
4480 (GET_CODE (operands[2]) == CONST_INT
4481 ? INTVAL (operands[2])
4482 : CONST_DOUBLE_LOW (operands[2])) - len;
4483 HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
4484
4485 operands[1] = GEN_INT (mask);
4486 return "andcc\t%0, %1, %%g0";
4487 }
4488 [(set_attr "type" "compare")])
4489 \f
4490 ;; Conversions between float, double and long double.
4491
4492 (define_insn "extendsfdf2"
4493 [(set (match_operand:DF 0 "register_operand" "=e")
4494 (float_extend:DF
4495 (match_operand:SF 1 "register_operand" "f")))]
4496 "TARGET_FPU"
4497 "fstod\t%1, %0"
4498 [(set_attr "type" "fp")
4499 (set_attr "fptype" "double")])
4500
4501 (define_expand "extendsftf2"
4502 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4503 (float_extend:TF
4504 (match_operand:SF 1 "register_operand" "")))]
4505 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4506 "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
4507
4508 (define_insn "*extendsftf2_hq"
4509 [(set (match_operand:TF 0 "register_operand" "=e")
4510 (float_extend:TF
4511 (match_operand:SF 1 "register_operand" "f")))]
4512 "TARGET_FPU && TARGET_HARD_QUAD"
4513 "fstoq\t%1, %0"
4514 [(set_attr "type" "fp")])
4515
4516 (define_expand "extenddftf2"
4517 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4518 (float_extend:TF
4519 (match_operand:DF 1 "register_operand" "")))]
4520 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4521 "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
4522
4523 (define_insn "*extenddftf2_hq"
4524 [(set (match_operand:TF 0 "register_operand" "=e")
4525 (float_extend:TF
4526 (match_operand:DF 1 "register_operand" "e")))]
4527 "TARGET_FPU && TARGET_HARD_QUAD"
4528 "fdtoq\t%1, %0"
4529 [(set_attr "type" "fp")])
4530
4531 (define_insn "truncdfsf2"
4532 [(set (match_operand:SF 0 "register_operand" "=f")
4533 (float_truncate:SF
4534 (match_operand:DF 1 "register_operand" "e")))]
4535 "TARGET_FPU"
4536 "fdtos\t%1, %0"
4537 [(set_attr "type" "fp")
4538 (set_attr "fptype" "double")])
4539
4540 (define_expand "trunctfsf2"
4541 [(set (match_operand:SF 0 "register_operand" "")
4542 (float_truncate:SF
4543 (match_operand:TF 1 "general_operand" "")))]
4544 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4545 "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
4546
4547 (define_insn "*trunctfsf2_hq"
4548 [(set (match_operand:SF 0 "register_operand" "=f")
4549 (float_truncate:SF
4550 (match_operand:TF 1 "register_operand" "e")))]
4551 "TARGET_FPU && TARGET_HARD_QUAD"
4552 "fqtos\t%1, %0"
4553 [(set_attr "type" "fp")])
4554
4555 (define_expand "trunctfdf2"
4556 [(set (match_operand:DF 0 "register_operand" "")
4557 (float_truncate:DF
4558 (match_operand:TF 1 "general_operand" "")))]
4559 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4560 "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
4561
4562 (define_insn "*trunctfdf2_hq"
4563 [(set (match_operand:DF 0 "register_operand" "=e")
4564 (float_truncate:DF
4565 (match_operand:TF 1 "register_operand" "e")))]
4566 "TARGET_FPU && TARGET_HARD_QUAD"
4567 "fqtod\t%1, %0"
4568 [(set_attr "type" "fp")])
4569 \f
4570 ;; Conversion between fixed point and floating point.
4571
4572 (define_insn "floatsisf2"
4573 [(set (match_operand:SF 0 "register_operand" "=f")
4574 (float:SF (match_operand:SI 1 "register_operand" "f")))]
4575 "TARGET_FPU"
4576 "fitos\t%1, %0"
4577 [(set_attr "type" "fp")
4578 (set_attr "fptype" "double")])
4579
4580 (define_insn "floatsidf2"
4581 [(set (match_operand:DF 0 "register_operand" "=e")
4582 (float:DF (match_operand:SI 1 "register_operand" "f")))]
4583 "TARGET_FPU"
4584 "fitod\t%1, %0"
4585 [(set_attr "type" "fp")
4586 (set_attr "fptype" "double")])
4587
4588 (define_expand "floatsitf2"
4589 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4590 (float:TF (match_operand:SI 1 "register_operand" "")))]
4591 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4592 "emit_tfmode_cvt (FLOAT, operands); DONE;")
4593
4594 (define_insn "*floatsitf2_hq"
4595 [(set (match_operand:TF 0 "register_operand" "=e")
4596 (float:TF (match_operand:SI 1 "register_operand" "f")))]
4597 "TARGET_FPU && TARGET_HARD_QUAD"
4598 "fitoq\t%1, %0"
4599 [(set_attr "type" "fp")])
4600
4601 (define_expand "floatunssitf2"
4602 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4603 (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
4604 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4605 "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
4606
4607 ;; Now the same for 64 bit sources.
4608
4609 (define_insn "floatdisf2"
4610 [(set (match_operand:SF 0 "register_operand" "=f")
4611 (float:SF (match_operand:DI 1 "register_operand" "e")))]
4612 "TARGET_V9 && TARGET_FPU"
4613 "fxtos\t%1, %0"
4614 [(set_attr "type" "fp")
4615 (set_attr "fptype" "double")])
4616
4617 (define_expand "floatunsdisf2"
4618 [(use (match_operand:SF 0 "register_operand" ""))
4619 (use (match_operand:DI 1 "register_operand" ""))]
4620 "TARGET_ARCH64 && TARGET_FPU"
4621 "sparc_emit_floatunsdi (operands); DONE;")
4622
4623 (define_insn "floatdidf2"
4624 [(set (match_operand:DF 0 "register_operand" "=e")
4625 (float:DF (match_operand:DI 1 "register_operand" "e")))]
4626 "TARGET_V9 && TARGET_FPU"
4627 "fxtod\t%1, %0"
4628 [(set_attr "type" "fp")
4629 (set_attr "fptype" "double")])
4630
4631 (define_expand "floatunsdidf2"
4632 [(use (match_operand:DF 0 "register_operand" ""))
4633 (use (match_operand:DI 1 "register_operand" ""))]
4634 "TARGET_ARCH64 && TARGET_FPU"
4635 "sparc_emit_floatunsdi (operands); DONE;")
4636
4637 (define_expand "floatditf2"
4638 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4639 (float:TF (match_operand:DI 1 "register_operand" "")))]
4640 "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4641 "emit_tfmode_cvt (FLOAT, operands); DONE;")
4642
4643 (define_insn "*floatditf2_hq"
4644 [(set (match_operand:TF 0 "register_operand" "=e")
4645 (float:TF (match_operand:DI 1 "register_operand" "e")))]
4646 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4647 "fxtoq\t%1, %0"
4648 [(set_attr "type" "fp")])
4649
4650 (define_expand "floatunsditf2"
4651 [(set (match_operand:TF 0 "nonimmediate_operand" "")
4652 (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
4653 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4654 "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
4655
4656 ;; Convert a float to an actual integer.
4657 ;; Truncation is performed as part of the conversion.
4658
4659 (define_insn "fix_truncsfsi2"
4660 [(set (match_operand:SI 0 "register_operand" "=f")
4661 (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
4662 "TARGET_FPU"
4663 "fstoi\t%1, %0"
4664 [(set_attr "type" "fp")
4665 (set_attr "fptype" "double")])
4666
4667 (define_insn "fix_truncdfsi2"
4668 [(set (match_operand:SI 0 "register_operand" "=f")
4669 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
4670 "TARGET_FPU"
4671 "fdtoi\t%1, %0"
4672 [(set_attr "type" "fp")
4673 (set_attr "fptype" "double")])
4674
4675 (define_expand "fix_trunctfsi2"
4676 [(set (match_operand:SI 0 "register_operand" "")
4677 (fix:SI (match_operand:TF 1 "general_operand" "")))]
4678 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4679 "emit_tfmode_cvt (FIX, operands); DONE;")
4680
4681 (define_insn "*fix_trunctfsi2_hq"
4682 [(set (match_operand:SI 0 "register_operand" "=f")
4683 (fix:SI (match_operand:TF 1 "register_operand" "e")))]
4684 "TARGET_FPU && TARGET_HARD_QUAD"
4685 "fqtoi\t%1, %0"
4686 [(set_attr "type" "fp")])
4687
4688 (define_expand "fixuns_trunctfsi2"
4689 [(set (match_operand:SI 0 "register_operand" "")
4690 (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
4691 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4692 "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
4693
4694 ;; Now the same, for V9 targets
4695
4696 (define_insn "fix_truncsfdi2"
4697 [(set (match_operand:DI 0 "register_operand" "=e")
4698 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
4699 "TARGET_V9 && TARGET_FPU"
4700 "fstox\t%1, %0"
4701 [(set_attr "type" "fp")
4702 (set_attr "fptype" "double")])
4703
4704 (define_insn "fix_truncdfdi2"
4705 [(set (match_operand:DI 0 "register_operand" "=e")
4706 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
4707 "TARGET_V9 && TARGET_FPU"
4708 "fdtox\t%1, %0"
4709 [(set_attr "type" "fp")
4710 (set_attr "fptype" "double")])
4711
4712 (define_expand "fix_trunctfdi2"
4713 [(set (match_operand:DI 0 "register_operand" "")
4714 (fix:DI (match_operand:TF 1 "general_operand" "")))]
4715 "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4716 "emit_tfmode_cvt (FIX, operands); DONE;")
4717
4718 (define_insn "*fix_trunctfdi2_hq"
4719 [(set (match_operand:DI 0 "register_operand" "=e")
4720 (fix:DI (match_operand:TF 1 "register_operand" "e")))]
4721 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4722 "fqtox\t%1, %0"
4723 [(set_attr "type" "fp")])
4724
4725 (define_expand "fixuns_trunctfdi2"
4726 [(set (match_operand:DI 0 "register_operand" "")
4727 (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
4728 "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4729 "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
4730 \f
4731 ;;- arithmetic instructions
4732
4733 (define_expand "adddi3"
4734 [(set (match_operand:DI 0 "register_operand" "=r")
4735 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4736 (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
4737 ""
4738 {
4739 HOST_WIDE_INT i;
4740
4741 if (! TARGET_ARCH64)
4742 {
4743 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
4744 gen_rtx_SET (VOIDmode, operands[0],
4745 gen_rtx_PLUS (DImode, operands[1],
4746 operands[2])),
4747 gen_rtx_CLOBBER (VOIDmode,
4748 gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
4749 DONE;
4750 }
4751 if (arith_double_4096_operand(operands[2], DImode))
4752 {
4753 switch (GET_CODE (operands[1]))
4754 {
4755 case CONST_INT: i = INTVAL (operands[1]); break;
4756 case CONST_DOUBLE: i = CONST_DOUBLE_LOW (operands[1]); break;
4757 default:
4758 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4759 gen_rtx_MINUS (DImode, operands[1],
4760 GEN_INT(-4096))));
4761 DONE;
4762 }
4763 emit_insn (gen_movdi (operands[0], GEN_INT (i + 4096)));
4764 DONE;
4765 }
4766 })
4767
4768 (define_insn_and_split "adddi3_insn_sp32"
4769 [(set (match_operand:DI 0 "register_operand" "=r")
4770 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4771 (match_operand:DI 2 "arith_double_operand" "rHI")))
4772 (clobber (reg:CC 100))]
4773 "! TARGET_ARCH64"
4774 "#"
4775 "&& reload_completed"
4776 [(parallel [(set (reg:CC_NOOV 100)
4777 (compare:CC_NOOV (plus:SI (match_dup 4)
4778 (match_dup 5))
4779 (const_int 0)))
4780 (set (match_dup 3)
4781 (plus:SI (match_dup 4) (match_dup 5)))])
4782 (set (match_dup 6)
4783 (plus:SI (plus:SI (match_dup 7)
4784 (match_dup 8))
4785 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4786 {
4787 operands[3] = gen_lowpart (SImode, operands[0]);
4788 operands[4] = gen_lowpart (SImode, operands[1]);
4789 operands[5] = gen_lowpart (SImode, operands[2]);
4790 operands[6] = gen_highpart (SImode, operands[0]);
4791 operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
4792 #if HOST_BITS_PER_WIDE_INT == 32
4793 if (GET_CODE (operands[2]) == CONST_INT)
4794 {
4795 if (INTVAL (operands[2]) < 0)
4796 operands[8] = constm1_rtx;
4797 else
4798 operands[8] = const0_rtx;
4799 }
4800 else
4801 #endif
4802 operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
4803 }
4804 [(set_attr "length" "2")])
4805
4806 (define_split
4807 [(set (match_operand:DI 0 "register_operand" "")
4808 (minus:DI (match_operand:DI 1 "arith_double_operand" "")
4809 (match_operand:DI 2 "arith_double_operand" "")))
4810 (clobber (reg:CC 100))]
4811 "! TARGET_ARCH64 && reload_completed"
4812 [(parallel [(set (reg:CC_NOOV 100)
4813 (compare:CC_NOOV (minus:SI (match_dup 4)
4814 (match_dup 5))
4815 (const_int 0)))
4816 (set (match_dup 3)
4817 (minus:SI (match_dup 4) (match_dup 5)))])
4818 (set (match_dup 6)
4819 (minus:SI (minus:SI (match_dup 7)
4820 (match_dup 8))
4821 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4822 {
4823 operands[3] = gen_lowpart (SImode, operands[0]);
4824 operands[4] = gen_lowpart (SImode, operands[1]);
4825 operands[5] = gen_lowpart (SImode, operands[2]);
4826 operands[6] = gen_highpart (SImode, operands[0]);
4827 operands[7] = gen_highpart (SImode, operands[1]);
4828 #if HOST_BITS_PER_WIDE_INT == 32
4829 if (GET_CODE (operands[2]) == CONST_INT)
4830 {
4831 if (INTVAL (operands[2]) < 0)
4832 operands[8] = constm1_rtx;
4833 else
4834 operands[8] = const0_rtx;
4835 }
4836 else
4837 #endif
4838 operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
4839 })
4840
4841 ;; LTU here means "carry set"
4842 (define_insn "addx"
4843 [(set (match_operand:SI 0 "register_operand" "=r")
4844 (plus:SI (plus:SI (match_operand:SI 1 "arith_operand" "%r")
4845 (match_operand:SI 2 "arith_operand" "rI"))
4846 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4847 ""
4848 "addx\t%1, %2, %0"
4849 [(set_attr "type" "ialuX")])
4850
4851 (define_insn_and_split "*addx_extend_sp32"
4852 [(set (match_operand:DI 0 "register_operand" "=r")
4853 (zero_extend:DI (plus:SI (plus:SI
4854 (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4855 (match_operand:SI 2 "arith_operand" "rI"))
4856 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4857 "! TARGET_ARCH64"
4858 "#"
4859 "&& reload_completed"
4860 [(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
4861 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
4862 (set (match_dup 4) (const_int 0))]
4863 "operands[3] = gen_lowpart (SImode, operands[0]);
4864 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);"
4865 [(set_attr "length" "2")])
4866
4867 (define_insn "*addx_extend_sp64"
4868 [(set (match_operand:DI 0 "register_operand" "=r")
4869 (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4870 (match_operand:SI 2 "arith_operand" "rI"))
4871 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4872 "TARGET_ARCH64"
4873 "addx\t%r1, %2, %0"
4874 [(set_attr "type" "ialuX")])
4875
4876 (define_insn "subx"
4877 [(set (match_operand:SI 0 "register_operand" "=r")
4878 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4879 (match_operand:SI 2 "arith_operand" "rI"))
4880 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4881 ""
4882 "subx\t%r1, %2, %0"
4883 [(set_attr "type" "ialuX")])
4884
4885 (define_insn "*subx_extend_sp64"
4886 [(set (match_operand:DI 0 "register_operand" "=r")
4887 (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4888 (match_operand:SI 2 "arith_operand" "rI"))
4889 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4890 "TARGET_ARCH64"
4891 "subx\t%r1, %2, %0"
4892 [(set_attr "type" "ialuX")])
4893
4894 (define_insn_and_split "*subx_extend"
4895 [(set (match_operand:DI 0 "register_operand" "=r")
4896 (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4897 (match_operand:SI 2 "arith_operand" "rI"))
4898 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4899 "! TARGET_ARCH64"
4900 "#"
4901 "&& reload_completed"
4902 [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
4903 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
4904 (set (match_dup 4) (const_int 0))]
4905 "operands[3] = gen_lowpart (SImode, operands[0]);
4906 operands[4] = gen_highpart (SImode, operands[0]);"
4907 [(set_attr "length" "2")])
4908
4909 (define_insn_and_split ""
4910 [(set (match_operand:DI 0 "register_operand" "=r")
4911 (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4912 (match_operand:DI 2 "register_operand" "r")))
4913 (clobber (reg:CC 100))]
4914 "! TARGET_ARCH64"
4915 "#"
4916 "&& reload_completed"
4917 [(parallel [(set (reg:CC_NOOV 100)
4918 (compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
4919 (const_int 0)))
4920 (set (match_dup 5) (plus:SI (match_dup 3) (match_dup 1)))])
4921 (set (match_dup 6)
4922 (plus:SI (plus:SI (match_dup 4) (const_int 0))
4923 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4924 "operands[3] = gen_lowpart (SImode, operands[2]);
4925 operands[4] = gen_highpart (SImode, operands[2]);
4926 operands[5] = gen_lowpart (SImode, operands[0]);
4927 operands[6] = gen_highpart (SImode, operands[0]);"
4928 [(set_attr "length" "2")])
4929
4930 (define_insn "*adddi3_sp64"
4931 [(set (match_operand:DI 0 "register_operand" "=r")
4932 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4933 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4934 "TARGET_ARCH64"
4935 "add\t%1, %2, %0")
4936
4937 (define_expand "addsi3"
4938 [(set (match_operand:SI 0 "register_operand" "=r,d")
4939 (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
4940 (match_operand:SI 2 "arith_add_operand" "rI,d")))]
4941 ""
4942 {
4943 if (arith_4096_operand(operands[2], SImode))
4944 {
4945 if (GET_CODE (operands[1]) == CONST_INT)
4946 emit_insn (gen_movsi (operands[0],
4947 GEN_INT (INTVAL (operands[1]) + 4096)));
4948 else
4949 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4950 gen_rtx_MINUS (SImode, operands[1],
4951 GEN_INT(-4096))));
4952 DONE;
4953 }
4954 })
4955
4956 (define_insn "*addsi3"
4957 [(set (match_operand:SI 0 "register_operand" "=r,d")
4958 (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
4959 (match_operand:SI 2 "arith_operand" "rI,d")))]
4960 ""
4961 "@
4962 add\t%1, %2, %0
4963 fpadd32s\t%1, %2, %0"
4964 [(set_attr "type" "*,fp")])
4965
4966 (define_insn "*cmp_cc_plus"
4967 [(set (reg:CC_NOOV 100)
4968 (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
4969 (match_operand:SI 1 "arith_operand" "rI"))
4970 (const_int 0)))]
4971 ""
4972 "addcc\t%0, %1, %%g0"
4973 [(set_attr "type" "compare")])
4974
4975 (define_insn "*cmp_ccx_plus"
4976 [(set (reg:CCX_NOOV 100)
4977 (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
4978 (match_operand:DI 1 "arith_double_operand" "rHI"))
4979 (const_int 0)))]
4980 "TARGET_ARCH64"
4981 "addcc\t%0, %1, %%g0"
4982 [(set_attr "type" "compare")])
4983
4984 (define_insn "*cmp_cc_plus_set"
4985 [(set (reg:CC_NOOV 100)
4986 (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
4987 (match_operand:SI 2 "arith_operand" "rI"))
4988 (const_int 0)))
4989 (set (match_operand:SI 0 "register_operand" "=r")
4990 (plus:SI (match_dup 1) (match_dup 2)))]
4991 ""
4992 "addcc\t%1, %2, %0"
4993 [(set_attr "type" "compare")])
4994
4995 (define_insn "*cmp_ccx_plus_set"
4996 [(set (reg:CCX_NOOV 100)
4997 (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4998 (match_operand:DI 2 "arith_double_operand" "rHI"))
4999 (const_int 0)))
5000 (set (match_operand:DI 0 "register_operand" "=r")
5001 (plus:DI (match_dup 1) (match_dup 2)))]
5002 "TARGET_ARCH64"
5003 "addcc\t%1, %2, %0"
5004 [(set_attr "type" "compare")])
5005
5006 (define_expand "subdi3"
5007 [(set (match_operand:DI 0 "register_operand" "=r")
5008 (minus:DI (match_operand:DI 1 "register_operand" "r")
5009 (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
5010 ""
5011 {
5012 if (! TARGET_ARCH64)
5013 {
5014 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
5015 gen_rtx_SET (VOIDmode, operands[0],
5016 gen_rtx_MINUS (DImode, operands[1],
5017 operands[2])),
5018 gen_rtx_CLOBBER (VOIDmode,
5019 gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
5020 DONE;
5021 }
5022 if (arith_double_4096_operand(operands[2], DImode))
5023 {
5024 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5025 gen_rtx_PLUS (DImode, operands[1],
5026 GEN_INT(-4096))));
5027 DONE;
5028 }
5029 })
5030
5031 (define_insn_and_split "*subdi3_sp32"
5032 [(set (match_operand:DI 0 "register_operand" "=r")
5033 (minus:DI (match_operand:DI 1 "register_operand" "r")
5034 (match_operand:DI 2 "arith_double_operand" "rHI")))
5035 (clobber (reg:CC 100))]
5036 "! TARGET_ARCH64"
5037 "#"
5038 "&& reload_completed
5039 && (GET_CODE (operands[2]) == CONST_INT
5040 || GET_CODE (operands[2]) == CONST_DOUBLE)"
5041 [(clobber (const_int 0))]
5042 {
5043 rtx highp, lowp;
5044
5045 highp = gen_highpart_mode (SImode, DImode, operands[2]);
5046 lowp = gen_lowpart (SImode, operands[2]);
5047 if ((lowp == const0_rtx)
5048 && (operands[0] == operands[1]))
5049 {
5050 emit_insn (gen_rtx_SET (VOIDmode,
5051 gen_highpart (SImode, operands[0]),
5052 gen_rtx_MINUS (SImode,
5053 gen_highpart_mode (SImode, DImode,
5054 operands[1]),
5055 highp)));
5056 }
5057 else
5058 {
5059 emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5060 gen_lowpart (SImode, operands[1]),
5061 lowp));
5062 emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5063 gen_highpart_mode (SImode, DImode, operands[1]),
5064 highp));
5065 }
5066 DONE;
5067 }
5068 [(set_attr "length" "2")])
5069
5070 (define_split
5071 [(set (match_operand:DI 0 "register_operand" "")
5072 (minus:DI (match_operand:DI 1 "register_operand" "")
5073 (match_operand:DI 2 "register_operand" "")))
5074 (clobber (reg:CC 100))]
5075 "! TARGET_ARCH64
5076 && reload_completed"
5077 [(clobber (const_int 0))]
5078 {
5079 emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5080 gen_lowpart (SImode, operands[1]),
5081 gen_lowpart (SImode, operands[2])));
5082 emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5083 gen_highpart (SImode, operands[1]),
5084 gen_highpart (SImode, operands[2])));
5085 DONE;
5086 })
5087
5088 (define_insn_and_split ""
5089 [(set (match_operand:DI 0 "register_operand" "=r")
5090 (minus:DI (match_operand:DI 1 "register_operand" "r")
5091 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
5092 (clobber (reg:CC 100))]
5093 "! TARGET_ARCH64"
5094 "#"
5095 "&& reload_completed"
5096 [(parallel [(set (reg:CC_NOOV 100)
5097 (compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
5098 (const_int 0)))
5099 (set (match_dup 5) (minus:SI (match_dup 3) (match_dup 2)))])
5100 (set (match_dup 6)
5101 (minus:SI (minus:SI (match_dup 4) (const_int 0))
5102 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5103 "operands[3] = gen_lowpart (SImode, operands[1]);
5104 operands[4] = gen_highpart (SImode, operands[1]);
5105 operands[5] = gen_lowpart (SImode, operands[0]);
5106 operands[6] = gen_highpart (SImode, operands[0]);"
5107 [(set_attr "length" "2")])
5108
5109 (define_insn "*subdi3_sp64"
5110 [(set (match_operand:DI 0 "register_operand" "=r")
5111 (minus:DI (match_operand:DI 1 "register_operand" "r")
5112 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5113 "TARGET_ARCH64"
5114 "sub\t%1, %2, %0")
5115
5116 (define_expand "subsi3"
5117 [(set (match_operand:SI 0 "register_operand" "=r,d")
5118 (minus:SI (match_operand:SI 1 "register_operand" "r,d")
5119 (match_operand:SI 2 "arith_add_operand" "rI,d")))]
5120 ""
5121 {
5122 if (arith_4096_operand(operands[2], SImode))
5123 {
5124 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5125 gen_rtx_PLUS (SImode, operands[1],
5126 GEN_INT(-4096))));
5127 DONE;
5128 }
5129 })
5130
5131 (define_insn "*subsi3"
5132 [(set (match_operand:SI 0 "register_operand" "=r,d")
5133 (minus:SI (match_operand:SI 1 "register_operand" "r,d")
5134 (match_operand:SI 2 "arith_operand" "rI,d")))]
5135 ""
5136 "@
5137 sub\t%1, %2, %0
5138 fpsub32s\t%1, %2, %0"
5139 [(set_attr "type" "*,fp")])
5140
5141 (define_insn "*cmp_minus_cc"
5142 [(set (reg:CC_NOOV 100)
5143 (compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
5144 (match_operand:SI 1 "arith_operand" "rI"))
5145 (const_int 0)))]
5146 ""
5147 "subcc\t%r0, %1, %%g0"
5148 [(set_attr "type" "compare")])
5149
5150 (define_insn "*cmp_minus_ccx"
5151 [(set (reg:CCX_NOOV 100)
5152 (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
5153 (match_operand:DI 1 "arith_double_operand" "rHI"))
5154 (const_int 0)))]
5155 "TARGET_ARCH64"
5156 "subcc\t%0, %1, %%g0"
5157 [(set_attr "type" "compare")])
5158
5159 (define_insn "cmp_minus_cc_set"
5160 [(set (reg:CC_NOOV 100)
5161 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5162 (match_operand:SI 2 "arith_operand" "rI"))
5163 (const_int 0)))
5164 (set (match_operand:SI 0 "register_operand" "=r")
5165 (minus:SI (match_dup 1) (match_dup 2)))]
5166 ""
5167 "subcc\t%r1, %2, %0"
5168 [(set_attr "type" "compare")])
5169
5170 (define_insn "*cmp_minus_ccx_set"
5171 [(set (reg:CCX_NOOV 100)
5172 (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
5173 (match_operand:DI 2 "arith_double_operand" "rHI"))
5174 (const_int 0)))
5175 (set (match_operand:DI 0 "register_operand" "=r")
5176 (minus:DI (match_dup 1) (match_dup 2)))]
5177 "TARGET_ARCH64"
5178 "subcc\t%1, %2, %0"
5179 [(set_attr "type" "compare")])
5180 \f
5181 ;; Integer Multiply/Divide.
5182
5183 ;; The 32 bit multiply/divide instructions are deprecated on v9, but at
5184 ;; least in UltraSPARC I, II and IIi it is a win tick-wise.
5185
5186 (define_insn "mulsi3"
5187 [(set (match_operand:SI 0 "register_operand" "=r")
5188 (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5189 (match_operand:SI 2 "arith_operand" "rI")))]
5190 "TARGET_HARD_MUL"
5191 "smul\t%1, %2, %0"
5192 [(set_attr "type" "imul")])
5193
5194 (define_expand "muldi3"
5195 [(set (match_operand:DI 0 "register_operand" "=r")
5196 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5197 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5198 "TARGET_ARCH64 || TARGET_V8PLUS"
5199 {
5200 if (TARGET_V8PLUS)
5201 {
5202 emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2]));
5203 DONE;
5204 }
5205 })
5206
5207 (define_insn "*muldi3_sp64"
5208 [(set (match_operand:DI 0 "register_operand" "=r")
5209 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5210 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5211 "TARGET_ARCH64"
5212 "mulx\t%1, %2, %0"
5213 [(set_attr "type" "imul")])
5214
5215 ;; V8plus wide multiply.
5216 ;; XXX
5217 (define_insn "muldi3_v8plus"
5218 [(set (match_operand:DI 0 "register_operand" "=r,h")
5219 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
5220 (match_operand:DI 2 "arith_double_operand" "rI,rI")))
5221 (clobber (match_scratch:SI 3 "=&h,X"))
5222 (clobber (match_scratch:SI 4 "=&h,X"))]
5223 "TARGET_V8PLUS"
5224 {
5225 if (sparc_check_64 (operands[1], insn) <= 0)
5226 output_asm_insn ("srl\t%L1, 0, %L1", operands);
5227 if (which_alternative == 1)
5228 output_asm_insn ("sllx\t%H1, 32, %H1", operands);
5229 if (GET_CODE (operands[2]) == CONST_INT)
5230 {
5231 if (which_alternative == 1)
5232 return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %2, %L0\;srlx\t%L0, 32, %H0";
5233 else
5234 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";
5235 }
5236 else if (rtx_equal_p (operands[1], operands[2]))
5237 {
5238 if (which_alternative == 1)
5239 return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %H1, %L0\;srlx\t%L0, 32, %H0";
5240 else
5241 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";
5242 }
5243 if (sparc_check_64 (operands[2], insn) <= 0)
5244 output_asm_insn ("srl\t%L2, 0, %L2", operands);
5245 if (which_alternative == 1)
5246 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";
5247 else
5248 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";
5249 }
5250 [(set_attr "type" "multi")
5251 (set_attr "length" "9,8")])
5252
5253 (define_insn "*cmp_mul_set"
5254 [(set (reg:CC 100)
5255 (compare:CC (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5256 (match_operand:SI 2 "arith_operand" "rI"))
5257 (const_int 0)))
5258 (set (match_operand:SI 0 "register_operand" "=r")
5259 (mult:SI (match_dup 1) (match_dup 2)))]
5260 "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
5261 "smulcc\t%1, %2, %0"
5262 [(set_attr "type" "imul")])
5263
5264 (define_expand "mulsidi3"
5265 [(set (match_operand:DI 0 "register_operand" "")
5266 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
5267 (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
5268 "TARGET_HARD_MUL"
5269 {
5270 if (CONSTANT_P (operands[2]))
5271 {
5272 if (TARGET_V8PLUS)
5273 emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
5274 operands[2]));
5275 else
5276 emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
5277 operands[2]));
5278 DONE;
5279 }
5280 if (TARGET_V8PLUS)
5281 {
5282 emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2]));
5283 DONE;
5284 }
5285 })
5286
5287 ;; V9 puts the 64 bit product in a 64 bit register. Only out or global
5288 ;; registers can hold 64 bit values in the V8plus environment.
5289 ;; XXX
5290 (define_insn "mulsidi3_v8plus"
5291 [(set (match_operand:DI 0 "register_operand" "=h,r")
5292 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5293 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
5294 (clobber (match_scratch:SI 3 "=X,&h"))]
5295 "TARGET_V8PLUS"
5296 "@
5297 smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5298 smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5299 [(set_attr "type" "multi")
5300 (set_attr "length" "2,3")])
5301
5302 ;; XXX
5303 (define_insn "const_mulsidi3_v8plus"
5304 [(set (match_operand:DI 0 "register_operand" "=h,r")
5305 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5306 (match_operand:SI 2 "small_int" "I,I")))
5307 (clobber (match_scratch:SI 3 "=X,&h"))]
5308 "TARGET_V8PLUS"
5309 "@
5310 smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5311 smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5312 [(set_attr "type" "multi")
5313 (set_attr "length" "2,3")])
5314
5315 ;; XXX
5316 (define_insn "*mulsidi3_sp32"
5317 [(set (match_operand:DI 0 "register_operand" "=r")
5318 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5319 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5320 "TARGET_HARD_MUL32"
5321 {
5322 return TARGET_SPARCLET
5323 ? "smuld\t%1, %2, %L0"
5324 : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
5325 }
5326 [(set (attr "type")
5327 (if_then_else (eq_attr "isa" "sparclet")
5328 (const_string "imul") (const_string "multi")))
5329 (set (attr "length")
5330 (if_then_else (eq_attr "isa" "sparclet")
5331 (const_int 1) (const_int 2)))])
5332
5333 (define_insn "*mulsidi3_sp64"
5334 [(set (match_operand:DI 0 "register_operand" "=r")
5335 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5336 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5337 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5338 "smul\t%1, %2, %0"
5339 [(set_attr "type" "imul")])
5340
5341 ;; Extra pattern, because sign_extend of a constant isn't valid.
5342
5343 ;; XXX
5344 (define_insn "const_mulsidi3_sp32"
5345 [(set (match_operand:DI 0 "register_operand" "=r")
5346 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5347 (match_operand:SI 2 "small_int" "I")))]
5348 "TARGET_HARD_MUL32"
5349 {
5350 return TARGET_SPARCLET
5351 ? "smuld\t%1, %2, %L0"
5352 : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
5353 }
5354 [(set (attr "type")
5355 (if_then_else (eq_attr "isa" "sparclet")
5356 (const_string "imul") (const_string "multi")))
5357 (set (attr "length")
5358 (if_then_else (eq_attr "isa" "sparclet")
5359 (const_int 1) (const_int 2)))])
5360
5361 (define_insn "const_mulsidi3_sp64"
5362 [(set (match_operand:DI 0 "register_operand" "=r")
5363 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5364 (match_operand:SI 2 "small_int" "I")))]
5365 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5366 "smul\t%1, %2, %0"
5367 [(set_attr "type" "imul")])
5368
5369 (define_expand "smulsi3_highpart"
5370 [(set (match_operand:SI 0 "register_operand" "")
5371 (truncate:SI
5372 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
5373 (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
5374 (const_int 32))))]
5375 "TARGET_HARD_MUL && TARGET_ARCH32"
5376 {
5377 if (CONSTANT_P (operands[2]))
5378 {
5379 if (TARGET_V8PLUS)
5380 {
5381 emit_insn (gen_const_smulsi3_highpart_v8plus (operands[0],
5382 operands[1],
5383 operands[2],
5384 GEN_INT (32)));
5385 DONE;
5386 }
5387 emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
5388 DONE;
5389 }
5390 if (TARGET_V8PLUS)
5391 {
5392 emit_insn (gen_smulsi3_highpart_v8plus (operands[0], operands[1],
5393 operands[2], GEN_INT (32)));
5394 DONE;
5395 }
5396 })
5397
5398 ;; XXX
5399 (define_insn "smulsi3_highpart_v8plus"
5400 [(set (match_operand:SI 0 "register_operand" "=h,r")
5401 (truncate:SI
5402 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5403 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5404 (match_operand:SI 3 "const_int_operand" "i,i"))))
5405 (clobber (match_scratch:SI 4 "=X,&h"))]
5406 "TARGET_V8PLUS"
5407 "@
5408 smul\t%1, %2, %0\;srlx\t%0, %3, %0
5409 smul\t%1, %2, %4\;srlx\t%4, %3, %0"
5410 [(set_attr "type" "multi")
5411 (set_attr "length" "2")])
5412
5413 ;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
5414 ;; XXX
5415 (define_insn ""
5416 [(set (match_operand:SI 0 "register_operand" "=h,r")
5417 (subreg:SI
5418 (lshiftrt:DI
5419 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5420 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5421 (match_operand:SI 3 "const_int_operand" "i,i"))
5422 4))
5423 (clobber (match_scratch:SI 4 "=X,&h"))]
5424 "TARGET_V8PLUS"
5425 "@
5426 smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5427 smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5428 [(set_attr "type" "multi")
5429 (set_attr "length" "2")])
5430
5431 ;; XXX
5432 (define_insn "const_smulsi3_highpart_v8plus"
5433 [(set (match_operand:SI 0 "register_operand" "=h,r")
5434 (truncate:SI
5435 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5436 (match_operand 2 "small_int" "i,i"))
5437 (match_operand:SI 3 "const_int_operand" "i,i"))))
5438 (clobber (match_scratch:SI 4 "=X,&h"))]
5439 "TARGET_V8PLUS"
5440 "@
5441 smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5442 smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5443 [(set_attr "type" "multi")
5444 (set_attr "length" "2")])
5445
5446 ;; XXX
5447 (define_insn "*smulsi3_highpart_sp32"
5448 [(set (match_operand:SI 0 "register_operand" "=r")
5449 (truncate:SI
5450 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5451 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
5452 (const_int 32))))]
5453 "TARGET_HARD_MUL32"
5454 "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
5455 [(set_attr "type" "multi")
5456 (set_attr "length" "2")])
5457
5458 ;; XXX
5459 (define_insn "const_smulsi3_highpart"
5460 [(set (match_operand:SI 0 "register_operand" "=r")
5461 (truncate:SI
5462 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5463 (match_operand:SI 2 "register_operand" "r"))
5464 (const_int 32))))]
5465 "TARGET_HARD_MUL32"
5466 "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
5467 [(set_attr "type" "multi")
5468 (set_attr "length" "2")])
5469
5470 (define_expand "umulsidi3"
5471 [(set (match_operand:DI 0 "register_operand" "")
5472 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5473 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
5474 "TARGET_HARD_MUL"
5475 {
5476 if (CONSTANT_P (operands[2]))
5477 {
5478 if (TARGET_V8PLUS)
5479 emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
5480 operands[2]));
5481 else
5482 emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
5483 operands[2]));
5484 DONE;
5485 }
5486 if (TARGET_V8PLUS)
5487 {
5488 emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2]));
5489 DONE;
5490 }
5491 })
5492
5493 ;; XXX
5494 (define_insn "umulsidi3_v8plus"
5495 [(set (match_operand:DI 0 "register_operand" "=h,r")
5496 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5497 (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
5498 (clobber (match_scratch:SI 3 "=X,&h"))]
5499 "TARGET_V8PLUS"
5500 "@
5501 umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5502 umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5503 [(set_attr "type" "multi")
5504 (set_attr "length" "2,3")])
5505
5506 ;; XXX
5507 (define_insn "*umulsidi3_sp32"
5508 [(set (match_operand:DI 0 "register_operand" "=r")
5509 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5510 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5511 "TARGET_HARD_MUL32"
5512 {
5513 return TARGET_SPARCLET
5514 ? "umuld\t%1, %2, %L0"
5515 : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
5516 }
5517 [(set (attr "type")
5518 (if_then_else (eq_attr "isa" "sparclet")
5519 (const_string "imul") (const_string "multi")))
5520 (set (attr "length")
5521 (if_then_else (eq_attr "isa" "sparclet")
5522 (const_int 1) (const_int 2)))])
5523
5524 (define_insn "*umulsidi3_sp64"
5525 [(set (match_operand:DI 0 "register_operand" "=r")
5526 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5527 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5528 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5529 "umul\t%1, %2, %0"
5530 [(set_attr "type" "imul")])
5531
5532 ;; Extra pattern, because sign_extend of a constant isn't valid.
5533
5534 ;; XXX
5535 (define_insn "const_umulsidi3_sp32"
5536 [(set (match_operand:DI 0 "register_operand" "=r")
5537 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5538 (match_operand:SI 2 "uns_small_int" "")))]
5539 "TARGET_HARD_MUL32"
5540 {
5541 return TARGET_SPARCLET
5542 ? "umuld\t%1, %2, %L0"
5543 : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
5544 }
5545 [(set (attr "type")
5546 (if_then_else (eq_attr "isa" "sparclet")
5547 (const_string "imul") (const_string "multi")))
5548 (set (attr "length")
5549 (if_then_else (eq_attr "isa" "sparclet")
5550 (const_int 1) (const_int 2)))])
5551
5552 (define_insn "const_umulsidi3_sp64"
5553 [(set (match_operand:DI 0 "register_operand" "=r")
5554 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5555 (match_operand:SI 2 "uns_small_int" "")))]
5556 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5557 "umul\t%1, %2, %0"
5558 [(set_attr "type" "imul")])
5559
5560 ;; XXX
5561 (define_insn "const_umulsidi3_v8plus"
5562 [(set (match_operand:DI 0 "register_operand" "=h,r")
5563 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5564 (match_operand:SI 2 "uns_small_int" "")))
5565 (clobber (match_scratch:SI 3 "=X,h"))]
5566 "TARGET_V8PLUS"
5567 "@
5568 umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5569 umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5570 [(set_attr "type" "multi")
5571 (set_attr "length" "2,3")])
5572
5573 (define_expand "umulsi3_highpart"
5574 [(set (match_operand:SI 0 "register_operand" "")
5575 (truncate:SI
5576 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5577 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
5578 (const_int 32))))]
5579 "TARGET_HARD_MUL && TARGET_ARCH32"
5580 {
5581 if (CONSTANT_P (operands[2]))
5582 {
5583 if (TARGET_V8PLUS)
5584 {
5585 emit_insn (gen_const_umulsi3_highpart_v8plus (operands[0],
5586 operands[1],
5587 operands[2],
5588 GEN_INT (32)));
5589 DONE;
5590 }
5591 emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
5592 DONE;
5593 }
5594 if (TARGET_V8PLUS)
5595 {
5596 emit_insn (gen_umulsi3_highpart_v8plus (operands[0], operands[1],
5597 operands[2], GEN_INT (32)));
5598 DONE;
5599 }
5600 })
5601
5602 ;; XXX
5603 (define_insn "umulsi3_highpart_v8plus"
5604 [(set (match_operand:SI 0 "register_operand" "=h,r")
5605 (truncate:SI
5606 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5607 (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5608 (match_operand:SI 3 "const_int_operand" "i,i"))))
5609 (clobber (match_scratch:SI 4 "=X,h"))]
5610 "TARGET_V8PLUS"
5611 "@
5612 umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5613 umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5614 [(set_attr "type" "multi")
5615 (set_attr "length" "2")])
5616
5617 ;; XXX
5618 (define_insn "const_umulsi3_highpart_v8plus"
5619 [(set (match_operand:SI 0 "register_operand" "=h,r")
5620 (truncate:SI
5621 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5622 (match_operand:SI 2 "uns_small_int" ""))
5623 (match_operand:SI 3 "const_int_operand" "i,i"))))
5624 (clobber (match_scratch:SI 4 "=X,h"))]
5625 "TARGET_V8PLUS"
5626 "@
5627 umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5628 umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5629 [(set_attr "type" "multi")
5630 (set_attr "length" "2")])
5631
5632 ;; XXX
5633 (define_insn "*umulsi3_highpart_sp32"
5634 [(set (match_operand:SI 0 "register_operand" "=r")
5635 (truncate:SI
5636 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5637 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
5638 (const_int 32))))]
5639 "TARGET_HARD_MUL32"
5640 "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
5641 [(set_attr "type" "multi")
5642 (set_attr "length" "2")])
5643
5644 ;; XXX
5645 (define_insn "const_umulsi3_highpart"
5646 [(set (match_operand:SI 0 "register_operand" "=r")
5647 (truncate:SI
5648 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5649 (match_operand:SI 2 "uns_small_int" ""))
5650 (const_int 32))))]
5651 "TARGET_HARD_MUL32"
5652 "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
5653 [(set_attr "type" "multi")
5654 (set_attr "length" "2")])
5655
5656 ;; The v8 architecture specifies that there must be 3 instructions between
5657 ;; a y register write and a use of it for correct results.
5658
5659 (define_expand "divsi3"
5660 [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
5661 (div:SI (match_operand:SI 1 "register_operand" "r,r")
5662 (match_operand:SI 2 "input_operand" "rI,m")))
5663 (clobber (match_scratch:SI 3 "=&r,&r"))])]
5664 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5665 {
5666 if (TARGET_ARCH64)
5667 {
5668 operands[3] = gen_reg_rtx(SImode);
5669 emit_insn (gen_ashrsi3 (operands[3], operands[1], GEN_INT (31)));
5670 emit_insn (gen_divsi3_sp64 (operands[0], operands[1], operands[2],
5671 operands[3]));
5672 DONE;
5673 }
5674 })
5675
5676 (define_insn "divsi3_sp32"
5677 [(set (match_operand:SI 0 "register_operand" "=r,r")
5678 (div:SI (match_operand:SI 1 "register_operand" "r,r")
5679 (match_operand:SI 2 "input_operand" "rI,m")))
5680 (clobber (match_scratch:SI 3 "=&r,&r"))]
5681 "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
5682 && TARGET_ARCH32"
5683 {
5684 if (which_alternative == 0)
5685 if (TARGET_V9)
5686 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdiv\t%1, %2, %0";
5687 else
5688 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0";
5689 else
5690 if (TARGET_V9)
5691 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0";
5692 else
5693 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";
5694 }
5695 [(set_attr "type" "multi")
5696 (set (attr "length")
5697 (if_then_else (eq_attr "isa" "v9")
5698 (const_int 4) (const_int 6)))])
5699
5700 (define_insn "divsi3_sp64"
5701 [(set (match_operand:SI 0 "register_operand" "=r")
5702 (div:SI (match_operand:SI 1 "register_operand" "r")
5703 (match_operand:SI 2 "input_operand" "rI")))
5704 (use (match_operand:SI 3 "register_operand" "r"))]
5705 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5706 "wr\t%%g0, %3, %%y\n\tsdiv\t%1, %2, %0"
5707 [(set_attr "type" "multi")
5708 (set_attr "length" "2")])
5709
5710 (define_insn "divdi3"
5711 [(set (match_operand:DI 0 "register_operand" "=r")
5712 (div:DI (match_operand:DI 1 "register_operand" "r")
5713 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5714 "TARGET_ARCH64"
5715 "sdivx\t%1, %2, %0"
5716 [(set_attr "type" "idiv")])
5717
5718 (define_insn "*cmp_sdiv_cc_set"
5719 [(set (reg:CC 100)
5720 (compare:CC (div:SI (match_operand:SI 1 "register_operand" "r")
5721 (match_operand:SI 2 "arith_operand" "rI"))
5722 (const_int 0)))
5723 (set (match_operand:SI 0 "register_operand" "=r")
5724 (div:SI (match_dup 1) (match_dup 2)))
5725 (clobber (match_scratch:SI 3 "=&r"))]
5726 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5727 {
5728 if (TARGET_V9)
5729 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdivcc\t%1, %2, %0";
5730 else
5731 return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0";
5732 }
5733 [(set_attr "type" "multi")
5734 (set (attr "length")
5735 (if_then_else (eq_attr "isa" "v9")
5736 (const_int 3) (const_int 6)))])
5737
5738 ;; XXX
5739 (define_expand "udivsi3"
5740 [(set (match_operand:SI 0 "register_operand" "")
5741 (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "")
5742 (match_operand:SI 2 "input_operand" "")))]
5743 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5744 "")
5745
5746 (define_insn "udivsi3_sp32"
5747 [(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
5748 (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
5749 (match_operand:SI 2 "input_operand" "rI,m,r")))]
5750 "(TARGET_V8
5751 || TARGET_DEPRECATED_V8_INSNS)
5752 && TARGET_ARCH32"
5753 {
5754 output_asm_insn ("wr\t%%g0, %%g0, %%y", operands);
5755 switch (which_alternative)
5756 {
5757 default:
5758 return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0";
5759 case 1:
5760 return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0";
5761 case 2:
5762 return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0";
5763 }
5764 }
5765 [(set_attr "type" "multi")
5766 (set_attr "length" "5")])
5767
5768 (define_insn "udivsi3_sp64"
5769 [(set (match_operand:SI 0 "register_operand" "=r")
5770 (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
5771 (match_operand:SI 2 "input_operand" "rI")))]
5772 "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5773 "wr\t%%g0, 0, %%y\n\tudiv\t%1, %2, %0"
5774 [(set_attr "type" "multi")
5775 (set_attr "length" "2")])
5776
5777 (define_insn "udivdi3"
5778 [(set (match_operand:DI 0 "register_operand" "=r")
5779 (udiv:DI (match_operand:DI 1 "register_operand" "r")
5780 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5781 "TARGET_ARCH64"
5782 "udivx\t%1, %2, %0"
5783 [(set_attr "type" "idiv")])
5784
5785 (define_insn "*cmp_udiv_cc_set"
5786 [(set (reg:CC 100)
5787 (compare:CC (udiv:SI (match_operand:SI 1 "register_operand" "r")
5788 (match_operand:SI 2 "arith_operand" "rI"))
5789 (const_int 0)))
5790 (set (match_operand:SI 0 "register_operand" "=r")
5791 (udiv:SI (match_dup 1) (match_dup 2)))]
5792 "TARGET_V8
5793 || TARGET_DEPRECATED_V8_INSNS"
5794 {
5795 if (TARGET_V9)
5796 return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0";
5797 else
5798 return "wr\t%%g0, %%g0, %%y\n\tnop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0";
5799 }
5800 [(set_attr "type" "multi")
5801 (set (attr "length")
5802 (if_then_else (eq_attr "isa" "v9")
5803 (const_int 2) (const_int 5)))])
5804
5805 ; sparclet multiply/accumulate insns
5806
5807 (define_insn "*smacsi"
5808 [(set (match_operand:SI 0 "register_operand" "=r")
5809 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
5810 (match_operand:SI 2 "arith_operand" "rI"))
5811 (match_operand:SI 3 "register_operand" "0")))]
5812 "TARGET_SPARCLET"
5813 "smac\t%1, %2, %0"
5814 [(set_attr "type" "imul")])
5815
5816 (define_insn "*smacdi"
5817 [(set (match_operand:DI 0 "register_operand" "=r")
5818 (plus:DI (mult:DI (sign_extend:DI
5819 (match_operand:SI 1 "register_operand" "%r"))
5820 (sign_extend:DI
5821 (match_operand:SI 2 "register_operand" "r")))
5822 (match_operand:DI 3 "register_operand" "0")))]
5823 "TARGET_SPARCLET"
5824 "smacd\t%1, %2, %L0"
5825 [(set_attr "type" "imul")])
5826
5827 (define_insn "*umacdi"
5828 [(set (match_operand:DI 0 "register_operand" "=r")
5829 (plus:DI (mult:DI (zero_extend:DI
5830 (match_operand:SI 1 "register_operand" "%r"))
5831 (zero_extend:DI
5832 (match_operand:SI 2 "register_operand" "r")))
5833 (match_operand:DI 3 "register_operand" "0")))]
5834 "TARGET_SPARCLET"
5835 "umacd\t%1, %2, %L0"
5836 [(set_attr "type" "imul")])
5837 \f
5838 ;;- Boolean instructions
5839 ;; We define DImode `and' so with DImode `not' we can get
5840 ;; DImode `andn'. Other combinations are possible.
5841
5842 (define_expand "anddi3"
5843 [(set (match_operand:DI 0 "register_operand" "")
5844 (and:DI (match_operand:DI 1 "arith_double_operand" "")
5845 (match_operand:DI 2 "arith_double_operand" "")))]
5846 ""
5847 "")
5848
5849 (define_insn "*anddi3_sp32"
5850 [(set (match_operand:DI 0 "register_operand" "=r,b")
5851 (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5852 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5853 "! TARGET_ARCH64"
5854 "@
5855 #
5856 fand\t%1, %2, %0"
5857 [(set_attr "type" "*,fp")
5858 (set_attr "length" "2,*")
5859 (set_attr "fptype" "double")])
5860
5861 (define_insn "*anddi3_sp64"
5862 [(set (match_operand:DI 0 "register_operand" "=r,b")
5863 (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5864 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5865 "TARGET_ARCH64"
5866 "@
5867 and\t%1, %2, %0
5868 fand\t%1, %2, %0"
5869 [(set_attr "type" "*,fp")
5870 (set_attr "fptype" "double")])
5871
5872 (define_insn "andsi3"
5873 [(set (match_operand:SI 0 "register_operand" "=r,d")
5874 (and:SI (match_operand:SI 1 "arith_operand" "%r,d")
5875 (match_operand:SI 2 "arith_operand" "rI,d")))]
5876 ""
5877 "@
5878 and\t%1, %2, %0
5879 fands\t%1, %2, %0"
5880 [(set_attr "type" "*,fp")])
5881
5882 (define_split
5883 [(set (match_operand:SI 0 "register_operand" "")
5884 (and:SI (match_operand:SI 1 "register_operand" "")
5885 (match_operand:SI 2 "" "")))
5886 (clobber (match_operand:SI 3 "register_operand" ""))]
5887 "GET_CODE (operands[2]) == CONST_INT
5888 && !SMALL_INT32 (operands[2])
5889 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
5890 [(set (match_dup 3) (match_dup 4))
5891 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
5892 {
5893 operands[4] = GEN_INT (~INTVAL (operands[2]));
5894 })
5895
5896 ;; Split DImode logical operations requiring two instructions.
5897 (define_split
5898 [(set (match_operand:DI 0 "register_operand" "")
5899 (match_operator:DI 1 "cc_arithop" ; AND, IOR, XOR
5900 [(match_operand:DI 2 "register_operand" "")
5901 (match_operand:DI 3 "arith_double_operand" "")]))]
5902 "! TARGET_ARCH64
5903 && reload_completed
5904 && ((GET_CODE (operands[0]) == REG
5905 && REGNO (operands[0]) < 32)
5906 || (GET_CODE (operands[0]) == SUBREG
5907 && GET_CODE (SUBREG_REG (operands[0])) == REG
5908 && REGNO (SUBREG_REG (operands[0])) < 32))"
5909 [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
5910 (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
5911 {
5912 operands[4] = gen_highpart (SImode, operands[0]);
5913 operands[5] = gen_lowpart (SImode, operands[0]);
5914 operands[6] = gen_highpart (SImode, operands[2]);
5915 operands[7] = gen_lowpart (SImode, operands[2]);
5916 #if HOST_BITS_PER_WIDE_INT == 32
5917 if (GET_CODE (operands[3]) == CONST_INT)
5918 {
5919 if (INTVAL (operands[3]) < 0)
5920 operands[8] = constm1_rtx;
5921 else
5922 operands[8] = const0_rtx;
5923 }
5924 else
5925 #endif
5926 operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
5927 operands[9] = gen_lowpart (SImode, operands[3]);
5928 })
5929
5930 (define_insn_and_split "*and_not_di_sp32"
5931 [(set (match_operand:DI 0 "register_operand" "=r,b")
5932 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
5933 (match_operand:DI 2 "register_operand" "r,b")))]
5934 "! TARGET_ARCH64"
5935 "@
5936 #
5937 fandnot1\t%1, %2, %0"
5938 "&& reload_completed
5939 && ((GET_CODE (operands[0]) == REG
5940 && REGNO (operands[0]) < 32)
5941 || (GET_CODE (operands[0]) == SUBREG
5942 && GET_CODE (SUBREG_REG (operands[0])) == REG
5943 && REGNO (SUBREG_REG (operands[0])) < 32))"
5944 [(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
5945 (set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
5946 "operands[3] = gen_highpart (SImode, operands[0]);
5947 operands[4] = gen_highpart (SImode, operands[1]);
5948 operands[5] = gen_highpart (SImode, operands[2]);
5949 operands[6] = gen_lowpart (SImode, operands[0]);
5950 operands[7] = gen_lowpart (SImode, operands[1]);
5951 operands[8] = gen_lowpart (SImode, operands[2]);"
5952 [(set_attr "type" "*,fp")
5953 (set_attr "length" "2,*")
5954 (set_attr "fptype" "double")])
5955
5956 (define_insn "*and_not_di_sp64"
5957 [(set (match_operand:DI 0 "register_operand" "=r,b")
5958 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
5959 (match_operand:DI 2 "register_operand" "r,b")))]
5960 "TARGET_ARCH64"
5961 "@
5962 andn\t%2, %1, %0
5963 fandnot1\t%1, %2, %0"
5964 [(set_attr "type" "*,fp")
5965 (set_attr "fptype" "double")])
5966
5967 (define_insn "*and_not_si"
5968 [(set (match_operand:SI 0 "register_operand" "=r,d")
5969 (and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
5970 (match_operand:SI 2 "register_operand" "r,d")))]
5971 ""
5972 "@
5973 andn\t%2, %1, %0
5974 fandnot1s\t%1, %2, %0"
5975 [(set_attr "type" "*,fp")])
5976
5977 (define_expand "iordi3"
5978 [(set (match_operand:DI 0 "register_operand" "")
5979 (ior:DI (match_operand:DI 1 "arith_double_operand" "")
5980 (match_operand:DI 2 "arith_double_operand" "")))]
5981 ""
5982 "")
5983
5984 (define_insn "*iordi3_sp32"
5985 [(set (match_operand:DI 0 "register_operand" "=r,b")
5986 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5987 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5988 "! TARGET_ARCH64"
5989 "@
5990 #
5991 for\t%1, %2, %0"
5992 [(set_attr "type" "*,fp")
5993 (set_attr "length" "2,*")
5994 (set_attr "fptype" "double")])
5995
5996 (define_insn "*iordi3_sp64"
5997 [(set (match_operand:DI 0 "register_operand" "=r,b")
5998 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5999 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6000 "TARGET_ARCH64"
6001 "@
6002 or\t%1, %2, %0
6003 for\t%1, %2, %0"
6004 [(set_attr "type" "*,fp")
6005 (set_attr "fptype" "double")])
6006
6007 (define_insn "iorsi3"
6008 [(set (match_operand:SI 0 "register_operand" "=r,d")
6009 (ior:SI (match_operand:SI 1 "arith_operand" "%r,d")
6010 (match_operand:SI 2 "arith_operand" "rI,d")))]
6011 ""
6012 "@
6013 or\t%1, %2, %0
6014 fors\t%1, %2, %0"
6015 [(set_attr "type" "*,fp")])
6016
6017 (define_split
6018 [(set (match_operand:SI 0 "register_operand" "")
6019 (ior:SI (match_operand:SI 1 "register_operand" "")
6020 (match_operand:SI 2 "" "")))
6021 (clobber (match_operand:SI 3 "register_operand" ""))]
6022 "GET_CODE (operands[2]) == CONST_INT
6023 && !SMALL_INT32 (operands[2])
6024 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6025 [(set (match_dup 3) (match_dup 4))
6026 (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
6027 {
6028 operands[4] = GEN_INT (~INTVAL (operands[2]));
6029 })
6030
6031 (define_insn_and_split "*or_not_di_sp32"
6032 [(set (match_operand:DI 0 "register_operand" "=r,b")
6033 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6034 (match_operand:DI 2 "register_operand" "r,b")))]
6035 "! TARGET_ARCH64"
6036 "@
6037 #
6038 fornot1\t%1, %2, %0"
6039 "&& reload_completed
6040 && ((GET_CODE (operands[0]) == REG
6041 && REGNO (operands[0]) < 32)
6042 || (GET_CODE (operands[0]) == SUBREG
6043 && GET_CODE (SUBREG_REG (operands[0])) == REG
6044 && REGNO (SUBREG_REG (operands[0])) < 32))"
6045 [(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
6046 (set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
6047 "operands[3] = gen_highpart (SImode, operands[0]);
6048 operands[4] = gen_highpart (SImode, operands[1]);
6049 operands[5] = gen_highpart (SImode, operands[2]);
6050 operands[6] = gen_lowpart (SImode, operands[0]);
6051 operands[7] = gen_lowpart (SImode, operands[1]);
6052 operands[8] = gen_lowpart (SImode, operands[2]);"
6053 [(set_attr "type" "*,fp")
6054 (set_attr "length" "2,*")
6055 (set_attr "fptype" "double")])
6056
6057 (define_insn "*or_not_di_sp64"
6058 [(set (match_operand:DI 0 "register_operand" "=r,b")
6059 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6060 (match_operand:DI 2 "register_operand" "r,b")))]
6061 "TARGET_ARCH64"
6062 "@
6063 orn\t%2, %1, %0
6064 fornot1\t%1, %2, %0"
6065 [(set_attr "type" "*,fp")
6066 (set_attr "fptype" "double")])
6067
6068 (define_insn "*or_not_si"
6069 [(set (match_operand:SI 0 "register_operand" "=r,d")
6070 (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
6071 (match_operand:SI 2 "register_operand" "r,d")))]
6072 ""
6073 "@
6074 orn\t%2, %1, %0
6075 fornot1s\t%1, %2, %0"
6076 [(set_attr "type" "*,fp")])
6077
6078 (define_expand "xordi3"
6079 [(set (match_operand:DI 0 "register_operand" "")
6080 (xor:DI (match_operand:DI 1 "arith_double_operand" "")
6081 (match_operand:DI 2 "arith_double_operand" "")))]
6082 ""
6083 "")
6084
6085 (define_insn "*xordi3_sp32"
6086 [(set (match_operand:DI 0 "register_operand" "=r,b")
6087 (xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6088 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6089 "! TARGET_ARCH64"
6090 "@
6091 #
6092 fxor\t%1, %2, %0"
6093 [(set_attr "type" "*,fp")
6094 (set_attr "length" "2,*")
6095 (set_attr "fptype" "double")])
6096
6097 (define_insn "*xordi3_sp64"
6098 [(set (match_operand:DI 0 "register_operand" "=r,b")
6099 (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
6100 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6101 "TARGET_ARCH64"
6102 "@
6103 xor\t%r1, %2, %0
6104 fxor\t%1, %2, %0"
6105 [(set_attr "type" "*,fp")
6106 (set_attr "fptype" "double")])
6107
6108 (define_insn "*xordi3_sp64_dbl"
6109 [(set (match_operand:DI 0 "register_operand" "=r")
6110 (xor:DI (match_operand:DI 1 "register_operand" "r")
6111 (match_operand:DI 2 "const64_operand" "")))]
6112 "(TARGET_ARCH64
6113 && HOST_BITS_PER_WIDE_INT != 64)"
6114 "xor\t%1, %2, %0")
6115
6116 (define_insn "xorsi3"
6117 [(set (match_operand:SI 0 "register_operand" "=r,d")
6118 (xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d")
6119 (match_operand:SI 2 "arith_operand" "rI,d")))]
6120 ""
6121 "@
6122 xor\t%r1, %2, %0
6123 fxors\t%1, %2, %0"
6124 [(set_attr "type" "*,fp")])
6125
6126 (define_split
6127 [(set (match_operand:SI 0 "register_operand" "")
6128 (xor:SI (match_operand:SI 1 "register_operand" "")
6129 (match_operand:SI 2 "" "")))
6130 (clobber (match_operand:SI 3 "register_operand" ""))]
6131 "GET_CODE (operands[2]) == CONST_INT
6132 && !SMALL_INT32 (operands[2])
6133 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6134 [(set (match_dup 3) (match_dup 4))
6135 (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
6136 {
6137 operands[4] = GEN_INT (~INTVAL (operands[2]));
6138 })
6139
6140 (define_split
6141 [(set (match_operand:SI 0 "register_operand" "")
6142 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
6143 (match_operand:SI 2 "" ""))))
6144 (clobber (match_operand:SI 3 "register_operand" ""))]
6145 "GET_CODE (operands[2]) == CONST_INT
6146 && !SMALL_INT32 (operands[2])
6147 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6148 [(set (match_dup 3) (match_dup 4))
6149 (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
6150 {
6151 operands[4] = GEN_INT (~INTVAL (operands[2]));
6152 })
6153
6154 ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
6155 ;; Combine now canonicalizes to the rightmost expression.
6156 (define_insn_and_split "*xor_not_di_sp32"
6157 [(set (match_operand:DI 0 "register_operand" "=r,b")
6158 (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
6159 (match_operand:DI 2 "register_operand" "r,b"))))]
6160 "! TARGET_ARCH64"
6161 "@
6162 #
6163 fxnor\t%1, %2, %0"
6164 "&& reload_completed
6165 && ((GET_CODE (operands[0]) == REG
6166 && REGNO (operands[0]) < 32)
6167 || (GET_CODE (operands[0]) == SUBREG
6168 && GET_CODE (SUBREG_REG (operands[0])) == REG
6169 && REGNO (SUBREG_REG (operands[0])) < 32))"
6170 [(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
6171 (set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
6172 "operands[3] = gen_highpart (SImode, operands[0]);
6173 operands[4] = gen_highpart (SImode, operands[1]);
6174 operands[5] = gen_highpart (SImode, operands[2]);
6175 operands[6] = gen_lowpart (SImode, operands[0]);
6176 operands[7] = gen_lowpart (SImode, operands[1]);
6177 operands[8] = gen_lowpart (SImode, operands[2]);"
6178 [(set_attr "type" "*,fp")
6179 (set_attr "length" "2,*")
6180 (set_attr "fptype" "double")])
6181
6182 (define_insn "*xor_not_di_sp64"
6183 [(set (match_operand:DI 0 "register_operand" "=r,b")
6184 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
6185 (match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
6186 "TARGET_ARCH64"
6187 "@
6188 xnor\t%r1, %2, %0
6189 fxnor\t%1, %2, %0"
6190 [(set_attr "type" "*,fp")
6191 (set_attr "fptype" "double")])
6192
6193 (define_insn "*xor_not_si"
6194 [(set (match_operand:SI 0 "register_operand" "=r,d")
6195 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d")
6196 (match_operand:SI 2 "arith_operand" "rI,d"))))]
6197 ""
6198 "@
6199 xnor\t%r1, %2, %0
6200 fxnors\t%1, %2, %0"
6201 [(set_attr "type" "*,fp")])
6202
6203 ;; These correspond to the above in the case where we also (or only)
6204 ;; want to set the condition code.
6205
6206 (define_insn "*cmp_cc_arith_op"
6207 [(set (reg:CC 100)
6208 (compare:CC
6209 (match_operator:SI 2 "cc_arithop"
6210 [(match_operand:SI 0 "arith_operand" "%r")
6211 (match_operand:SI 1 "arith_operand" "rI")])
6212 (const_int 0)))]
6213 ""
6214 "%A2cc\t%0, %1, %%g0"
6215 [(set_attr "type" "compare")])
6216
6217 (define_insn "*cmp_ccx_arith_op"
6218 [(set (reg:CCX 100)
6219 (compare:CCX
6220 (match_operator:DI 2 "cc_arithop"
6221 [(match_operand:DI 0 "arith_double_operand" "%r")
6222 (match_operand:DI 1 "arith_double_operand" "rHI")])
6223 (const_int 0)))]
6224 "TARGET_ARCH64"
6225 "%A2cc\t%0, %1, %%g0"
6226 [(set_attr "type" "compare")])
6227
6228 (define_insn "*cmp_cc_arith_op_set"
6229 [(set (reg:CC 100)
6230 (compare:CC
6231 (match_operator:SI 3 "cc_arithop"
6232 [(match_operand:SI 1 "arith_operand" "%r")
6233 (match_operand:SI 2 "arith_operand" "rI")])
6234 (const_int 0)))
6235 (set (match_operand:SI 0 "register_operand" "=r")
6236 (match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
6237 "GET_CODE (operands[3]) == GET_CODE (operands[4])"
6238 "%A3cc\t%1, %2, %0"
6239 [(set_attr "type" "compare")])
6240
6241 (define_insn "*cmp_ccx_arith_op_set"
6242 [(set (reg:CCX 100)
6243 (compare:CCX
6244 (match_operator:DI 3 "cc_arithop"
6245 [(match_operand:DI 1 "arith_double_operand" "%r")
6246 (match_operand:DI 2 "arith_double_operand" "rHI")])
6247 (const_int 0)))
6248 (set (match_operand:DI 0 "register_operand" "=r")
6249 (match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
6250 "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
6251 "%A3cc\t%1, %2, %0"
6252 [(set_attr "type" "compare")])
6253
6254 (define_insn "*cmp_cc_xor_not"
6255 [(set (reg:CC 100)
6256 (compare:CC
6257 (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
6258 (match_operand:SI 1 "arith_operand" "rI")))
6259 (const_int 0)))]
6260 ""
6261 "xnorcc\t%r0, %1, %%g0"
6262 [(set_attr "type" "compare")])
6263
6264 (define_insn "*cmp_ccx_xor_not"
6265 [(set (reg:CCX 100)
6266 (compare:CCX
6267 (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
6268 (match_operand:DI 1 "arith_double_operand" "rHI")))
6269 (const_int 0)))]
6270 "TARGET_ARCH64"
6271 "xnorcc\t%r0, %1, %%g0"
6272 [(set_attr "type" "compare")])
6273
6274 (define_insn "*cmp_cc_xor_not_set"
6275 [(set (reg:CC 100)
6276 (compare:CC
6277 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
6278 (match_operand:SI 2 "arith_operand" "rI")))
6279 (const_int 0)))
6280 (set (match_operand:SI 0 "register_operand" "=r")
6281 (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
6282 ""
6283 "xnorcc\t%r1, %2, %0"
6284 [(set_attr "type" "compare")])
6285
6286 (define_insn "*cmp_ccx_xor_not_set"
6287 [(set (reg:CCX 100)
6288 (compare:CCX
6289 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
6290 (match_operand:DI 2 "arith_double_operand" "rHI")))
6291 (const_int 0)))
6292 (set (match_operand:DI 0 "register_operand" "=r")
6293 (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
6294 "TARGET_ARCH64"
6295 "xnorcc\t%r1, %2, %0"
6296 [(set_attr "type" "compare")])
6297
6298 (define_insn "*cmp_cc_arith_op_not"
6299 [(set (reg:CC 100)
6300 (compare:CC
6301 (match_operator:SI 2 "cc_arithopn"
6302 [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
6303 (match_operand:SI 1 "reg_or_0_operand" "rJ")])
6304 (const_int 0)))]
6305 ""
6306 "%B2cc\t%r1, %0, %%g0"
6307 [(set_attr "type" "compare")])
6308
6309 (define_insn "*cmp_ccx_arith_op_not"
6310 [(set (reg:CCX 100)
6311 (compare:CCX
6312 (match_operator:DI 2 "cc_arithopn"
6313 [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6314 (match_operand:DI 1 "reg_or_0_operand" "rJ")])
6315 (const_int 0)))]
6316 "TARGET_ARCH64"
6317 "%B2cc\t%r1, %0, %%g0"
6318 [(set_attr "type" "compare")])
6319
6320 (define_insn "*cmp_cc_arith_op_not_set"
6321 [(set (reg:CC 100)
6322 (compare:CC
6323 (match_operator:SI 3 "cc_arithopn"
6324 [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
6325 (match_operand:SI 2 "reg_or_0_operand" "rJ")])
6326 (const_int 0)))
6327 (set (match_operand:SI 0 "register_operand" "=r")
6328 (match_operator:SI 4 "cc_arithopn"
6329 [(not:SI (match_dup 1)) (match_dup 2)]))]
6330 "GET_CODE (operands[3]) == GET_CODE (operands[4])"
6331 "%B3cc\t%r2, %1, %0"
6332 [(set_attr "type" "compare")])
6333
6334 (define_insn "*cmp_ccx_arith_op_not_set"
6335 [(set (reg:CCX 100)
6336 (compare:CCX
6337 (match_operator:DI 3 "cc_arithopn"
6338 [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6339 (match_operand:DI 2 "reg_or_0_operand" "rJ")])
6340 (const_int 0)))
6341 (set (match_operand:DI 0 "register_operand" "=r")
6342 (match_operator:DI 4 "cc_arithopn"
6343 [(not:DI (match_dup 1)) (match_dup 2)]))]
6344 "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
6345 "%B3cc\t%r2, %1, %0"
6346 [(set_attr "type" "compare")])
6347
6348 ;; We cannot use the "neg" pseudo insn because the Sun assembler
6349 ;; does not know how to make it work for constants.
6350
6351 (define_expand "negdi2"
6352 [(set (match_operand:DI 0 "register_operand" "=r")
6353 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
6354 ""
6355 {
6356 if (! TARGET_ARCH64)
6357 {
6358 emit_insn (gen_rtx_PARALLEL
6359 (VOIDmode,
6360 gen_rtvec (2,
6361 gen_rtx_SET (VOIDmode, operand0,
6362 gen_rtx_NEG (DImode, operand1)),
6363 gen_rtx_CLOBBER (VOIDmode,
6364 gen_rtx_REG (CCmode,
6365 SPARC_ICC_REG)))));
6366 DONE;
6367 }
6368 })
6369
6370 (define_insn_and_split "*negdi2_sp32"
6371 [(set (match_operand:DI 0 "register_operand" "=r")
6372 (neg:DI (match_operand:DI 1 "register_operand" "r")))
6373 (clobber (reg:CC 100))]
6374 "TARGET_ARCH32"
6375 "#"
6376 "&& reload_completed"
6377 [(parallel [(set (reg:CC_NOOV 100)
6378 (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
6379 (const_int 0)))
6380 (set (match_dup 4) (minus:SI (const_int 0) (match_dup 5)))])
6381 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
6382 (ltu:SI (reg:CC 100) (const_int 0))))]
6383 "operands[2] = gen_highpart (SImode, operands[0]);
6384 operands[3] = gen_highpart (SImode, operands[1]);
6385 operands[4] = gen_lowpart (SImode, operands[0]);
6386 operands[5] = gen_lowpart (SImode, operands[1]);"
6387 [(set_attr "length" "2")])
6388
6389 (define_insn "*negdi2_sp64"
6390 [(set (match_operand:DI 0 "register_operand" "=r")
6391 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
6392 "TARGET_ARCH64"
6393 "sub\t%%g0, %1, %0")
6394
6395 (define_insn "negsi2"
6396 [(set (match_operand:SI 0 "register_operand" "=r")
6397 (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
6398 ""
6399 "sub\t%%g0, %1, %0")
6400
6401 (define_insn "*cmp_cc_neg"
6402 [(set (reg:CC_NOOV 100)
6403 (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
6404 (const_int 0)))]
6405 ""
6406 "subcc\t%%g0, %0, %%g0"
6407 [(set_attr "type" "compare")])
6408
6409 (define_insn "*cmp_ccx_neg"
6410 [(set (reg:CCX_NOOV 100)
6411 (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6412 (const_int 0)))]
6413 "TARGET_ARCH64"
6414 "subcc\t%%g0, %0, %%g0"
6415 [(set_attr "type" "compare")])
6416
6417 (define_insn "*cmp_cc_set_neg"
6418 [(set (reg:CC_NOOV 100)
6419 (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
6420 (const_int 0)))
6421 (set (match_operand:SI 0 "register_operand" "=r")
6422 (neg:SI (match_dup 1)))]
6423 ""
6424 "subcc\t%%g0, %1, %0"
6425 [(set_attr "type" "compare")])
6426
6427 (define_insn "*cmp_ccx_set_neg"
6428 [(set (reg:CCX_NOOV 100)
6429 (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6430 (const_int 0)))
6431 (set (match_operand:DI 0 "register_operand" "=r")
6432 (neg:DI (match_dup 1)))]
6433 "TARGET_ARCH64"
6434 "subcc\t%%g0, %1, %0"
6435 [(set_attr "type" "compare")])
6436
6437 ;; We cannot use the "not" pseudo insn because the Sun assembler
6438 ;; does not know how to make it work for constants.
6439 (define_expand "one_cmpldi2"
6440 [(set (match_operand:DI 0 "register_operand" "")
6441 (not:DI (match_operand:DI 1 "register_operand" "")))]
6442 ""
6443 "")
6444
6445 (define_insn_and_split "*one_cmpldi2_sp32"
6446 [(set (match_operand:DI 0 "register_operand" "=r,b")
6447 (not:DI (match_operand:DI 1 "register_operand" "r,b")))]
6448 "! TARGET_ARCH64"
6449 "@
6450 #
6451 fnot1\t%1, %0"
6452 "&& reload_completed
6453 && ((GET_CODE (operands[0]) == REG
6454 && REGNO (operands[0]) < 32)
6455 || (GET_CODE (operands[0]) == SUBREG
6456 && GET_CODE (SUBREG_REG (operands[0])) == REG
6457 && REGNO (SUBREG_REG (operands[0])) < 32))"
6458 [(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
6459 (set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
6460 "operands[2] = gen_highpart (SImode, operands[0]);
6461 operands[3] = gen_highpart (SImode, operands[1]);
6462 operands[4] = gen_lowpart (SImode, operands[0]);
6463 operands[5] = gen_lowpart (SImode, operands[1]);"
6464 [(set_attr "type" "*,fp")
6465 (set_attr "length" "2,*")
6466 (set_attr "fptype" "double")])
6467
6468 (define_insn "*one_cmpldi2_sp64"
6469 [(set (match_operand:DI 0 "register_operand" "=r,b")
6470 (not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
6471 "TARGET_ARCH64"
6472 "@
6473 xnor\t%%g0, %1, %0
6474 fnot1\t%1, %0"
6475 [(set_attr "type" "*,fp")
6476 (set_attr "fptype" "double")])
6477
6478 (define_insn "one_cmplsi2"
6479 [(set (match_operand:SI 0 "register_operand" "=r,d")
6480 (not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
6481 ""
6482 "@
6483 xnor\t%%g0, %1, %0
6484 fnot1s\t%1, %0"
6485 [(set_attr "type" "*,fp")])
6486
6487 (define_insn "*cmp_cc_not"
6488 [(set (reg:CC 100)
6489 (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
6490 (const_int 0)))]
6491 ""
6492 "xnorcc\t%%g0, %0, %%g0"
6493 [(set_attr "type" "compare")])
6494
6495 (define_insn "*cmp_ccx_not"
6496 [(set (reg:CCX 100)
6497 (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6498 (const_int 0)))]
6499 "TARGET_ARCH64"
6500 "xnorcc\t%%g0, %0, %%g0"
6501 [(set_attr "type" "compare")])
6502
6503 (define_insn "*cmp_cc_set_not"
6504 [(set (reg:CC 100)
6505 (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
6506 (const_int 0)))
6507 (set (match_operand:SI 0 "register_operand" "=r")
6508 (not:SI (match_dup 1)))]
6509 ""
6510 "xnorcc\t%%g0, %1, %0"
6511 [(set_attr "type" "compare")])
6512
6513 (define_insn "*cmp_ccx_set_not"
6514 [(set (reg:CCX 100)
6515 (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6516 (const_int 0)))
6517 (set (match_operand:DI 0 "register_operand" "=r")
6518 (not:DI (match_dup 1)))]
6519 "TARGET_ARCH64"
6520 "xnorcc\t%%g0, %1, %0"
6521 [(set_attr "type" "compare")])
6522
6523 (define_insn "*cmp_cc_set"
6524 [(set (match_operand:SI 0 "register_operand" "=r")
6525 (match_operand:SI 1 "register_operand" "r"))
6526 (set (reg:CC 100)
6527 (compare:CC (match_dup 1)
6528 (const_int 0)))]
6529 ""
6530 "orcc\t%1, 0, %0"
6531 [(set_attr "type" "compare")])
6532
6533 (define_insn "*cmp_ccx_set64"
6534 [(set (match_operand:DI 0 "register_operand" "=r")
6535 (match_operand:DI 1 "register_operand" "r"))
6536 (set (reg:CCX 100)
6537 (compare:CCX (match_dup 1)
6538 (const_int 0)))]
6539 "TARGET_ARCH64"
6540 "orcc\t%1, 0, %0"
6541 [(set_attr "type" "compare")])
6542 \f
6543 ;; Floating point arithmetic instructions.
6544
6545 (define_expand "addtf3"
6546 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6547 (plus:TF (match_operand:TF 1 "general_operand" "")
6548 (match_operand:TF 2 "general_operand" "")))]
6549 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6550 "emit_tfmode_binop (PLUS, operands); DONE;")
6551
6552 (define_insn "*addtf3_hq"
6553 [(set (match_operand:TF 0 "register_operand" "=e")
6554 (plus:TF (match_operand:TF 1 "register_operand" "e")
6555 (match_operand:TF 2 "register_operand" "e")))]
6556 "TARGET_FPU && TARGET_HARD_QUAD"
6557 "faddq\t%1, %2, %0"
6558 [(set_attr "type" "fp")])
6559
6560 (define_insn "adddf3"
6561 [(set (match_operand:DF 0 "register_operand" "=e")
6562 (plus:DF (match_operand:DF 1 "register_operand" "e")
6563 (match_operand:DF 2 "register_operand" "e")))]
6564 "TARGET_FPU"
6565 "faddd\t%1, %2, %0"
6566 [(set_attr "type" "fp")
6567 (set_attr "fptype" "double")])
6568
6569 (define_insn "addsf3"
6570 [(set (match_operand:SF 0 "register_operand" "=f")
6571 (plus:SF (match_operand:SF 1 "register_operand" "f")
6572 (match_operand:SF 2 "register_operand" "f")))]
6573 "TARGET_FPU"
6574 "fadds\t%1, %2, %0"
6575 [(set_attr "type" "fp")])
6576
6577 (define_expand "subtf3"
6578 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6579 (minus:TF (match_operand:TF 1 "general_operand" "")
6580 (match_operand:TF 2 "general_operand" "")))]
6581 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6582 "emit_tfmode_binop (MINUS, operands); DONE;")
6583
6584 (define_insn "*subtf3_hq"
6585 [(set (match_operand:TF 0 "register_operand" "=e")
6586 (minus:TF (match_operand:TF 1 "register_operand" "e")
6587 (match_operand:TF 2 "register_operand" "e")))]
6588 "TARGET_FPU && TARGET_HARD_QUAD"
6589 "fsubq\t%1, %2, %0"
6590 [(set_attr "type" "fp")])
6591
6592 (define_insn "subdf3"
6593 [(set (match_operand:DF 0 "register_operand" "=e")
6594 (minus:DF (match_operand:DF 1 "register_operand" "e")
6595 (match_operand:DF 2 "register_operand" "e")))]
6596 "TARGET_FPU"
6597 "fsubd\t%1, %2, %0"
6598 [(set_attr "type" "fp")
6599 (set_attr "fptype" "double")])
6600
6601 (define_insn "subsf3"
6602 [(set (match_operand:SF 0 "register_operand" "=f")
6603 (minus:SF (match_operand:SF 1 "register_operand" "f")
6604 (match_operand:SF 2 "register_operand" "f")))]
6605 "TARGET_FPU"
6606 "fsubs\t%1, %2, %0"
6607 [(set_attr "type" "fp")])
6608
6609 (define_expand "multf3"
6610 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6611 (mult:TF (match_operand:TF 1 "general_operand" "")
6612 (match_operand:TF 2 "general_operand" "")))]
6613 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6614 "emit_tfmode_binop (MULT, operands); DONE;")
6615
6616 (define_insn "*multf3_hq"
6617 [(set (match_operand:TF 0 "register_operand" "=e")
6618 (mult:TF (match_operand:TF 1 "register_operand" "e")
6619 (match_operand:TF 2 "register_operand" "e")))]
6620 "TARGET_FPU && TARGET_HARD_QUAD"
6621 "fmulq\t%1, %2, %0"
6622 [(set_attr "type" "fpmul")])
6623
6624 (define_insn "muldf3"
6625 [(set (match_operand:DF 0 "register_operand" "=e")
6626 (mult:DF (match_operand:DF 1 "register_operand" "e")
6627 (match_operand:DF 2 "register_operand" "e")))]
6628 "TARGET_FPU"
6629 "fmuld\t%1, %2, %0"
6630 [(set_attr "type" "fpmul")
6631 (set_attr "fptype" "double")])
6632
6633 (define_insn "mulsf3"
6634 [(set (match_operand:SF 0 "register_operand" "=f")
6635 (mult:SF (match_operand:SF 1 "register_operand" "f")
6636 (match_operand:SF 2 "register_operand" "f")))]
6637 "TARGET_FPU"
6638 "fmuls\t%1, %2, %0"
6639 [(set_attr "type" "fpmul")])
6640
6641 (define_insn "*muldf3_extend"
6642 [(set (match_operand:DF 0 "register_operand" "=e")
6643 (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
6644 (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
6645 "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
6646 "fsmuld\t%1, %2, %0"
6647 [(set_attr "type" "fpmul")
6648 (set_attr "fptype" "double")])
6649
6650 (define_insn "*multf3_extend"
6651 [(set (match_operand:TF 0 "register_operand" "=e")
6652 (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
6653 (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
6654 "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
6655 "fdmulq\t%1, %2, %0"
6656 [(set_attr "type" "fpmul")])
6657
6658 (define_expand "divtf3"
6659 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6660 (div:TF (match_operand:TF 1 "general_operand" "")
6661 (match_operand:TF 2 "general_operand" "")))]
6662 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6663 "emit_tfmode_binop (DIV, operands); DONE;")
6664
6665 ;; don't have timing for quad-prec. divide.
6666 (define_insn "*divtf3_hq"
6667 [(set (match_operand:TF 0 "register_operand" "=e")
6668 (div:TF (match_operand:TF 1 "register_operand" "e")
6669 (match_operand:TF 2 "register_operand" "e")))]
6670 "TARGET_FPU && TARGET_HARD_QUAD"
6671 "fdivq\t%1, %2, %0"
6672 [(set_attr "type" "fpdivd")])
6673
6674 (define_insn "divdf3"
6675 [(set (match_operand:DF 0 "register_operand" "=e")
6676 (div:DF (match_operand:DF 1 "register_operand" "e")
6677 (match_operand:DF 2 "register_operand" "e")))]
6678 "TARGET_FPU"
6679 "fdivd\t%1, %2, %0"
6680 [(set_attr "type" "fpdivd")
6681 (set_attr "fptype" "double")])
6682
6683 (define_insn "divsf3"
6684 [(set (match_operand:SF 0 "register_operand" "=f")
6685 (div:SF (match_operand:SF 1 "register_operand" "f")
6686 (match_operand:SF 2 "register_operand" "f")))]
6687 "TARGET_FPU"
6688 "fdivs\t%1, %2, %0"
6689 [(set_attr "type" "fpdivs")])
6690
6691 (define_expand "negtf2"
6692 [(set (match_operand:TF 0 "register_operand" "=e,e")
6693 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6694 "TARGET_FPU"
6695 "")
6696
6697 (define_insn_and_split "*negtf2_notv9"
6698 [(set (match_operand:TF 0 "register_operand" "=e,e")
6699 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6700 ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6701 "TARGET_FPU
6702 && ! TARGET_V9"
6703 "@
6704 fnegs\t%0, %0
6705 #"
6706 "&& reload_completed
6707 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6708 [(set (match_dup 2) (neg:SF (match_dup 3)))
6709 (set (match_dup 4) (match_dup 5))
6710 (set (match_dup 6) (match_dup 7))]
6711 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6712 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6713 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6714 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
6715 operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6716 operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6717 [(set_attr "type" "fpmove,*")
6718 (set_attr "length" "*,2")])
6719
6720 (define_insn_and_split "*negtf2_v9"
6721 [(set (match_operand:TF 0 "register_operand" "=e,e")
6722 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6723 ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6724 "TARGET_FPU && TARGET_V9"
6725 "@
6726 fnegd\t%0, %0
6727 #"
6728 "&& reload_completed
6729 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6730 [(set (match_dup 2) (neg:DF (match_dup 3)))
6731 (set (match_dup 4) (match_dup 5))]
6732 "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
6733 operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
6734 operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6735 operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6736 [(set_attr "type" "fpmove,*")
6737 (set_attr "length" "*,2")
6738 (set_attr "fptype" "double")])
6739
6740 (define_expand "negdf2"
6741 [(set (match_operand:DF 0 "register_operand" "")
6742 (neg:DF (match_operand:DF 1 "register_operand" "")))]
6743 "TARGET_FPU"
6744 "")
6745
6746 (define_insn_and_split "*negdf2_notv9"
6747 [(set (match_operand:DF 0 "register_operand" "=e,e")
6748 (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
6749 "TARGET_FPU && ! TARGET_V9"
6750 "@
6751 fnegs\t%0, %0
6752 #"
6753 "&& reload_completed
6754 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6755 [(set (match_dup 2) (neg:SF (match_dup 3)))
6756 (set (match_dup 4) (match_dup 5))]
6757 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6758 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6759 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6760 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
6761 [(set_attr "type" "fpmove,*")
6762 (set_attr "length" "*,2")])
6763
6764 (define_insn "*negdf2_v9"
6765 [(set (match_operand:DF 0 "register_operand" "=e")
6766 (neg:DF (match_operand:DF 1 "register_operand" "e")))]
6767 "TARGET_FPU && TARGET_V9"
6768 "fnegd\t%1, %0"
6769 [(set_attr "type" "fpmove")
6770 (set_attr "fptype" "double")])
6771
6772 (define_insn "negsf2"
6773 [(set (match_operand:SF 0 "register_operand" "=f")
6774 (neg:SF (match_operand:SF 1 "register_operand" "f")))]
6775 "TARGET_FPU"
6776 "fnegs\t%1, %0"
6777 [(set_attr "type" "fpmove")])
6778
6779 (define_expand "abstf2"
6780 [(set (match_operand:TF 0 "register_operand" "")
6781 (abs:TF (match_operand:TF 1 "register_operand" "")))]
6782 "TARGET_FPU"
6783 "")
6784
6785 (define_insn_and_split "*abstf2_notv9"
6786 [(set (match_operand:TF 0 "register_operand" "=e,e")
6787 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6788 ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6789 "TARGET_FPU && ! TARGET_V9"
6790 "@
6791 fabss\t%0, %0
6792 #"
6793 "&& reload_completed
6794 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6795 [(set (match_dup 2) (abs:SF (match_dup 3)))
6796 (set (match_dup 4) (match_dup 5))
6797 (set (match_dup 6) (match_dup 7))]
6798 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6799 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6800 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6801 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
6802 operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6803 operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6804 [(set_attr "type" "fpmove,*")
6805 (set_attr "length" "*,2")])
6806
6807 (define_insn "*abstf2_hq_v9"
6808 [(set (match_operand:TF 0 "register_operand" "=e,e")
6809 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6810 "TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
6811 "@
6812 fabsd\t%0, %0
6813 fabsq\t%1, %0"
6814 [(set_attr "type" "fpmove")
6815 (set_attr "fptype" "double,*")])
6816
6817 (define_insn_and_split "*abstf2_v9"
6818 [(set (match_operand:TF 0 "register_operand" "=e,e")
6819 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6820 "TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
6821 "@
6822 fabsd\t%0, %0
6823 #"
6824 "&& reload_completed
6825 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6826 [(set (match_dup 2) (abs:DF (match_dup 3)))
6827 (set (match_dup 4) (match_dup 5))]
6828 "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
6829 operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
6830 operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6831 operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6832 [(set_attr "type" "fpmove,*")
6833 (set_attr "length" "*,2")
6834 (set_attr "fptype" "double,*")])
6835
6836 (define_expand "absdf2"
6837 [(set (match_operand:DF 0 "register_operand" "")
6838 (abs:DF (match_operand:DF 1 "register_operand" "")))]
6839 "TARGET_FPU"
6840 "")
6841
6842 (define_insn_and_split "*absdf2_notv9"
6843 [(set (match_operand:DF 0 "register_operand" "=e,e")
6844 (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
6845 "TARGET_FPU && ! TARGET_V9"
6846 "@
6847 fabss\t%0, %0
6848 #"
6849 "&& reload_completed
6850 && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6851 [(set (match_dup 2) (abs:SF (match_dup 3)))
6852 (set (match_dup 4) (match_dup 5))]
6853 "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6854 operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6855 operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6856 operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
6857 [(set_attr "type" "fpmove,*")
6858 (set_attr "length" "*,2")])
6859
6860 (define_insn "*absdf2_v9"
6861 [(set (match_operand:DF 0 "register_operand" "=e")
6862 (abs:DF (match_operand:DF 1 "register_operand" "e")))]
6863 "TARGET_FPU && TARGET_V9"
6864 "fabsd\t%1, %0"
6865 [(set_attr "type" "fpmove")
6866 (set_attr "fptype" "double")])
6867
6868 (define_insn "abssf2"
6869 [(set (match_operand:SF 0 "register_operand" "=f")
6870 (abs:SF (match_operand:SF 1 "register_operand" "f")))]
6871 "TARGET_FPU"
6872 "fabss\t%1, %0"
6873 [(set_attr "type" "fpmove")])
6874
6875 (define_expand "sqrttf2"
6876 [(set (match_operand:TF 0 "nonimmediate_operand" "")
6877 (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
6878 "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6879 "emit_tfmode_unop (SQRT, operands); DONE;")
6880
6881 (define_insn "*sqrttf2_hq"
6882 [(set (match_operand:TF 0 "register_operand" "=e")
6883 (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
6884 "TARGET_FPU && TARGET_HARD_QUAD"
6885 "fsqrtq\t%1, %0"
6886 [(set_attr "type" "fpsqrtd")])
6887
6888 (define_insn "sqrtdf2"
6889 [(set (match_operand:DF 0 "register_operand" "=e")
6890 (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
6891 "TARGET_FPU"
6892 "fsqrtd\t%1, %0"
6893 [(set_attr "type" "fpsqrtd")
6894 (set_attr "fptype" "double")])
6895
6896 (define_insn "sqrtsf2"
6897 [(set (match_operand:SF 0 "register_operand" "=f")
6898 (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
6899 "TARGET_FPU"
6900 "fsqrts\t%1, %0"
6901 [(set_attr "type" "fpsqrts")])
6902 \f
6903 ;;- arithmetic shift instructions
6904
6905 (define_insn "ashlsi3"
6906 [(set (match_operand:SI 0 "register_operand" "=r")
6907 (ashift:SI (match_operand:SI 1 "register_operand" "r")
6908 (match_operand:SI 2 "arith_operand" "rI")))]
6909 ""
6910 {
6911 if (operands[2] == const1_rtx)
6912 return "add\t%1, %1, %0";
6913 return "sll\t%1, %2, %0";
6914 }
6915 [(set (attr "type")
6916 (if_then_else (match_operand 2 "const1_operand" "")
6917 (const_string "ialu") (const_string "shift")))])
6918
6919 (define_expand "ashldi3"
6920 [(set (match_operand:DI 0 "register_operand" "=r")
6921 (ashift:DI (match_operand:DI 1 "register_operand" "r")
6922 (match_operand:SI 2 "arith_operand" "rI")))]
6923 "TARGET_ARCH64 || TARGET_V8PLUS"
6924 {
6925 if (! TARGET_ARCH64)
6926 {
6927 if (GET_CODE (operands[2]) == CONST_INT)
6928 FAIL;
6929 emit_insn (gen_ashldi3_v8plus (operands[0], operands[1], operands[2]));
6930 DONE;
6931 }
6932 })
6933
6934 (define_insn "*ashldi3_sp64"
6935 [(set (match_operand:DI 0 "register_operand" "=r")
6936 (ashift:DI (match_operand:DI 1 "register_operand" "r")
6937 (match_operand:SI 2 "arith_operand" "rI")))]
6938 "TARGET_ARCH64"
6939 {
6940 if (operands[2] == const1_rtx)
6941 return "add\t%1, %1, %0";
6942 return "sllx\t%1, %2, %0";
6943 }
6944 [(set (attr "type")
6945 (if_then_else (match_operand 2 "const1_operand" "")
6946 (const_string "ialu") (const_string "shift")))])
6947
6948 ;; XXX UGH!
6949 (define_insn "ashldi3_v8plus"
6950 [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
6951 (ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
6952 (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
6953 (clobber (match_scratch:SI 3 "=X,X,&h"))]
6954 "TARGET_V8PLUS"
6955 { return sparc_v8plus_shift (operands, insn, "sllx"); }
6956 [(set_attr "type" "multi")
6957 (set_attr "length" "5,5,6")])
6958
6959 ;; Optimize (1LL<<x)-1
6960 ;; XXX this also needs to be fixed to handle equal subregs
6961 ;; XXX first before we could re-enable it.
6962 ;(define_insn ""
6963 ; [(set (match_operand:DI 0 "register_operand" "=h")
6964 ; (plus:DI (ashift:DI (const_int 1)
6965 ; (match_operand:SI 1 "arith_operand" "rI"))
6966 ; (const_int -1)))]
6967 ; "0 && TARGET_V8PLUS"
6968 ;{
6969 ; if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == REGNO (operands[0]))
6970 ; return "mov\t1, %L0\;sllx\t%L0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
6971 ; return "mov\t1, %H0\;sllx\t%H0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
6972 ;}
6973 ; [(set_attr "type" "multi")
6974 ; (set_attr "length" "4")])
6975
6976 (define_insn "*cmp_cc_ashift_1"
6977 [(set (reg:CC_NOOV 100)
6978 (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
6979 (const_int 1))
6980 (const_int 0)))]
6981 ""
6982 "addcc\t%0, %0, %%g0"
6983 [(set_attr "type" "compare")])
6984
6985 (define_insn "*cmp_cc_set_ashift_1"
6986 [(set (reg:CC_NOOV 100)
6987 (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
6988 (const_int 1))
6989 (const_int 0)))
6990 (set (match_operand:SI 0 "register_operand" "=r")
6991 (ashift:SI (match_dup 1) (const_int 1)))]
6992 ""
6993 "addcc\t%1, %1, %0"
6994 [(set_attr "type" "compare")])
6995
6996 (define_insn "ashrsi3"
6997 [(set (match_operand:SI 0 "register_operand" "=r")
6998 (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
6999 (match_operand:SI 2 "arith_operand" "rI")))]
7000 ""
7001 "sra\t%1, %2, %0"
7002 [(set_attr "type" "shift")])
7003
7004 (define_insn "*ashrsi3_extend"
7005 [(set (match_operand:DI 0 "register_operand" "=r")
7006 (sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
7007 (match_operand:SI 2 "arith_operand" "r"))))]
7008 "TARGET_ARCH64"
7009 "sra\t%1, %2, %0"
7010 [(set_attr "type" "shift")])
7011
7012 ;; This handles the case as above, but with constant shift instead of
7013 ;; register. Combiner "simplifies" it for us a little bit though.
7014 (define_insn "*ashrsi3_extend2"
7015 [(set (match_operand:DI 0 "register_operand" "=r")
7016 (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
7017 (const_int 32))
7018 (match_operand:SI 2 "small_int_or_double" "n")))]
7019 "TARGET_ARCH64
7020 && ((GET_CODE (operands[2]) == CONST_INT
7021 && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64)
7022 || (GET_CODE (operands[2]) == CONST_DOUBLE
7023 && !CONST_DOUBLE_HIGH (operands[2])
7024 && CONST_DOUBLE_LOW (operands[2]) >= 32
7025 && CONST_DOUBLE_LOW (operands[2]) < 64))"
7026 {
7027 operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
7028
7029 return "sra\t%1, %2, %0";
7030 }
7031 [(set_attr "type" "shift")])
7032
7033 (define_expand "ashrdi3"
7034 [(set (match_operand:DI 0 "register_operand" "=r")
7035 (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7036 (match_operand:SI 2 "arith_operand" "rI")))]
7037 "TARGET_ARCH64 || TARGET_V8PLUS"
7038 {
7039 if (! TARGET_ARCH64)
7040 {
7041 if (GET_CODE (operands[2]) == CONST_INT)
7042 FAIL; /* prefer generic code in this case */
7043 emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
7044 DONE;
7045 }
7046 })
7047
7048 (define_insn ""
7049 [(set (match_operand:DI 0 "register_operand" "=r")
7050 (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7051 (match_operand:SI 2 "arith_operand" "rI")))]
7052 "TARGET_ARCH64"
7053 "srax\t%1, %2, %0"
7054 [(set_attr "type" "shift")])
7055
7056 ;; XXX
7057 (define_insn "ashrdi3_v8plus"
7058 [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
7059 (ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
7060 (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
7061 (clobber (match_scratch:SI 3 "=X,X,&h"))]
7062 "TARGET_V8PLUS"
7063 { return sparc_v8plus_shift (operands, insn, "srax"); }
7064 [(set_attr "type" "multi")
7065 (set_attr "length" "5,5,6")])
7066
7067 (define_insn "lshrsi3"
7068 [(set (match_operand:SI 0 "register_operand" "=r")
7069 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
7070 (match_operand:SI 2 "arith_operand" "rI")))]
7071 ""
7072 "srl\t%1, %2, %0"
7073 [(set_attr "type" "shift")])
7074
7075 ;; This handles the case where
7076 ;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
7077 ;; but combiner "simplifies" it for us.
7078 (define_insn "*lshrsi3_extend"
7079 [(set (match_operand:DI 0 "register_operand" "=r")
7080 (and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
7081 (match_operand:SI 2 "arith_operand" "r")) 0)
7082 (match_operand 3 "" "")))]
7083 "TARGET_ARCH64
7084 && ((GET_CODE (operands[3]) == CONST_DOUBLE
7085 && CONST_DOUBLE_HIGH (operands[3]) == 0
7086 && CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
7087 || (HOST_BITS_PER_WIDE_INT >= 64
7088 && GET_CODE (operands[3]) == CONST_INT
7089 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff))"
7090 "srl\t%1, %2, %0"
7091 [(set_attr "type" "shift")])
7092
7093 ;; This handles the case where
7094 ;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int >=0 < 32))
7095 ;; but combiner "simplifies" it for us.
7096 (define_insn "*lshrsi3_extend2"
7097 [(set (match_operand:DI 0 "register_operand" "=r")
7098 (zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
7099 (match_operand 2 "small_int_or_double" "n")
7100 (const_int 32)))]
7101 "TARGET_ARCH64
7102 && ((GET_CODE (operands[2]) == CONST_INT
7103 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7104 || (GET_CODE (operands[2]) == CONST_DOUBLE
7105 && CONST_DOUBLE_HIGH (operands[2]) == 0
7106 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7107 {
7108 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
7109
7110 return "srl\t%1, %2, %0";
7111 }
7112 [(set_attr "type" "shift")])
7113
7114 (define_expand "lshrdi3"
7115 [(set (match_operand:DI 0 "register_operand" "=r")
7116 (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7117 (match_operand:SI 2 "arith_operand" "rI")))]
7118 "TARGET_ARCH64 || TARGET_V8PLUS"
7119 {
7120 if (! TARGET_ARCH64)
7121 {
7122 if (GET_CODE (operands[2]) == CONST_INT)
7123 FAIL;
7124 emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
7125 DONE;
7126 }
7127 })
7128
7129 (define_insn ""
7130 [(set (match_operand:DI 0 "register_operand" "=r")
7131 (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7132 (match_operand:SI 2 "arith_operand" "rI")))]
7133 "TARGET_ARCH64"
7134 "srlx\t%1, %2, %0"
7135 [(set_attr "type" "shift")])
7136
7137 ;; XXX
7138 (define_insn "lshrdi3_v8plus"
7139 [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
7140 (lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
7141 (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
7142 (clobber (match_scratch:SI 3 "=X,X,&h"))]
7143 "TARGET_V8PLUS"
7144 { return sparc_v8plus_shift (operands, insn, "srlx"); }
7145 [(set_attr "type" "multi")
7146 (set_attr "length" "5,5,6")])
7147
7148 (define_insn ""
7149 [(set (match_operand:SI 0 "register_operand" "=r")
7150 (ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7151 (const_int 32)) 4)
7152 (match_operand:SI 2 "small_int_or_double" "n")))]
7153 "TARGET_ARCH64
7154 && ((GET_CODE (operands[2]) == CONST_INT
7155 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7156 || (GET_CODE (operands[2]) == CONST_DOUBLE
7157 && !CONST_DOUBLE_HIGH (operands[2])
7158 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7159 {
7160 operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
7161
7162 return "srax\t%1, %2, %0";
7163 }
7164 [(set_attr "type" "shift")])
7165
7166 (define_insn ""
7167 [(set (match_operand:SI 0 "register_operand" "=r")
7168 (lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7169 (const_int 32)) 4)
7170 (match_operand:SI 2 "small_int_or_double" "n")))]
7171 "TARGET_ARCH64
7172 && ((GET_CODE (operands[2]) == CONST_INT
7173 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7174 || (GET_CODE (operands[2]) == CONST_DOUBLE
7175 && !CONST_DOUBLE_HIGH (operands[2])
7176 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7177 {
7178 operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
7179
7180 return "srlx\t%1, %2, %0";
7181 }
7182 [(set_attr "type" "shift")])
7183
7184 (define_insn ""
7185 [(set (match_operand:SI 0 "register_operand" "=r")
7186 (ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7187 (match_operand:SI 2 "small_int_or_double" "n")) 4)
7188 (match_operand:SI 3 "small_int_or_double" "n")))]
7189 "TARGET_ARCH64
7190 && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
7191 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
7192 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
7193 && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
7194 {
7195 operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
7196
7197 return "srax\t%1, %2, %0";
7198 }
7199 [(set_attr "type" "shift")])
7200
7201 (define_insn ""
7202 [(set (match_operand:SI 0 "register_operand" "=r")
7203 (lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7204 (match_operand:SI 2 "small_int_or_double" "n")) 4)
7205 (match_operand:SI 3 "small_int_or_double" "n")))]
7206 "TARGET_ARCH64
7207 && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
7208 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
7209 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
7210 && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
7211 {
7212 operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
7213
7214 return "srlx\t%1, %2, %0";
7215 }
7216 [(set_attr "type" "shift")])
7217 \f
7218 ;; Unconditional and other jump instructions
7219 ;; On the SPARC, by setting the annul bit on an unconditional branch, the
7220 ;; following insn is never executed. This saves us a nop. Dbx does not
7221 ;; handle such branches though, so we only use them when optimizing.
7222 (define_insn "jump"
7223 [(set (pc) (label_ref (match_operand 0 "" "")))]
7224 ""
7225 {
7226 /* TurboSPARC is reported to have problems with
7227 with
7228 foo: b,a foo
7229 i.e. an empty loop with the annul bit set. The workaround is to use
7230 foo: b foo; nop
7231 instead. */
7232
7233 if (! TARGET_V9 && flag_delayed_branch
7234 && (INSN_ADDRESSES (INSN_UID (operands[0]))
7235 == INSN_ADDRESSES (INSN_UID (insn))))
7236 return "b\t%l0%#";
7237 else
7238 return TARGET_V9 ? "ba,pt%*\t%%xcc, %l0%(" : "b%*\t%l0%(";
7239 }
7240 [(set_attr "type" "uncond_branch")])
7241
7242 (define_expand "tablejump"
7243 [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
7244 (use (label_ref (match_operand 1 "" "")))])]
7245 ""
7246 {
7247 if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
7248 abort ();
7249
7250 /* In pic mode, our address differences are against the base of the
7251 table. Add that base value back in; CSE ought to be able to combine
7252 the two address loads. */
7253 if (flag_pic)
7254 {
7255 rtx tmp, tmp2;
7256 tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
7257 tmp2 = operands[0];
7258 if (CASE_VECTOR_MODE != Pmode)
7259 tmp2 = gen_rtx_SIGN_EXTEND (Pmode, tmp2);
7260 tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
7261 operands[0] = memory_address (Pmode, tmp);
7262 }
7263 })
7264
7265 (define_insn "*tablejump_sp32"
7266 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
7267 (use (label_ref (match_operand 1 "" "")))]
7268 "! TARGET_ARCH64"
7269 "jmp\t%a0%#"
7270 [(set_attr "type" "uncond_branch")])
7271
7272 (define_insn "*tablejump_sp64"
7273 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
7274 (use (label_ref (match_operand 1 "" "")))]
7275 "TARGET_ARCH64"
7276 "jmp\t%a0%#"
7277 [(set_attr "type" "uncond_branch")])
7278
7279 ;; This pattern recognizes the "instruction" that appears in
7280 ;; a function call that wants a structure value,
7281 ;; to inform the called function if compiled with Sun CC.
7282 ;(define_insn "*unimp_insn"
7283 ; [(match_operand:SI 0 "immediate_operand" "")]
7284 ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
7285 ; "unimp\t%0"
7286 ; [(set_attr "type" "marker")])
7287
7288 ;;- jump to subroutine
7289 (define_expand "call"
7290 ;; Note that this expression is not used for generating RTL.
7291 ;; All the RTL is generated explicitly below.
7292 [(call (match_operand 0 "call_operand" "")
7293 (match_operand 3 "" "i"))]
7294 ;; operands[2] is next_arg_register
7295 ;; operands[3] is struct_value_size_rtx.
7296 ""
7297 {
7298 rtx fn_rtx, nregs_rtx;
7299
7300 if (GET_MODE (operands[0]) != FUNCTION_MODE)
7301 abort ();
7302
7303 if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
7304 {
7305 /* This is really a PIC sequence. We want to represent
7306 it as a funny jump so its delay slots can be filled.
7307
7308 ??? But if this really *is* a CALL, will not it clobber the
7309 call-clobbered registers? We lose this if it is a JUMP_INSN.
7310 Why cannot we have delay slots filled if it were a CALL? */
7311
7312 if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
7313 emit_jump_insn
7314 (gen_rtx_PARALLEL
7315 (VOIDmode,
7316 gen_rtvec (3,
7317 gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
7318 operands[3],
7319 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7320 else
7321 emit_jump_insn
7322 (gen_rtx_PARALLEL
7323 (VOIDmode,
7324 gen_rtvec (2,
7325 gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
7326 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7327 goto finish_call;
7328 }
7329
7330 fn_rtx = operands[0];
7331
7332 /* Count the number of parameter registers being used by this call.
7333 if that argument is NULL, it means we are using them all, which
7334 means 6 on the sparc. */
7335 #if 0
7336 if (operands[2])
7337 nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
7338 else
7339 nregs_rtx = GEN_INT (6);
7340 #else
7341 nregs_rtx = const0_rtx;
7342 #endif
7343
7344 if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
7345 emit_call_insn
7346 (gen_rtx_PARALLEL
7347 (VOIDmode,
7348 gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
7349 operands[3],
7350 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7351 else
7352 emit_call_insn
7353 (gen_rtx_PARALLEL
7354 (VOIDmode,
7355 gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
7356 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7357
7358 finish_call:
7359 #if 0
7360 /* If this call wants a structure value,
7361 emit an unimp insn to let the called function know about this. */
7362 if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
7363 {
7364 rtx insn = emit_insn (operands[3]);
7365 SCHED_GROUP_P (insn) = 1;
7366 }
7367 #endif
7368
7369 DONE;
7370 })
7371
7372 ;; We can't use the same pattern for these two insns, because then registers
7373 ;; in the address may not be properly reloaded.
7374
7375 (define_insn "*call_address_sp32"
7376 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7377 (match_operand 1 "" ""))
7378 (clobber (reg:SI 15))]
7379 ;;- Do not use operand 1 for most machines.
7380 "! TARGET_ARCH64"
7381 "call\t%a0, %1%#"
7382 [(set_attr "type" "call")])
7383
7384 (define_insn "*call_symbolic_sp32"
7385 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7386 (match_operand 1 "" ""))
7387 (clobber (reg:SI 15))]
7388 ;;- Do not use operand 1 for most machines.
7389 "! TARGET_ARCH64"
7390 "call\t%a0, %1%#"
7391 [(set_attr "type" "call")])
7392
7393 (define_insn "*call_address_sp64"
7394 [(call (mem:DI (match_operand:DI 0 "address_operand" "p"))
7395 (match_operand 1 "" ""))
7396 (clobber (reg:DI 15))]
7397 ;;- Do not use operand 1 for most machines.
7398 "TARGET_ARCH64"
7399 "call\t%a0, %1%#"
7400 [(set_attr "type" "call")])
7401
7402 (define_insn "*call_symbolic_sp64"
7403 [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
7404 (match_operand 1 "" ""))
7405 (clobber (reg:DI 15))]
7406 ;;- Do not use operand 1 for most machines.
7407 "TARGET_ARCH64"
7408 "call\t%a0, %1%#"
7409 [(set_attr "type" "call")])
7410
7411 ;; This is a call that wants a structure value.
7412 ;; There is no such critter for v9 (??? we may need one anyway).
7413 (define_insn "*call_address_struct_value_sp32"
7414 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7415 (match_operand 1 "" ""))
7416 (match_operand 2 "immediate_operand" "")
7417 (clobber (reg:SI 15))]
7418 ;;- Do not use operand 1 for most machines.
7419 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
7420 "call\t%a0, %1\n\tnop\n\tunimp\t%2"
7421 [(set_attr "type" "call_no_delay_slot")
7422 (set_attr "length" "3")])
7423
7424 ;; This is a call that wants a structure value.
7425 ;; There is no such critter for v9 (??? we may need one anyway).
7426 (define_insn "*call_symbolic_struct_value_sp32"
7427 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7428 (match_operand 1 "" ""))
7429 (match_operand 2 "immediate_operand" "")
7430 (clobber (reg:SI 15))]
7431 ;;- Do not use operand 1 for most machines.
7432 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
7433 "call\t%a0, %1\n\tnop\n\tunimp\t%2"
7434 [(set_attr "type" "call_no_delay_slot")
7435 (set_attr "length" "3")])
7436
7437 ;; This is a call that may want a structure value. This is used for
7438 ;; untyped_calls.
7439 (define_insn "*call_address_untyped_struct_value_sp32"
7440 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7441 (match_operand 1 "" ""))
7442 (match_operand 2 "immediate_operand" "")
7443 (clobber (reg:SI 15))]
7444 ;;- Do not use operand 1 for most machines.
7445 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
7446 "call\t%a0, %1\n\tnop\n\tnop"
7447 [(set_attr "type" "call_no_delay_slot")
7448 (set_attr "length" "3")])
7449
7450 ;; This is a call that wants a structure value.
7451 (define_insn "*call_symbolic_untyped_struct_value_sp32"
7452 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7453 (match_operand 1 "" ""))
7454 (match_operand 2 "immediate_operand" "")
7455 (clobber (reg:SI 15))]
7456 ;;- Do not use operand 1 for most machines.
7457 "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
7458 "call\t%a0, %1\n\tnop\n\tnop"
7459 [(set_attr "type" "call_no_delay_slot")
7460 (set_attr "length" "3")])
7461
7462 (define_expand "call_value"
7463 ;; Note that this expression is not used for generating RTL.
7464 ;; All the RTL is generated explicitly below.
7465 [(set (match_operand 0 "register_operand" "=rf")
7466 (call (match_operand 1 "" "")
7467 (match_operand 4 "" "")))]
7468 ;; operand 2 is stack_size_rtx
7469 ;; operand 3 is next_arg_register
7470 ""
7471 {
7472 rtx fn_rtx, nregs_rtx;
7473 rtvec vec;
7474
7475 if (GET_MODE (operands[1]) != FUNCTION_MODE)
7476 abort ();
7477
7478 fn_rtx = operands[1];
7479
7480 #if 0
7481 if (operands[3])
7482 nregs_rtx = GEN_INT (REGNO (operands[3]) - 8);
7483 else
7484 nregs_rtx = GEN_INT (6);
7485 #else
7486 nregs_rtx = const0_rtx;
7487 #endif
7488
7489 vec = gen_rtvec (2,
7490 gen_rtx_SET (VOIDmode, operands[0],
7491 gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
7492 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
7493
7494 emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
7495
7496 DONE;
7497 })
7498
7499 (define_insn "*call_value_address_sp32"
7500 [(set (match_operand 0 "" "=rf")
7501 (call (mem:SI (match_operand:SI 1 "address_operand" "p"))
7502 (match_operand 2 "" "")))
7503 (clobber (reg:SI 15))]
7504 ;;- Do not use operand 2 for most machines.
7505 "! TARGET_ARCH64"
7506 "call\t%a1, %2%#"
7507 [(set_attr "type" "call")])
7508
7509 (define_insn "*call_value_symbolic_sp32"
7510 [(set (match_operand 0 "" "=rf")
7511 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
7512 (match_operand 2 "" "")))
7513 (clobber (reg:SI 15))]
7514 ;;- Do not use operand 2 for most machines.
7515 "! TARGET_ARCH64"
7516 "call\t%a1, %2%#"
7517 [(set_attr "type" "call")])
7518
7519 (define_insn "*call_value_address_sp64"
7520 [(set (match_operand 0 "" "")
7521 (call (mem:DI (match_operand:DI 1 "address_operand" "p"))
7522 (match_operand 2 "" "")))
7523 (clobber (reg:DI 15))]
7524 ;;- Do not use operand 2 for most machines.
7525 "TARGET_ARCH64"
7526 "call\t%a1, %2%#"
7527 [(set_attr "type" "call")])
7528
7529 (define_insn "*call_value_symbolic_sp64"
7530 [(set (match_operand 0 "" "")
7531 (call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
7532 (match_operand 2 "" "")))
7533 (clobber (reg:DI 15))]
7534 ;;- Do not use operand 2 for most machines.
7535 "TARGET_ARCH64"
7536 "call\t%a1, %2%#"
7537 [(set_attr "type" "call")])
7538
7539 (define_expand "untyped_call"
7540 [(parallel [(call (match_operand 0 "" "")
7541 (const_int 0))
7542 (match_operand 1 "" "")
7543 (match_operand 2 "" "")])]
7544 ""
7545 {
7546 int i;
7547
7548 /* Pass constm1 to indicate that it may expect a structure value, but
7549 we don't know what size it is. */
7550 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));
7551
7552 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7553 {
7554 rtx set = XVECEXP (operands[2], 0, i);
7555 emit_move_insn (SET_DEST (set), SET_SRC (set));
7556 }
7557
7558 /* The optimizer does not know that the call sets the function value
7559 registers we stored in the result block. We avoid problems by
7560 claiming that all hard registers are used and clobbered at this
7561 point. */
7562 emit_insn (gen_blockage ());
7563
7564 DONE;
7565 })
7566
7567 ;;- tail calls
7568 (define_expand "sibcall"
7569 [(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
7570 (return)])]
7571 ""
7572 "")
7573
7574 (define_insn "*sibcall_symbolic_sp32"
7575 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7576 (match_operand 1 "" ""))
7577 (return)]
7578 "! TARGET_ARCH64"
7579 "* return output_sibcall(insn, operands[0]);"
7580 [(set_attr "type" "sibcall")])
7581
7582 (define_insn "*sibcall_symbolic_sp64"
7583 [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
7584 (match_operand 1 "" ""))
7585 (return)]
7586 "TARGET_ARCH64"
7587 "* return output_sibcall(insn, operands[0]);"
7588 [(set_attr "type" "sibcall")])
7589
7590 (define_expand "sibcall_value"
7591 [(parallel [(set (match_operand 0 "register_operand" "=rf")
7592 (call (match_operand 1 "" "") (const_int 0)))
7593 (return)])]
7594 ""
7595 "")
7596
7597 (define_insn "*sibcall_value_symbolic_sp32"
7598 [(set (match_operand 0 "" "=rf")
7599 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
7600 (match_operand 2 "" "")))
7601 (return)]
7602 "! TARGET_ARCH64"
7603 "* return output_sibcall(insn, operands[1]);"
7604 [(set_attr "type" "sibcall")])
7605
7606 (define_insn "*sibcall_value_symbolic_sp64"
7607 [(set (match_operand 0 "" "")
7608 (call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
7609 (match_operand 2 "" "")))
7610 (return)]
7611 "TARGET_ARCH64"
7612 "* return output_sibcall(insn, operands[1]);"
7613 [(set_attr "type" "sibcall")])
7614
7615 (define_expand "sibcall_epilogue"
7616 [(const_int 0)]
7617 ""
7618 "DONE;")
7619
7620 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7621 ;; all of memory. This blocks insns from being moved across this point.
7622
7623 (define_insn "blockage"
7624 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7625 ""
7626 ""
7627 [(set_attr "length" "0")])
7628
7629 ;; Prepare to return any type including a structure value.
7630
7631 (define_expand "untyped_return"
7632 [(match_operand:BLK 0 "memory_operand" "")
7633 (match_operand 1 "" "")]
7634 ""
7635 {
7636 rtx valreg1 = gen_rtx_REG (DImode, 24);
7637 rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
7638 rtx result = operands[0];
7639
7640 if (! TARGET_ARCH64)
7641 {
7642 rtx rtnreg = gen_rtx_REG (SImode, (current_function_uses_only_leaf_regs
7643 ? 15 : 31));
7644 rtx value = gen_reg_rtx (SImode);
7645
7646 /* Fetch the instruction where we will return to and see if it's an unimp
7647 instruction (the most significant 10 bits will be zero). If so,
7648 update the return address to skip the unimp instruction. */
7649 emit_move_insn (value,
7650 gen_rtx_MEM (SImode, plus_constant (rtnreg, 8)));
7651 emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
7652 emit_insn (gen_update_return (rtnreg, value));
7653 }
7654
7655 /* Reload the function value registers. */
7656 emit_move_insn (valreg1, adjust_address (result, DImode, 0));
7657 emit_move_insn (valreg2,
7658 adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8));
7659
7660 /* Put USE insns before the return. */
7661 emit_insn (gen_rtx_USE (VOIDmode, valreg1));
7662 emit_insn (gen_rtx_USE (VOIDmode, valreg2));
7663
7664 /* Construct the return. */
7665 expand_null_return ();
7666
7667 DONE;
7668 })
7669
7670 ;; This is a bit of a hack. We're incrementing a fixed register (%i7),
7671 ;; and parts of the compiler don't want to believe that the add is needed.
7672
7673 (define_insn "update_return"
7674 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
7675 (match_operand:SI 1 "register_operand" "r")] UNSPEC_UPDATE_RETURN)]
7676 "! TARGET_ARCH64"
7677 "cmp\t%1, 0\;be,a\t.+8\;add\t%0, 4, %0"
7678 [(set_attr "type" "multi")
7679 (set_attr "length" "3")])
7680 \f
7681 (define_insn "nop"
7682 [(const_int 0)]
7683 ""
7684 "nop")
7685
7686 (define_expand "indirect_jump"
7687 [(set (pc) (match_operand 0 "address_operand" "p"))]
7688 ""
7689 "")
7690
7691 (define_insn "*branch_sp32"
7692 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
7693 "! TARGET_ARCH64"
7694 "jmp\t%a0%#"
7695 [(set_attr "type" "uncond_branch")])
7696
7697 (define_insn "*branch_sp64"
7698 [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
7699 "TARGET_ARCH64"
7700 "jmp\t%a0%#"
7701 [(set_attr "type" "uncond_branch")])
7702
7703 ;; ??? Doesn't work with -mflat.
7704 (define_expand "nonlocal_goto"
7705 [(match_operand:SI 0 "general_operand" "")
7706 (match_operand:SI 1 "general_operand" "")
7707 (match_operand:SI 2 "general_operand" "")
7708 (match_operand:SI 3 "" "")]
7709 ""
7710 {
7711 #if 0
7712 rtx chain = operands[0];
7713 #endif
7714 rtx lab = operands[1];
7715 rtx stack = operands[2];
7716 rtx fp = operands[3];
7717 rtx labreg;
7718
7719 /* Trap instruction to flush all the register windows. */
7720 emit_insn (gen_flush_register_windows ());
7721
7722 /* Load the fp value for the containing fn into %fp. This is needed
7723 because STACK refers to %fp. Note that virtual register instantiation
7724 fails if the virtual %fp isn't set from a register. */
7725 if (GET_CODE (fp) != REG)
7726 fp = force_reg (Pmode, fp);
7727 emit_move_insn (virtual_stack_vars_rtx, fp);
7728
7729 /* Find the containing function's current nonlocal goto handler,
7730 which will do any cleanups and then jump to the label. */
7731 labreg = gen_rtx_REG (Pmode, 8);
7732 emit_move_insn (labreg, lab);
7733
7734 /* Restore %fp from stack pointer value for containing function.
7735 The restore insn that follows will move this to %sp,
7736 and reload the appropriate value into %fp. */
7737 emit_move_insn (hard_frame_pointer_rtx, stack);
7738
7739 /* USE of frame_pointer_rtx added for consistency; not clear if
7740 really needed. */
7741 /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
7742 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
7743
7744 #if 0
7745 /* Return, restoring reg window and jumping to goto handler. */
7746 if (TARGET_V9 && GET_CODE (chain) == CONST_INT
7747 && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
7748 {
7749 emit_jump_insn (gen_goto_handler_and_restore_v9 (labreg,
7750 static_chain_rtx,
7751 chain));
7752 emit_barrier ();
7753 DONE;
7754 }
7755 /* Put in the static chain register the nonlocal label address. */
7756 emit_move_insn (static_chain_rtx, chain);
7757 #endif
7758
7759 emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
7760 emit_jump_insn (gen_goto_handler_and_restore (labreg));
7761 emit_barrier ();
7762 DONE;
7763 })
7764
7765 ;; Special trap insn to flush register windows.
7766 (define_insn "flush_register_windows"
7767 [(unspec_volatile [(const_int 0)] UNSPECV_FLUSHW)]
7768 ""
7769 { return TARGET_V9 ? "flushw" : "ta\t3"; }
7770 [(set_attr "type" "flushw")])
7771
7772 (define_insn "goto_handler_and_restore"
7773 [(unspec_volatile [(match_operand 0 "register_operand" "=r")] UNSPECV_GOTO)]
7774 "GET_MODE (operands[0]) == Pmode"
7775 "jmp\t%0+0\n\trestore"
7776 [(set_attr "type" "multi")
7777 (set_attr "length" "2")])
7778
7779 ;;(define_insn "goto_handler_and_restore_v9"
7780 ;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
7781 ;; (match_operand:SI 1 "register_operand" "=r,r")
7782 ;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
7783 ;; "TARGET_V9 && ! TARGET_ARCH64"
7784 ;; "@
7785 ;; return\t%0+0\n\tmov\t%2, %Y1
7786 ;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
7787 ;; [(set_attr "type" "multi")
7788 ;; (set_attr "length" "2,3")])
7789 ;;
7790 ;;(define_insn "*goto_handler_and_restore_v9_sp64"
7791 ;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
7792 ;; (match_operand:DI 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 ;; For __builtin_setjmp we need to flush register windows iff the function
7802 ;; calls alloca as well, because otherwise the register window might be
7803 ;; saved after %sp adjustement and thus setjmp would crash
7804 (define_expand "builtin_setjmp_setup"
7805 [(match_operand 0 "register_operand" "r")]
7806 ""
7807 {
7808 emit_insn (gen_do_builtin_setjmp_setup ());
7809 DONE;
7810 })
7811
7812 (define_insn "do_builtin_setjmp_setup"
7813 [(unspec_volatile [(const_int 0)] UNSPECV_SETJMP)]
7814 ""
7815 {
7816 if (! current_function_calls_alloca)
7817 return "";
7818 if (! TARGET_V9 || TARGET_FLAT)
7819 return "\tta\t3\n";
7820 fputs ("\tflushw\n", asm_out_file);
7821 if (flag_pic)
7822 fprintf (asm_out_file, "\tst%c\t%%l7, [%%sp+%d]\n",
7823 TARGET_ARCH64 ? 'x' : 'w',
7824 SPARC_STACK_BIAS + 7 * UNITS_PER_WORD);
7825 fprintf (asm_out_file, "\tst%c\t%%fp, [%%sp+%d]\n",
7826 TARGET_ARCH64 ? 'x' : 'w',
7827 SPARC_STACK_BIAS + 14 * UNITS_PER_WORD);
7828 fprintf (asm_out_file, "\tst%c\t%%i7, [%%sp+%d]\n",
7829 TARGET_ARCH64 ? 'x' : 'w',
7830 SPARC_STACK_BIAS + 15 * UNITS_PER_WORD);
7831 return "";
7832 }
7833 [(set_attr "type" "multi")
7834 (set (attr "length")
7835 (cond [(eq_attr "current_function_calls_alloca" "false")
7836 (const_int 0)
7837 (eq_attr "flat" "true")
7838 (const_int 1)
7839 (eq_attr "isa" "!v9")
7840 (const_int 1)
7841 (eq_attr "pic" "true")
7842 (const_int 4)] (const_int 3)))])
7843
7844 ;; Pattern for use after a setjmp to store FP and the return register
7845 ;; into the stack area.
7846
7847 (define_expand "setjmp"
7848 [(const_int 0)]
7849 ""
7850 {
7851 if (TARGET_ARCH64)
7852 emit_insn (gen_setjmp_64 ());
7853 else
7854 emit_insn (gen_setjmp_32 ());
7855 DONE;
7856 })
7857
7858 (define_expand "setjmp_32"
7859 [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
7860 (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
7861 ""
7862 { operands[0] = frame_pointer_rtx; })
7863
7864 (define_expand "setjmp_64"
7865 [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
7866 (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
7867 ""
7868 { operands[0] = frame_pointer_rtx; })
7869
7870 ;; Special pattern for the FLUSH instruction.
7871
7872 ; We do SImode and DImode versions of this to quiet down genrecog's complaints
7873 ; of the define_insn otherwise missing a mode. We make "flush", aka
7874 ; gen_flush, the default one since sparc_initialize_trampoline uses
7875 ; it on SImode mem values.
7876
7877 (define_insn "flush"
7878 [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
7879 ""
7880 { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
7881 [(set_attr "type" "iflush")])
7882
7883 (define_insn "flushdi"
7884 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
7885 ""
7886 { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
7887 [(set_attr "type" "iflush")])
7888
7889 \f
7890 ;; find first set.
7891
7892 ;; The scan instruction searches from the most significant bit while ffs
7893 ;; searches from the least significant bit. The bit index and treatment of
7894 ;; zero also differ. It takes at least 7 instructions to get the proper
7895 ;; result. Here is an obvious 8 instruction sequence.
7896
7897 ;; XXX
7898 (define_insn "ffssi2"
7899 [(set (match_operand:SI 0 "register_operand" "=&r")
7900 (ffs:SI (match_operand:SI 1 "register_operand" "r")))
7901 (clobber (match_scratch:SI 2 "=&r"))]
7902 "TARGET_SPARCLITE || TARGET_SPARCLET"
7903 {
7904 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";
7905 }
7906 [(set_attr "type" "multi")
7907 (set_attr "length" "8")])
7908
7909 ;; ??? This should be a define expand, so that the extra instruction have
7910 ;; a chance of being optimized away.
7911
7912 ;; Disabled because none of the UltraSPARCs implement popc. The HAL R1
7913 ;; does, but no one uses that and we don't have a switch for it.
7914 ;
7915 ;(define_insn "ffsdi2"
7916 ; [(set (match_operand:DI 0 "register_operand" "=&r")
7917 ; (ffs:DI (match_operand:DI 1 "register_operand" "r")))
7918 ; (clobber (match_scratch:DI 2 "=&r"))]
7919 ; "TARGET_ARCH64"
7920 ; "neg\t%1, %2\;xnor\t%1, %2, %2\;popc\t%2, %0\;movzr\t%1, 0, %0"
7921 ; [(set_attr "type" "multi")
7922 ; (set_attr "length" "4")])
7923
7924
7925 \f
7926 ;; Peepholes go at the end.
7927
7928 ;; Optimize consecutive loads or stores into ldd and std when possible.
7929 ;; The conditions in which we do this are very restricted and are
7930 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
7931
7932 (define_peephole2
7933 [(set (match_operand:SI 0 "memory_operand" "")
7934 (const_int 0))
7935 (set (match_operand:SI 1 "memory_operand" "")
7936 (const_int 0))]
7937 "TARGET_V9
7938 && mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
7939 [(set (match_dup 0)
7940 (const_int 0))]
7941 "operands[0] = change_address (operands[0], DImode, NULL);")
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[1], operands[0], NULL_RTX)"
7950 [(set (match_dup 1)
7951 (const_int 0))]
7952 "operands[1] = change_address (operands[1], DImode, NULL);")
7953
7954 (define_peephole2
7955 [(set (match_operand:SI 0 "register_operand" "")
7956 (match_operand:SI 1 "memory_operand" ""))
7957 (set (match_operand:SI 2 "register_operand" "")
7958 (match_operand:SI 3 "memory_operand" ""))]
7959 "registers_ok_for_ldd_peep (operands[0], operands[2])
7960 && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
7961 [(set (match_dup 0)
7962 (match_dup 1))]
7963 "operands[1] = change_address (operands[1], DImode, NULL);
7964 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));")
7965
7966 (define_peephole2
7967 [(set (match_operand:SI 0 "memory_operand" "")
7968 (match_operand:SI 1 "register_operand" ""))
7969 (set (match_operand:SI 2 "memory_operand" "")
7970 (match_operand:SI 3 "register_operand" ""))]
7971 "registers_ok_for_ldd_peep (operands[1], operands[3])
7972 && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
7973 [(set (match_dup 0)
7974 (match_dup 1))]
7975 "operands[0] = change_address (operands[0], DImode, NULL);
7976 operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));")
7977
7978 (define_peephole2
7979 [(set (match_operand:SF 0 "register_operand" "")
7980 (match_operand:SF 1 "memory_operand" ""))
7981 (set (match_operand:SF 2 "register_operand" "")
7982 (match_operand:SF 3 "memory_operand" ""))]
7983 "registers_ok_for_ldd_peep (operands[0], operands[2])
7984 && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
7985 [(set (match_dup 0)
7986 (match_dup 1))]
7987 "operands[1] = change_address (operands[1], DFmode, NULL);
7988 operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));")
7989
7990 (define_peephole2
7991 [(set (match_operand:SF 0 "memory_operand" "")
7992 (match_operand:SF 1 "register_operand" ""))
7993 (set (match_operand:SF 2 "memory_operand" "")
7994 (match_operand:SF 3 "register_operand" ""))]
7995 "registers_ok_for_ldd_peep (operands[1], operands[3])
7996 && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
7997 [(set (match_dup 0)
7998 (match_dup 1))]
7999 "operands[0] = change_address (operands[0], DFmode, NULL);
8000 operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));")
8001
8002 (define_peephole2
8003 [(set (match_operand:SI 0 "register_operand" "")
8004 (match_operand:SI 1 "memory_operand" ""))
8005 (set (match_operand:SI 2 "register_operand" "")
8006 (match_operand:SI 3 "memory_operand" ""))]
8007 "registers_ok_for_ldd_peep (operands[2], operands[0])
8008 && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
8009 [(set (match_dup 2)
8010 (match_dup 3))]
8011 "operands[3] = change_address (operands[3], DImode, NULL);
8012 operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));")
8013
8014 (define_peephole2
8015 [(set (match_operand:SI 0 "memory_operand" "")
8016 (match_operand:SI 1 "register_operand" ""))
8017 (set (match_operand:SI 2 "memory_operand" "")
8018 (match_operand:SI 3 "register_operand" ""))]
8019 "registers_ok_for_ldd_peep (operands[3], operands[1])
8020 && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
8021 [(set (match_dup 2)
8022 (match_dup 3))]
8023 "operands[2] = change_address (operands[2], DImode, NULL);
8024 operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
8025 ")
8026
8027 (define_peephole2
8028 [(set (match_operand:SF 0 "register_operand" "")
8029 (match_operand:SF 1 "memory_operand" ""))
8030 (set (match_operand:SF 2 "register_operand" "")
8031 (match_operand:SF 3 "memory_operand" ""))]
8032 "registers_ok_for_ldd_peep (operands[2], operands[0])
8033 && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
8034 [(set (match_dup 2)
8035 (match_dup 3))]
8036 "operands[3] = change_address (operands[3], DFmode, NULL);
8037 operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));")
8038
8039 (define_peephole2
8040 [(set (match_operand:SF 0 "memory_operand" "")
8041 (match_operand:SF 1 "register_operand" ""))
8042 (set (match_operand:SF 2 "memory_operand" "")
8043 (match_operand:SF 3 "register_operand" ""))]
8044 "registers_ok_for_ldd_peep (operands[3], operands[1])
8045 && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
8046 [(set (match_dup 2)
8047 (match_dup 3))]
8048 "operands[2] = change_address (operands[2], DFmode, NULL);
8049 operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));")
8050
8051 ;; Optimize the case of following a reg-reg move with a test
8052 ;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
8053 ;; This can result from a float to fix conversion.
8054
8055 (define_peephole2
8056 [(set (match_operand:SI 0 "register_operand" "")
8057 (match_operand:SI 1 "register_operand" ""))
8058 (set (reg:CC 100)
8059 (compare:CC (match_operand:SI 2 "register_operand" "")
8060 (const_int 0)))]
8061 "(rtx_equal_p (operands[2], operands[0])
8062 || rtx_equal_p (operands[2], operands[1]))
8063 && ! SPARC_FP_REG_P (REGNO (operands[0]))
8064 && ! SPARC_FP_REG_P (REGNO (operands[1]))"
8065 [(parallel [(set (match_dup 0) (match_dup 1))
8066 (set (reg:CC 100)
8067 (compare:CC (match_dup 1) (const_int 0)))])]
8068 "")
8069
8070 (define_peephole2
8071 [(set (match_operand:DI 0 "register_operand" "")
8072 (match_operand:DI 1 "register_operand" ""))
8073 (set (reg:CCX 100)
8074 (compare:CCX (match_operand:DI 2 "register_operand" "")
8075 (const_int 0)))]
8076 "TARGET_ARCH64
8077 && (rtx_equal_p (operands[2], operands[0])
8078 || rtx_equal_p (operands[2], operands[1]))
8079 && ! SPARC_FP_REG_P (REGNO (operands[0]))
8080 && ! SPARC_FP_REG_P (REGNO (operands[1]))"
8081 [(parallel [(set (match_dup 0) (match_dup 1))
8082 (set (reg:CCX 100)
8083 (compare:CCX (match_dup 1) (const_int 0)))])]
8084 "")
8085
8086 ;; Return peepholes. These are generated by sparc_nonflat_function_epilogue
8087 ;; who then immediately calls final_scan_insn.
8088
8089 (define_insn "*return_qi"
8090 [(set (match_operand:QI 0 "restore_operand" "")
8091 (match_operand:QI 1 "arith_operand" "rI"))
8092 (return)]
8093 "sparc_emitting_epilogue"
8094 {
8095 if (! TARGET_ARCH64 && current_function_returns_struct)
8096 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8097 else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8098 || IN_OR_GLOBAL_P (operands[1])))
8099 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8100 else
8101 return "ret\n\trestore %%g0, %1, %Y0";
8102 }
8103 [(set_attr "type" "multi")
8104 (set_attr "length" "2")])
8105
8106 (define_insn "*return_hi"
8107 [(set (match_operand:HI 0 "restore_operand" "")
8108 (match_operand:HI 1 "arith_operand" "rI"))
8109 (return)]
8110 "sparc_emitting_epilogue"
8111 {
8112 if (! TARGET_ARCH64 && current_function_returns_struct)
8113 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8114 else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8115 || IN_OR_GLOBAL_P (operands[1])))
8116 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8117 else
8118 return "ret\;restore %%g0, %1, %Y0";
8119 }
8120 [(set_attr "type" "multi")
8121 (set_attr "length" "2")])
8122
8123 (define_insn "*return_si"
8124 [(set (match_operand:SI 0 "restore_operand" "")
8125 (match_operand:SI 1 "arith_operand" "rI"))
8126 (return)]
8127 "sparc_emitting_epilogue"
8128 {
8129 if (! TARGET_ARCH64 && current_function_returns_struct)
8130 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8131 else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8132 || IN_OR_GLOBAL_P (operands[1])))
8133 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8134 else
8135 return "ret\;restore %%g0, %1, %Y0";
8136 }
8137 [(set_attr "type" "multi")
8138 (set_attr "length" "2")])
8139
8140 (define_insn "*return_sf_no_fpu"
8141 [(set (match_operand:SF 0 "restore_operand" "=r")
8142 (match_operand:SF 1 "register_operand" "r"))
8143 (return)]
8144 "sparc_emitting_epilogue"
8145 {
8146 if (! TARGET_ARCH64 && current_function_returns_struct)
8147 return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8148 else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
8149 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8150 else
8151 return "ret\;restore %%g0, %1, %Y0";
8152 }
8153 [(set_attr "type" "multi")
8154 (set_attr "length" "2")])
8155
8156 (define_insn "*return_df_no_fpu"
8157 [(set (match_operand:DF 0 "restore_operand" "=r")
8158 (match_operand:DF 1 "register_operand" "r"))
8159 (return)]
8160 "sparc_emitting_epilogue && TARGET_ARCH64"
8161 {
8162 if (IN_OR_GLOBAL_P (operands[1]))
8163 return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8164 else
8165 return "ret\;restore %%g0, %1, %Y0";
8166 }
8167 [(set_attr "type" "multi")
8168 (set_attr "length" "2")])
8169
8170 (define_insn "*return_addsi"
8171 [(set (match_operand:SI 0 "restore_operand" "")
8172 (plus:SI (match_operand:SI 1 "register_operand" "r")
8173 (match_operand:SI 2 "arith_operand" "rI")))
8174 (return)]
8175 "sparc_emitting_epilogue"
8176 {
8177 if (! TARGET_ARCH64 && current_function_returns_struct)
8178 return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
8179 /* If operands are global or in registers, can use return */
8180 else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
8181 && (GET_CODE (operands[2]) == CONST_INT
8182 || IN_OR_GLOBAL_P (operands[2])))
8183 return "return\t%%i7+8\n\tadd\t%Y1, %Y2, %Y0";
8184 else
8185 return "ret\;restore %r1, %2, %Y0";
8186 }
8187 [(set_attr "type" "multi")
8188 (set_attr "length" "2")])
8189
8190 (define_insn "*return_losum_si"
8191 [(set (match_operand:SI 0 "restore_operand" "")
8192 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
8193 (match_operand:SI 2 "immediate_operand" "in")))
8194 (return)]
8195 "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
8196 {
8197 if (! TARGET_ARCH64 && current_function_returns_struct)
8198 return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
8199 /* If operands are global or in registers, can use return */
8200 else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
8201 return "return\t%%i7+8\n\tor\t%Y1, %%lo(%a2), %Y0";
8202 else
8203 return "ret\;restore %r1, %%lo(%a2), %Y0";
8204 }
8205 [(set_attr "type" "multi")
8206 (set_attr "length" "2")])
8207
8208 (define_insn "*return_di"
8209 [(set (match_operand:DI 0 "restore_operand" "")
8210 (match_operand:DI 1 "arith_double_operand" "rHI"))
8211 (return)]
8212 "sparc_emitting_epilogue && TARGET_ARCH64"
8213 "ret\;restore %%g0, %1, %Y0"
8214 [(set_attr "type" "multi")
8215 (set_attr "length" "2")])
8216
8217 (define_insn "*return_adddi"
8218 [(set (match_operand:DI 0 "restore_operand" "")
8219 (plus:DI (match_operand:DI 1 "arith_operand" "%r")
8220 (match_operand:DI 2 "arith_double_operand" "rHI")))
8221 (return)]
8222 "sparc_emitting_epilogue && TARGET_ARCH64"
8223 "ret\;restore %r1, %2, %Y0"
8224 [(set_attr "type" "multi")
8225 (set_attr "length" "2")])
8226
8227 (define_insn "*return_losum_di"
8228 [(set (match_operand:DI 0 "restore_operand" "")
8229 (lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
8230 (match_operand:DI 2 "immediate_operand" "in")))
8231 (return)]
8232 "sparc_emitting_epilogue && TARGET_ARCH64 && ! TARGET_CM_MEDMID"
8233 "ret\;restore %r1, %%lo(%a2), %Y0"
8234 [(set_attr "type" "multi")
8235 (set_attr "length" "2")])
8236
8237 (define_insn "*return_sf"
8238 [(set (reg:SF 32)
8239 (match_operand:SF 0 "register_operand" "f"))
8240 (return)]
8241 "sparc_emitting_epilogue"
8242 "ret\;fmovs\t%0, %%f0"
8243 [(set_attr "type" "multi")
8244 (set_attr "length" "2")])
8245
8246 ;; Now peepholes to do a call followed by a jump.
8247
8248 (define_peephole
8249 [(parallel [(set (match_operand 0 "" "")
8250 (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
8251 (match_operand 2 "" "")))
8252 (clobber (reg:SI 15))])
8253 (set (pc) (label_ref (match_operand 3 "" "")))]
8254 "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
8255 && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
8256 && sparc_cpu != PROCESSOR_ULTRASPARC
8257 && sparc_cpu != PROCESSOR_ULTRASPARC3"
8258 "call\t%a1, %2\n\tadd\t%%o7, (%l3-.-4), %%o7")
8259
8260 (define_peephole
8261 [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
8262 (match_operand 1 "" ""))
8263 (clobber (reg:SI 15))])
8264 (set (pc) (label_ref (match_operand 2 "" "")))]
8265 "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
8266 && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
8267 && sparc_cpu != PROCESSOR_ULTRASPARC
8268 && sparc_cpu != PROCESSOR_ULTRASPARC3"
8269 "call\t%a0, %1\n\tadd\t%%o7, (%l2-.-4), %%o7")
8270
8271 ;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
8272 ;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
8273 ;; ??? operations. With DFA we might be able to model this, but it requires a lot of
8274 ;; ??? state.
8275 (define_expand "prefetch"
8276 [(match_operand 0 "address_operand" "")
8277 (match_operand 1 "const_int_operand" "")
8278 (match_operand 2 "const_int_operand" "")]
8279 "TARGET_V9"
8280 {
8281 if (TARGET_ARCH64)
8282 emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
8283 else
8284 emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
8285 DONE;
8286 })
8287
8288 (define_insn "prefetch_64"
8289 [(prefetch (match_operand:DI 0 "address_operand" "p")
8290 (match_operand:DI 1 "const_int_operand" "n")
8291 (match_operand:DI 2 "const_int_operand" "n"))]
8292 ""
8293 {
8294 static const char * const prefetch_instr[2][2] = {
8295 {
8296 "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
8297 "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
8298 },
8299 {
8300 "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
8301 "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
8302 }
8303 };
8304 int read_or_write = INTVAL (operands[1]);
8305 int locality = INTVAL (operands[2]);
8306
8307 if (read_or_write != 0 && read_or_write != 1)
8308 abort ();
8309 if (locality < 0 || locality > 3)
8310 abort ();
8311 return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
8312 }
8313 [(set_attr "type" "load")])
8314
8315 (define_insn "prefetch_32"
8316 [(prefetch (match_operand:SI 0 "address_operand" "p")
8317 (match_operand:SI 1 "const_int_operand" "n")
8318 (match_operand:SI 2 "const_int_operand" "n"))]
8319 ""
8320 {
8321 static const char * const prefetch_instr[2][2] = {
8322 {
8323 "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
8324 "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
8325 },
8326 {
8327 "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
8328 "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
8329 }
8330 };
8331 int read_or_write = INTVAL (operands[1]);
8332 int locality = INTVAL (operands[2]);
8333
8334 if (read_or_write != 0 && read_or_write != 1)
8335 abort ();
8336 if (locality < 0 || locality > 3)
8337 abort ();
8338 return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
8339 }
8340 [(set_attr "type" "load")])
8341 \f
8342 (define_expand "prologue"
8343 [(const_int 1)]
8344 "flag_pic && current_function_uses_pic_offset_table"
8345 {
8346 load_pic_register ();
8347 DONE;
8348 })
8349
8350 ;; We need to reload %l7 for -mflat -fpic,
8351 ;; otherwise %l7 should be preserved simply
8352 ;; by loading the function's register window
8353 (define_expand "exception_receiver"
8354 [(const_int 0)]
8355 "TARGET_FLAT && flag_pic"
8356 {
8357 load_pic_register ();
8358 DONE;
8359 })
8360
8361 ;; Likewise
8362 (define_expand "builtin_setjmp_receiver"
8363 [(label_ref (match_operand 0 "" ""))]
8364 "TARGET_FLAT && flag_pic"
8365 {
8366 load_pic_register ();
8367 DONE;
8368 })
8369 \f
8370 (define_insn "trap"
8371 [(trap_if (const_int 1) (const_int 5))]
8372 ""
8373 "ta\t5"
8374 [(set_attr "type" "trap")])
8375
8376 (define_expand "conditional_trap"
8377 [(trap_if (match_operator 0 "noov_compare_op"
8378 [(match_dup 2) (match_dup 3)])
8379 (match_operand:SI 1 "arith_operand" ""))]
8380 ""
8381 "operands[2] = gen_compare_reg (GET_CODE (operands[0]),
8382 sparc_compare_op0, sparc_compare_op1);
8383 operands[3] = const0_rtx;")
8384
8385 (define_insn ""
8386 [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
8387 (match_operand:SI 1 "arith_operand" "rM"))]
8388 ""
8389 "t%C0\t%1"
8390 [(set_attr "type" "trap")])
8391
8392 (define_insn ""
8393 [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
8394 (match_operand:SI 1 "arith_operand" "rM"))]
8395 "TARGET_V9"
8396 "t%C0\t%%xcc, %1"
8397 [(set_attr "type" "trap")])