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