]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/powerpcspe/powerpcspe.md
re PR fortran/88269 (ICE in gfc_format_decoder, at fortran/error.c:947)
[thirdparty/gcc.git] / gcc / config / powerpcspe / powerpcspe.md
1 ;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
2 ;; Copyright (C) 1990-2018 Free Software Foundation, Inc.
3 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
4
5 ;; This file is part of GCC.
6
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
11
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 ;; License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23 ;;
24 ;; REGNOS
25 ;;
26
27 (define_constants
28 [(FIRST_GPR_REGNO 0)
29 (STACK_POINTER_REGNUM 1)
30 (TOC_REGNUM 2)
31 (STATIC_CHAIN_REGNUM 11)
32 (HARD_FRAME_POINTER_REGNUM 31)
33 (LAST_GPR_REGNO 31)
34 (FIRST_FPR_REGNO 32)
35 (LAST_FPR_REGNO 63)
36 (LR_REGNO 65)
37 (CTR_REGNO 66)
38 (ARG_POINTER_REGNUM 67)
39 (CR0_REGNO 68)
40 (CR1_REGNO 69)
41 (CR2_REGNO 70)
42 (CR3_REGNO 71)
43 (CR4_REGNO 72)
44 (CR5_REGNO 73)
45 (CR6_REGNO 74)
46 (CR7_REGNO 75)
47 (MAX_CR_REGNO 75)
48 (CA_REGNO 76)
49 (FIRST_ALTIVEC_REGNO 77)
50 (LAST_ALTIVEC_REGNO 108)
51 (VRSAVE_REGNO 109)
52 (VSCR_REGNO 110)
53 (SPE_ACC_REGNO 111)
54 (SPEFSCR_REGNO 112)
55 (FRAME_POINTER_REGNUM 113)
56 (TFHAR_REGNO 114)
57 (TFIAR_REGNO 115)
58 (TEXASR_REGNO 116)
59 (FIRST_SPE_HIGH_REGNO 117)
60 (LAST_SPE_HIGH_REGNO 148)
61 ])
62
63 ;;
64 ;; UNSPEC usage
65 ;;
66
67 (define_c_enum "unspec"
68 [UNSPEC_FRSP ; frsp for POWER machines
69 UNSPEC_PROBE_STACK ; probe stack memory reference
70 UNSPEC_TOCPTR ; address of a word pointing to the TOC
71 UNSPEC_TOC ; address of the TOC (more-or-less)
72 UNSPEC_TOCSLOT ; offset from r1 of toc pointer save slot
73 UNSPEC_MOVSI_GOT
74 UNSPEC_MV_CR_OV ; move_from_CR_ov_bit
75 UNSPEC_FCTIWZ
76 UNSPEC_FRIM
77 UNSPEC_FRIN
78 UNSPEC_FRIP
79 UNSPEC_FRIZ
80 UNSPEC_XSRDPI
81 UNSPEC_LD_MPIC ; load_macho_picbase
82 UNSPEC_RELD_MPIC ; re-load_macho_picbase
83 UNSPEC_MPIC_CORRECT ; macho_correct_pic
84 UNSPEC_TLSGD
85 UNSPEC_TLSLD
86 UNSPEC_MOVESI_FROM_CR
87 UNSPEC_MOVESI_TO_CR
88 UNSPEC_TLSDTPREL
89 UNSPEC_TLSDTPRELHA
90 UNSPEC_TLSDTPRELLO
91 UNSPEC_TLSGOTDTPREL
92 UNSPEC_TLSTPREL
93 UNSPEC_TLSTPRELHA
94 UNSPEC_TLSTPRELLO
95 UNSPEC_TLSGOTTPREL
96 UNSPEC_TLSTLS
97 UNSPEC_FIX_TRUNC_TF ; fadd, rounding towards zero
98 UNSPEC_MV_CR_GT ; move_from_CR_gt_bit
99 UNSPEC_STFIWX
100 UNSPEC_POPCNTB
101 UNSPEC_FRES
102 UNSPEC_SP_SET
103 UNSPEC_SP_TEST
104 UNSPEC_SYNC
105 UNSPEC_LWSYNC
106 UNSPEC_SYNC_OP
107 UNSPEC_ATOMIC
108 UNSPEC_CMPXCHG
109 UNSPEC_XCHG
110 UNSPEC_AND
111 UNSPEC_DLMZB
112 UNSPEC_DLMZB_CR
113 UNSPEC_DLMZB_STRLEN
114 UNSPEC_RSQRT
115 UNSPEC_TOCREL
116 UNSPEC_MACHOPIC_OFFSET
117 UNSPEC_BPERM
118 UNSPEC_COPYSIGN
119 UNSPEC_PARITY
120 UNSPEC_CMPB
121 UNSPEC_FCTIW
122 UNSPEC_FCTID
123 UNSPEC_LFIWAX
124 UNSPEC_LFIWZX
125 UNSPEC_FCTIWUZ
126 UNSPEC_NOP
127 UNSPEC_GRP_END_NOP
128 UNSPEC_P8V_FMRGOW
129 UNSPEC_P8V_MTVSRWZ
130 UNSPEC_P8V_RELOAD_FROM_GPR
131 UNSPEC_P8V_MTVSRD
132 UNSPEC_P8V_XXPERMDI
133 UNSPEC_P8V_RELOAD_FROM_VSX
134 UNSPEC_ADDG6S
135 UNSPEC_CDTBCD
136 UNSPEC_CBCDTD
137 UNSPEC_DIVE
138 UNSPEC_DIVEO
139 UNSPEC_DIVEU
140 UNSPEC_DIVEUO
141 UNSPEC_UNPACK_128BIT
142 UNSPEC_PACK_128BIT
143 UNSPEC_LSQ
144 UNSPEC_FUSION_GPR
145 UNSPEC_STACK_CHECK
146 UNSPEC_FUSION_P9
147 UNSPEC_FUSION_ADDIS
148 UNSPEC_ROUND_TO_ODD
149 UNSPEC_SIGNBIT
150 UNSPEC_SF_FROM_SI
151 UNSPEC_SI_FROM_SF
152 ])
153
154 ;;
155 ;; UNSPEC_VOLATILE usage
156 ;;
157
158 (define_c_enum "unspecv"
159 [UNSPECV_BLOCK
160 UNSPECV_LL ; load-locked
161 UNSPECV_SC ; store-conditional
162 UNSPECV_PROBE_STACK_RANGE ; probe range of stack addresses
163 UNSPECV_EH_RR ; eh_reg_restore
164 UNSPECV_ISYNC ; isync instruction
165 UNSPECV_MFTB ; move from time base
166 UNSPECV_NLGR ; non-local goto receiver
167 UNSPECV_MFFS ; Move from FPSCR
168 UNSPECV_MTFSF ; Move to FPSCR Fields
169 UNSPECV_SPLIT_STACK_RETURN ; A camouflaged return
170 ])
171
172 \f
173 ;; Define an insn type attribute. This is used in function unit delay
174 ;; computations.
175 (define_attr "type"
176 "integer,two,three,
177 add,logical,shift,insert,
178 mul,halfmul,div,
179 exts,cntlz,popcnt,isel,
180 load,store,fpload,fpstore,vecload,vecstore,
181 cmp,
182 branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c,
183 cr_logical,delayed_cr,mfcr,mfcrf,mtcr,
184 fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,
185 brinc,
186 vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
187 vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto,
188 veclogical,veccmpfx,vecexts,vecmove,
189 htm,htmsimple,dfp"
190 (const_string "integer"))
191
192 ;; What data size does this instruction work on?
193 ;; This is used for insert, mul and others as necessary.
194 (define_attr "size" "8,16,32,64,128" (const_string "32"))
195
196 ;; Is this instruction record form ("dot", signed compare to 0, writing CR0)?
197 ;; This is used for add, logical, shift, exts, mul.
198 (define_attr "dot" "no,yes" (const_string "no"))
199
200 ;; Does this instruction sign-extend its result?
201 ;; This is used for load insns.
202 (define_attr "sign_extend" "no,yes" (const_string "no"))
203
204 ;; Does this instruction use indexed (that is, reg+reg) addressing?
205 ;; This is used for load and store insns. If operand 0 or 1 is a MEM
206 ;; it is automatically set based on that. If a load or store instruction
207 ;; has fewer than two operands it needs to set this attribute manually
208 ;; or the compiler will crash.
209 (define_attr "indexed" "no,yes"
210 (if_then_else (ior (match_operand 0 "indexed_address_mem")
211 (match_operand 1 "indexed_address_mem"))
212 (const_string "yes")
213 (const_string "no")))
214
215 ;; Does this instruction use update addressing?
216 ;; This is used for load and store insns. See the comments for "indexed".
217 (define_attr "update" "no,yes"
218 (if_then_else (ior (match_operand 0 "update_address_mem")
219 (match_operand 1 "update_address_mem"))
220 (const_string "yes")
221 (const_string "no")))
222
223 ;; Is this instruction using operands[2] as shift amount, and can that be a
224 ;; register?
225 ;; This is used for shift insns.
226 (define_attr "maybe_var_shift" "no,yes" (const_string "no"))
227
228 ;; Is this instruction using a shift amount from a register?
229 ;; This is used for shift insns.
230 (define_attr "var_shift" "no,yes"
231 (if_then_else (and (eq_attr "type" "shift")
232 (eq_attr "maybe_var_shift" "yes"))
233 (if_then_else (match_operand 2 "gpc_reg_operand")
234 (const_string "yes")
235 (const_string "no"))
236 (const_string "no")))
237
238 ;; Is copying of this instruction disallowed?
239 (define_attr "cannot_copy" "no,yes" (const_string "no"))
240
241 ;; Define floating point instruction sub-types for use with Xfpu.md
242 (define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default"))
243
244 ;; Length (in bytes).
245 ; '(pc)' in the following doesn't include the instruction itself; it is
246 ; calculated as if the instruction had zero size.
247 (define_attr "length" ""
248 (if_then_else (eq_attr "type" "branch")
249 (if_then_else (and (ge (minus (match_dup 0) (pc))
250 (const_int -32768))
251 (lt (minus (match_dup 0) (pc))
252 (const_int 32764)))
253 (const_int 4)
254 (const_int 8))
255 (const_int 4)))
256
257 ;; Processor type -- this attribute must exactly match the processor_type
258 ;; enumeration in rs6000-opts.h.
259 (define_attr "cpu"
260 "ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,
261 ppc750,ppc7400,ppc7450,
262 ppc403,ppc405,ppc440,ppc476,
263 ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,
264 power4,power5,power6,power7,power8,power9,
265 rs64a,mpccore,cell,ppca2,titan"
266 (const (symbol_ref "rs6000_cpu_attr")))
267
268
269 ;; If this instruction is microcoded on the CELL processor
270 ; The default for load extended, the recorded instructions and rotate/shifts by a variable is always microcoded
271 (define_attr "cell_micro" "not,conditional,always"
272 (if_then_else (ior (and (eq_attr "type" "shift,exts,mul")
273 (eq_attr "dot" "yes"))
274 (and (eq_attr "type" "load")
275 (eq_attr "sign_extend" "yes"))
276 (and (eq_attr "type" "shift")
277 (eq_attr "var_shift" "yes")))
278 (const_string "always")
279 (const_string "not")))
280
281 (automata_option "ndfa")
282
283 (include "rs64.md")
284 (include "mpc.md")
285 (include "40x.md")
286 (include "440.md")
287 (include "476.md")
288 (include "601.md")
289 (include "603.md")
290 (include "6xx.md")
291 (include "7xx.md")
292 (include "7450.md")
293 (include "8540.md")
294 (include "e300c2c3.md")
295 (include "e500mc.md")
296 (include "e500mc64.md")
297 (include "e5500.md")
298 (include "e6500.md")
299 (include "power4.md")
300 (include "power5.md")
301 (include "power6.md")
302 (include "power7.md")
303 (include "power8.md")
304 (include "power9.md")
305 (include "cell.md")
306 (include "xfpu.md")
307 (include "a2.md")
308 (include "titan.md")
309
310 (include "predicates.md")
311 (include "constraints.md")
312
313 (include "darwin.md")
314
315 \f
316 ;; Mode iterators
317
318 ; This mode iterator allows :GPR to be used to indicate the allowable size
319 ; of whole values in GPRs.
320 (define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")])
321
322 ; Any supported integer mode.
323 (define_mode_iterator INT [QI HI SI DI TI PTI])
324
325 ; Any supported integer mode that fits in one register.
326 (define_mode_iterator INT1 [QI HI SI (DI "TARGET_POWERPC64")])
327
328 ; Integer modes supported in VSX registers with ISA 3.0 instructions
329 (define_mode_iterator INT_ISA3 [QI HI SI DI])
330
331 ; Everything we can extend QImode to.
332 (define_mode_iterator EXTQI [SI (DI "TARGET_POWERPC64")])
333
334 ; Everything we can extend HImode to.
335 (define_mode_iterator EXTHI [SI (DI "TARGET_POWERPC64")])
336
337 ; Everything we can extend SImode to.
338 (define_mode_iterator EXTSI [(DI "TARGET_POWERPC64")])
339
340 ; QImode or HImode for small integer moves and small atomic ops
341 (define_mode_iterator QHI [QI HI])
342
343 ; QImode, HImode, SImode for fused ops only for GPR loads
344 (define_mode_iterator QHSI [QI HI SI])
345
346 ; HImode or SImode for sign extended fusion ops
347 (define_mode_iterator HSI [HI SI])
348
349 ; SImode or DImode, even if DImode doesn't fit in GPRs.
350 (define_mode_iterator SDI [SI DI])
351
352 ; Types that can be fused with an ADDIS instruction to load or store a GPR
353 ; register that has reg+offset addressing.
354 (define_mode_iterator GPR_FUSION [QI
355 HI
356 SI
357 (DI "TARGET_POWERPC64")
358 SF
359 (DF "TARGET_POWERPC64")])
360
361 ; Types that can be fused with an ADDIS instruction to load or store a FPR
362 ; register that has reg+offset addressing.
363 (define_mode_iterator FPR_FUSION [DI SF DF])
364
365 ; The size of a pointer. Also, the size of the value that a record-condition
366 ; (one with a '.') will compare; and the size used for arithmetic carries.
367 (define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
368
369 ; Iterator to add PTImode along with TImode (TImode can go in VSX registers,
370 ; PTImode is GPR only)
371 (define_mode_iterator TI2 [TI PTI])
372
373 ; Any hardware-supported floating-point mode
374 (define_mode_iterator FP [
375 (SF "TARGET_HARD_FLOAT
376 && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_E500_SINGLE)")
377 (DF "TARGET_HARD_FLOAT
378 && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)")
379 (TF "TARGET_HARD_FLOAT
380 && (TARGET_FPRS || TARGET_E500_DOUBLE)
381 && TARGET_LONG_DOUBLE_128")
382 (IF "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128")
383 (KF "TARGET_FLOAT128_TYPE")
384 (DD "TARGET_DFP")
385 (TD "TARGET_DFP")])
386
387 ; Any fma capable floating-point mode.
388 (define_mode_iterator FMA_F [
389 (SF "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT")
390 (DF "(TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
391 || VECTOR_UNIT_VSX_P (DFmode)")
392 (V2SF "TARGET_PAIRED_FLOAT")
393 (V4SF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)")
394 (V2DF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)")
395 (KF "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (KFmode)")
396 (TF "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (TFmode)")
397 ])
398
399 ; Floating point move iterators to combine binary and decimal moves
400 (define_mode_iterator FMOVE32 [SF SD])
401 (define_mode_iterator FMOVE64 [DF DD])
402 (define_mode_iterator FMOVE64X [DI DF DD])
403 (define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128")
404 (IF "FLOAT128_IBM_P (IFmode)")
405 (TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
406
407 (define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)")
408 (IF "FLOAT128_2REG_P (IFmode)")
409 (TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
410
411 ; Iterators for 128 bit types for direct move
412 (define_mode_iterator FMOVE128_GPR [(TI "TARGET_VSX_TIMODE")
413 (V16QI "")
414 (V8HI "")
415 (V4SI "")
416 (V4SF "")
417 (V2DI "")
418 (V2DF "")
419 (V1TI "")
420 (KF "FLOAT128_VECTOR_P (KFmode)")
421 (TF "FLOAT128_VECTOR_P (TFmode)")])
422
423 ; Iterator for 128-bit VSX types for pack/unpack
424 (define_mode_iterator FMOVE128_VSX [V1TI KF])
425
426 ; Whether a floating point move is ok, don't allow SD without hardware FP
427 (define_mode_attr fmove_ok [(SF "")
428 (DF "")
429 (SD "TARGET_HARD_FLOAT && TARGET_FPRS")
430 (DD "")])
431
432 ; Convert REAL_VALUE to the appropriate bits
433 (define_mode_attr real_value_to_target [(SF "REAL_VALUE_TO_TARGET_SINGLE")
434 (DF "REAL_VALUE_TO_TARGET_DOUBLE")
435 (SD "REAL_VALUE_TO_TARGET_DECIMAL32")
436 (DD "REAL_VALUE_TO_TARGET_DECIMAL64")])
437
438 ; Whether 0.0 has an all-zero bit pattern
439 (define_mode_attr zero_fp [(SF "j")
440 (DF "j")
441 (TF "j")
442 (IF "j")
443 (KF "j")
444 (SD "wn")
445 (DD "wn")
446 (TD "wn")])
447
448 ; Definitions for 64-bit VSX
449 (define_mode_attr f64_vsx [(DF "ws") (DD "wn")])
450
451 ; Definitions for 64-bit direct move
452 (define_mode_attr f64_dm [(DF "wk") (DD "wh")])
453
454 ; Definitions for 64-bit use of altivec registers
455 (define_mode_attr f64_av [(DF "wv") (DD "wn")])
456
457 ; Definitions for 64-bit access to ISA 3.0 (power9) vector
458 (define_mode_attr f64_p9 [(DF "wb") (DD "wn")])
459
460 ; These modes do not fit in integer registers in 32-bit mode.
461 ; but on e500v2, the gpr are 64 bit registers
462 (define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD])
463
464 ; Iterator for reciprocal estimate instructions
465 (define_mode_iterator RECIPF [SF DF V4SF V2DF])
466
467 ; Iterator for just SF/DF
468 (define_mode_iterator SFDF [SF DF])
469
470 ; Like SFDF, but a different name to match conditional move where the
471 ; comparison operands may be a different mode than the input operands.
472 (define_mode_iterator SFDF2 [SF DF])
473
474 ; Iterator for 128-bit floating point that uses the IBM double-double format
475 (define_mode_iterator IBM128 [(IF "FLOAT128_IBM_P (IFmode)")
476 (TF "FLOAT128_IBM_P (TFmode)")])
477
478 ; Iterator for 128-bit floating point that uses IEEE 128-bit float
479 (define_mode_iterator IEEE128 [(KF "FLOAT128_IEEE_P (KFmode)")
480 (TF "FLOAT128_IEEE_P (TFmode)")])
481
482 ; Iterator for 128-bit floating point
483 (define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128_TYPE")
484 (IF "TARGET_FLOAT128_TYPE")
485 (TF "TARGET_LONG_DOUBLE_128")])
486
487 ; Iterator for signbit on 64-bit machines with direct move
488 (define_mode_iterator SIGNBIT [(KF "FLOAT128_VECTOR_P (KFmode)")
489 (TF "FLOAT128_VECTOR_P (TFmode)")])
490
491 ; Iterator for ISA 3.0 supported floating point types
492 (define_mode_iterator FP_ISA3 [SF DF])
493
494 ; SF/DF suffix for traditional floating instructions
495 (define_mode_attr Ftrad [(SF "s") (DF "")])
496
497 ; SF/DF suffix for VSX instructions
498 (define_mode_attr Fvsx [(SF "sp") (DF "dp")])
499
500 ; SF/DF constraint for arithmetic on traditional floating point registers
501 (define_mode_attr Ff [(SF "f") (DF "d") (DI "d")])
502
503 ; SF/DF constraint for arithmetic on VSX registers using instructions added in
504 ; ISA 2.06 (power7). This includes instructions that normally target DF mode,
505 ; but are used on SFmode, since internally SFmode values are kept in the DFmode
506 ; format.
507 (define_mode_attr Fv [(SF "ww") (DF "ws") (DI "wi")])
508
509 ; SF/DF constraint for arithmetic on VSX registers. This is intended to be
510 ; used for DFmode instructions added in ISA 2.06 (power7) and SFmode
511 ; instructions added in ISA 2.07 (power8)
512 (define_mode_attr Fv2 [(SF "wy") (DF "ws") (DI "wi")])
513
514 ; SF/DF constraint for arithmetic on altivec registers
515 (define_mode_attr Fa [(SF "wu") (DF "wv")])
516
517 ; s/d suffix for things like fp_addsub_s/fp_addsub_d
518 (define_mode_attr Fs [(SF "s") (DF "d")])
519
520 ; FRE/FRES support
521 (define_mode_attr Ffre [(SF "fres") (DF "fre")])
522 (define_mode_attr FFRE [(SF "FRES") (DF "FRE")])
523
524 ; Conditional returns.
525 (define_code_iterator any_return [return simple_return])
526 (define_code_attr return_pred [(return "direct_return ()")
527 (simple_return "1")])
528 (define_code_attr return_str [(return "") (simple_return "simple_")])
529
530 ; Logical operators.
531 (define_code_iterator iorxor [ior xor])
532 (define_code_iterator and_ior_xor [and ior xor])
533
534 ; Signed/unsigned variants of ops.
535 (define_code_iterator any_extend [sign_extend zero_extend])
536 (define_code_iterator any_fix [fix unsigned_fix])
537 (define_code_iterator any_float [float unsigned_float])
538
539 (define_code_attr u [(sign_extend "")
540 (zero_extend "u")
541 (fix "")
542 (unsigned_fix "u")])
543
544 (define_code_attr su [(sign_extend "s")
545 (zero_extend "u")
546 (fix "s")
547 (unsigned_fix "s")
548 (float "s")
549 (unsigned_float "u")])
550
551 (define_code_attr az [(sign_extend "a")
552 (zero_extend "z")
553 (fix "a")
554 (unsigned_fix "z")
555 (float "a")
556 (unsigned_float "z")])
557
558 (define_code_attr uns [(fix "")
559 (unsigned_fix "uns")
560 (float "")
561 (unsigned_float "uns")])
562
563 ; Various instructions that come in SI and DI forms.
564 ; A generic w/d attribute, for things like cmpw/cmpd.
565 (define_mode_attr wd [(QI "b")
566 (HI "h")
567 (SI "w")
568 (DI "d")
569 (V16QI "b")
570 (V8HI "h")
571 (V4SI "w")
572 (V2DI "d")
573 (V1TI "q")
574 (TI "q")])
575
576 ;; How many bits in this mode?
577 (define_mode_attr bits [(QI "8") (HI "16") (SI "32") (DI "64")])
578
579 ; DImode bits
580 (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
581
582 ;; ISEL/ISEL64 target selection
583 (define_mode_attr sel [(SI "") (DI "64")])
584
585 ;; Bitmask for shift instructions
586 (define_mode_attr hH [(SI "h") (DI "H")])
587
588 ;; A mode twice the size of the given mode
589 (define_mode_attr dmode [(SI "di") (DI "ti")])
590 (define_mode_attr DMODE [(SI "DI") (DI "TI")])
591
592 ;; Suffix for reload patterns
593 (define_mode_attr ptrsize [(SI "32bit")
594 (DI "64bit")])
595
596 (define_mode_attr tptrsize [(SI "TARGET_32BIT")
597 (DI "TARGET_64BIT")])
598
599 (define_mode_attr mptrsize [(SI "si")
600 (DI "di")])
601
602 (define_mode_attr ptrload [(SI "lwz")
603 (DI "ld")])
604
605 (define_mode_attr ptrm [(SI "m")
606 (DI "Y")])
607
608 (define_mode_attr rreg [(SF "f")
609 (DF "ws")
610 (TF "f")
611 (TD "f")
612 (V4SF "wf")
613 (V2DF "wd")])
614
615 (define_mode_attr rreg2 [(SF "f")
616 (DF "d")])
617
618 (define_mode_attr SI_CONVERT_FP [(SF "TARGET_FCFIDS")
619 (DF "TARGET_FCFID")])
620
621 (define_mode_attr E500_CONVERT [(SF "!TARGET_FPRS")
622 (DF "TARGET_E500_DOUBLE")])
623
624 (define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
625 (DF "TARGET_DOUBLE_FLOAT")])
626
627 ;; Mode iterator for logical operations on 128-bit types
628 (define_mode_iterator BOOL_128 [TI
629 PTI
630 (V16QI "TARGET_ALTIVEC")
631 (V8HI "TARGET_ALTIVEC")
632 (V4SI "TARGET_ALTIVEC")
633 (V4SF "TARGET_ALTIVEC")
634 (V2DI "TARGET_ALTIVEC")
635 (V2DF "TARGET_ALTIVEC")
636 (V1TI "TARGET_ALTIVEC")])
637
638 ;; For the GPRs we use 3 constraints for register outputs, two that are the
639 ;; same as the output register, and a third where the output register is an
640 ;; early clobber, so we don't have to deal with register overlaps. For the
641 ;; vector types, we prefer to use the vector registers. For TI mode, allow
642 ;; either.
643
644 ;; Mode attribute for boolean operation register constraints for output
645 (define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wt,v")
646 (PTI "&r,r,r")
647 (V16QI "wa,v,&?r,?r,?r")
648 (V8HI "wa,v,&?r,?r,?r")
649 (V4SI "wa,v,&?r,?r,?r")
650 (V4SF "wa,v,&?r,?r,?r")
651 (V2DI "wa,v,&?r,?r,?r")
652 (V2DF "wa,v,&?r,?r,?r")
653 (V1TI "wa,v,&?r,?r,?r")])
654
655 ;; Mode attribute for boolean operation register constraints for operand1
656 (define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wt,v")
657 (PTI "r,0,r")
658 (V16QI "wa,v,r,0,r")
659 (V8HI "wa,v,r,0,r")
660 (V4SI "wa,v,r,0,r")
661 (V4SF "wa,v,r,0,r")
662 (V2DI "wa,v,r,0,r")
663 (V2DF "wa,v,r,0,r")
664 (V1TI "wa,v,r,0,r")])
665
666 ;; Mode attribute for boolean operation register constraints for operand2
667 (define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wt,v")
668 (PTI "r,r,0")
669 (V16QI "wa,v,r,r,0")
670 (V8HI "wa,v,r,r,0")
671 (V4SI "wa,v,r,r,0")
672 (V4SF "wa,v,r,r,0")
673 (V2DI "wa,v,r,r,0")
674 (V2DF "wa,v,r,r,0")
675 (V1TI "wa,v,r,r,0")])
676
677 ;; Mode attribute for boolean operation register constraints for operand1
678 ;; for one_cmpl. To simplify things, we repeat the constraint where 0
679 ;; is used for operand1 or operand2
680 (define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wt,v")
681 (PTI "r,0,0")
682 (V16QI "wa,v,r,0,0")
683 (V8HI "wa,v,r,0,0")
684 (V4SI "wa,v,r,0,0")
685 (V4SF "wa,v,r,0,0")
686 (V2DI "wa,v,r,0,0")
687 (V2DF "wa,v,r,0,0")
688 (V1TI "wa,v,r,0,0")])
689
690 ;; Reload iterator for creating the function to allocate a base register to
691 ;; supplement addressing modes.
692 (define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
693 SF SD SI DF DD DI TI PTI KF IF TF])
694
695 ;; Iterate over smin, smax
696 (define_code_iterator fp_minmax [smin smax])
697
698 (define_code_attr minmax [(smin "min")
699 (smax "max")])
700
701 (define_code_attr SMINMAX [(smin "SMIN")
702 (smax "SMAX")])
703
704 ;; Iterator to optimize the following cases:
705 ;; D-form load to FPR register & move to Altivec register
706 ;; Move Altivec register to FPR register and store
707 (define_mode_iterator ALTIVEC_DFORM [DI DF SF])
708
709 \f
710 ;; Start with fixed-point load and store insns. Here we put only the more
711 ;; complex forms. Basic data transfer is done later.
712
713 (define_insn "zero_extendqi<mode>2"
714 [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r,^wJwK,^wK")
715 (zero_extend:EXTQI (match_operand:QI 1 "reg_or_mem_operand" "m,r,Z,wK")))]
716 ""
717 "@
718 lbz%U1%X1 %0,%1
719 rlwinm %0,%1,0,0xff
720 lxsibzx %x0,%y1
721 vextractub %0,%1,7"
722 [(set_attr "type" "load,shift,fpload,vecperm")])
723
724 (define_insn_and_split "*zero_extendqi<mode>2_dot"
725 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
726 (compare:CC (zero_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
727 (const_int 0)))
728 (clobber (match_scratch:EXTQI 0 "=r,r"))]
729 "rs6000_gen_cell_microcode"
730 "@
731 andi. %0,%1,0xff
732 #"
733 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
734 [(set (match_dup 0)
735 (zero_extend:EXTQI (match_dup 1)))
736 (set (match_dup 2)
737 (compare:CC (match_dup 0)
738 (const_int 0)))]
739 ""
740 [(set_attr "type" "logical")
741 (set_attr "dot" "yes")
742 (set_attr "length" "4,8")])
743
744 (define_insn_and_split "*zero_extendqi<mode>2_dot2"
745 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
746 (compare:CC (zero_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
747 (const_int 0)))
748 (set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
749 (zero_extend:EXTQI (match_dup 1)))]
750 "rs6000_gen_cell_microcode"
751 "@
752 andi. %0,%1,0xff
753 #"
754 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
755 [(set (match_dup 0)
756 (zero_extend:EXTQI (match_dup 1)))
757 (set (match_dup 2)
758 (compare:CC (match_dup 0)
759 (const_int 0)))]
760 ""
761 [(set_attr "type" "logical")
762 (set_attr "dot" "yes")
763 (set_attr "length" "4,8")])
764
765
766 (define_insn "zero_extendhi<mode>2"
767 [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r,^wJwK,^wK")
768 (zero_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r,Z,wK")))]
769 ""
770 "@
771 lhz%U1%X1 %0,%1
772 rlwinm %0,%1,0,0xffff
773 lxsihzx %x0,%y1
774 vextractuh %0,%1,6"
775 [(set_attr "type" "load,shift,fpload,vecperm")])
776
777 (define_insn_and_split "*zero_extendhi<mode>2_dot"
778 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
779 (compare:CC (zero_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
780 (const_int 0)))
781 (clobber (match_scratch:EXTHI 0 "=r,r"))]
782 "rs6000_gen_cell_microcode"
783 "@
784 andi. %0,%1,0xffff
785 #"
786 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
787 [(set (match_dup 0)
788 (zero_extend:EXTHI (match_dup 1)))
789 (set (match_dup 2)
790 (compare:CC (match_dup 0)
791 (const_int 0)))]
792 ""
793 [(set_attr "type" "logical")
794 (set_attr "dot" "yes")
795 (set_attr "length" "4,8")])
796
797 (define_insn_and_split "*zero_extendhi<mode>2_dot2"
798 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
799 (compare:CC (zero_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
800 (const_int 0)))
801 (set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
802 (zero_extend:EXTHI (match_dup 1)))]
803 "rs6000_gen_cell_microcode"
804 "@
805 andi. %0,%1,0xffff
806 #"
807 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
808 [(set (match_dup 0)
809 (zero_extend:EXTHI (match_dup 1)))
810 (set (match_dup 2)
811 (compare:CC (match_dup 0)
812 (const_int 0)))]
813 ""
814 [(set_attr "type" "logical")
815 (set_attr "dot" "yes")
816 (set_attr "length" "4,8")])
817
818
819 (define_insn "zero_extendsi<mode>2"
820 [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wz,wu,wj,r,wJwK")
821 (zero_extend:EXTSI (match_operand:SI 1 "reg_or_mem_operand" "m,r,Z,Z,r,wIwH,wJwK")))]
822 ""
823 "@
824 lwz%U1%X1 %0,%1
825 rldicl %0,%1,0,32
826 lfiwzx %0,%y1
827 lxsiwzx %x0,%y1
828 mtvsrwz %x0,%1
829 mfvsrwz %0,%x1
830 xxextractuw %x0,%x1,4"
831 [(set_attr "type" "load,shift,fpload,fpload,mffgpr,mftgpr,vecexts")])
832
833 (define_insn_and_split "*zero_extendsi<mode>2_dot"
834 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
835 (compare:CC (zero_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
836 (const_int 0)))
837 (clobber (match_scratch:EXTSI 0 "=r,r"))]
838 "rs6000_gen_cell_microcode"
839 "@
840 rldicl. %0,%1,0,32
841 #"
842 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
843 [(set (match_dup 0)
844 (zero_extend:DI (match_dup 1)))
845 (set (match_dup 2)
846 (compare:CC (match_dup 0)
847 (const_int 0)))]
848 ""
849 [(set_attr "type" "shift")
850 (set_attr "dot" "yes")
851 (set_attr "length" "4,8")])
852
853 (define_insn_and_split "*zero_extendsi<mode>2_dot2"
854 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
855 (compare:CC (zero_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
856 (const_int 0)))
857 (set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r")
858 (zero_extend:EXTSI (match_dup 1)))]
859 "rs6000_gen_cell_microcode"
860 "@
861 rldicl. %0,%1,0,32
862 #"
863 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
864 [(set (match_dup 0)
865 (zero_extend:EXTSI (match_dup 1)))
866 (set (match_dup 2)
867 (compare:CC (match_dup 0)
868 (const_int 0)))]
869 ""
870 [(set_attr "type" "shift")
871 (set_attr "dot" "yes")
872 (set_attr "length" "4,8")])
873
874
875 (define_insn "extendqi<mode>2"
876 [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,?*wK")
877 (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,?*wK")))]
878 ""
879 "@
880 extsb %0,%1
881 vextsb2d %0,%1"
882 [(set_attr "type" "exts,vecperm")])
883
884 (define_insn_and_split "*extendqi<mode>2_dot"
885 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
886 (compare:CC (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
887 (const_int 0)))
888 (clobber (match_scratch:EXTQI 0 "=r,r"))]
889 "rs6000_gen_cell_microcode"
890 "@
891 extsb. %0,%1
892 #"
893 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
894 [(set (match_dup 0)
895 (sign_extend:EXTQI (match_dup 1)))
896 (set (match_dup 2)
897 (compare:CC (match_dup 0)
898 (const_int 0)))]
899 ""
900 [(set_attr "type" "exts")
901 (set_attr "dot" "yes")
902 (set_attr "length" "4,8")])
903
904 (define_insn_and_split "*extendqi<mode>2_dot2"
905 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
906 (compare:CC (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
907 (const_int 0)))
908 (set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
909 (sign_extend:EXTQI (match_dup 1)))]
910 "rs6000_gen_cell_microcode"
911 "@
912 extsb. %0,%1
913 #"
914 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
915 [(set (match_dup 0)
916 (sign_extend:EXTQI (match_dup 1)))
917 (set (match_dup 2)
918 (compare:CC (match_dup 0)
919 (const_int 0)))]
920 ""
921 [(set_attr "type" "exts")
922 (set_attr "dot" "yes")
923 (set_attr "length" "4,8")])
924
925
926 (define_expand "extendhi<mode>2"
927 [(set (match_operand:EXTHI 0 "gpc_reg_operand")
928 (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand")))]
929 ""
930 "")
931
932 (define_insn "*extendhi<mode>2"
933 [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r,?*wK,?*wK")
934 (sign_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r,Z,wK")))]
935 "rs6000_gen_cell_microcode || TARGET_VSX_SMALL_INTEGER"
936 "@
937 lha%U1%X1 %0,%1
938 extsh %0,%1
939 #
940 vextsh2d %0,%1"
941 [(set_attr "type" "load,exts,fpload,vecperm")
942 (set_attr "sign_extend" "yes")
943 (set_attr "length" "4,4,8,4")])
944
945 (define_split
946 [(set (match_operand:EXTHI 0 "altivec_register_operand")
947 (sign_extend:EXTHI
948 (match_operand:HI 1 "indexed_or_indirect_operand")))]
949 "TARGET_P9_VECTOR && reload_completed"
950 [(set (match_dup 2)
951 (match_dup 1))
952 (set (match_dup 0)
953 (sign_extend:EXTHI (match_dup 2)))]
954 {
955 operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
956 })
957
958 (define_insn "*extendhi<mode>2_noload"
959 [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r")
960 (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r")))]
961 "!rs6000_gen_cell_microcode"
962 "extsh %0,%1"
963 [(set_attr "type" "exts")])
964
965 (define_insn_and_split "*extendhi<mode>2_dot"
966 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
967 (compare:CC (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
968 (const_int 0)))
969 (clobber (match_scratch:EXTHI 0 "=r,r"))]
970 "rs6000_gen_cell_microcode"
971 "@
972 extsh. %0,%1
973 #"
974 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
975 [(set (match_dup 0)
976 (sign_extend:EXTHI (match_dup 1)))
977 (set (match_dup 2)
978 (compare:CC (match_dup 0)
979 (const_int 0)))]
980 ""
981 [(set_attr "type" "exts")
982 (set_attr "dot" "yes")
983 (set_attr "length" "4,8")])
984
985 (define_insn_and_split "*extendhi<mode>2_dot2"
986 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
987 (compare:CC (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
988 (const_int 0)))
989 (set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
990 (sign_extend:EXTHI (match_dup 1)))]
991 "rs6000_gen_cell_microcode"
992 "@
993 extsh. %0,%1
994 #"
995 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
996 [(set (match_dup 0)
997 (sign_extend:EXTHI (match_dup 1)))
998 (set (match_dup 2)
999 (compare:CC (match_dup 0)
1000 (const_int 0)))]
1001 ""
1002 [(set_attr "type" "exts")
1003 (set_attr "dot" "yes")
1004 (set_attr "length" "4,8")])
1005
1006
1007 (define_insn "extendsi<mode>2"
1008 [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wl,wu,wj,wK,wH")
1009 (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,Z,Z,r,wK,wH")))]
1010 ""
1011 "@
1012 lwa%U1%X1 %0,%1
1013 extsw %0,%1
1014 lfiwax %0,%y1
1015 lxsiwax %x0,%y1
1016 mtvsrwa %x0,%1
1017 vextsw2d %0,%1
1018 #"
1019 [(set_attr "type" "load,exts,fpload,fpload,mffgpr,vecexts,vecperm")
1020 (set_attr "sign_extend" "yes")
1021 (set_attr "length" "4,4,4,4,4,4,8")])
1022
1023 (define_split
1024 [(set (match_operand:DI 0 "altivec_register_operand")
1025 (sign_extend:DI (match_operand:SI 1 "altivec_register_operand")))]
1026 "TARGET_VSX_SMALL_INTEGER && TARGET_P8_VECTOR && !TARGET_P9_VECTOR
1027 && reload_completed"
1028 [(const_int 0)]
1029 {
1030 rtx dest = operands[0];
1031 rtx src = operands[1];
1032 int dest_regno = REGNO (dest);
1033 int src_regno = REGNO (src);
1034 rtx dest_v2di = gen_rtx_REG (V2DImode, dest_regno);
1035 rtx src_v4si = gen_rtx_REG (V4SImode, src_regno);
1036
1037 if (VECTOR_ELT_ORDER_BIG)
1038 {
1039 emit_insn (gen_altivec_vupkhsw (dest_v2di, src_v4si));
1040 emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const1_rtx));
1041 }
1042 else
1043 {
1044 emit_insn (gen_altivec_vupklsw (dest_v2di, src_v4si));
1045 emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const0_rtx));
1046 }
1047 DONE;
1048 })
1049
1050 (define_insn_and_split "*extendsi<mode>2_dot"
1051 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
1052 (compare:CC (sign_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
1053 (const_int 0)))
1054 (clobber (match_scratch:EXTSI 0 "=r,r"))]
1055 "rs6000_gen_cell_microcode"
1056 "@
1057 extsw. %0,%1
1058 #"
1059 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
1060 [(set (match_dup 0)
1061 (sign_extend:EXTSI (match_dup 1)))
1062 (set (match_dup 2)
1063 (compare:CC (match_dup 0)
1064 (const_int 0)))]
1065 ""
1066 [(set_attr "type" "exts")
1067 (set_attr "dot" "yes")
1068 (set_attr "length" "4,8")])
1069
1070 (define_insn_and_split "*extendsi<mode>2_dot2"
1071 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
1072 (compare:CC (sign_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
1073 (const_int 0)))
1074 (set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r")
1075 (sign_extend:EXTSI (match_dup 1)))]
1076 "rs6000_gen_cell_microcode"
1077 "@
1078 extsw. %0,%1
1079 #"
1080 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
1081 [(set (match_dup 0)
1082 (sign_extend:EXTSI (match_dup 1)))
1083 (set (match_dup 2)
1084 (compare:CC (match_dup 0)
1085 (const_int 0)))]
1086 ""
1087 [(set_attr "type" "exts")
1088 (set_attr "dot" "yes")
1089 (set_attr "length" "4,8")])
1090 \f
1091 ;; IBM 405, 440, 464 and 476 half-word multiplication operations.
1092
1093 (define_insn "*macchwc"
1094 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1095 (compare:CC (plus:SI (mult:SI (ashiftrt:SI
1096 (match_operand:SI 2 "gpc_reg_operand" "r")
1097 (const_int 16))
1098 (sign_extend:SI
1099 (match_operand:HI 1 "gpc_reg_operand" "r")))
1100 (match_operand:SI 4 "gpc_reg_operand" "0"))
1101 (const_int 0)))
1102 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1103 (plus:SI (mult:SI (ashiftrt:SI
1104 (match_dup 2)
1105 (const_int 16))
1106 (sign_extend:SI
1107 (match_dup 1)))
1108 (match_dup 4)))]
1109 "TARGET_MULHW"
1110 "macchw. %0,%1,%2"
1111 [(set_attr "type" "halfmul")])
1112
1113 (define_insn "*macchw"
1114 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1115 (plus:SI (mult:SI (ashiftrt:SI
1116 (match_operand:SI 2 "gpc_reg_operand" "r")
1117 (const_int 16))
1118 (sign_extend:SI
1119 (match_operand:HI 1 "gpc_reg_operand" "r")))
1120 (match_operand:SI 3 "gpc_reg_operand" "0")))]
1121 "TARGET_MULHW"
1122 "macchw %0,%1,%2"
1123 [(set_attr "type" "halfmul")])
1124
1125 (define_insn "*macchwuc"
1126 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1127 (compare:CC (plus:SI (mult:SI (lshiftrt:SI
1128 (match_operand:SI 2 "gpc_reg_operand" "r")
1129 (const_int 16))
1130 (zero_extend:SI
1131 (match_operand:HI 1 "gpc_reg_operand" "r")))
1132 (match_operand:SI 4 "gpc_reg_operand" "0"))
1133 (const_int 0)))
1134 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1135 (plus:SI (mult:SI (lshiftrt:SI
1136 (match_dup 2)
1137 (const_int 16))
1138 (zero_extend:SI
1139 (match_dup 1)))
1140 (match_dup 4)))]
1141 "TARGET_MULHW"
1142 "macchwu. %0,%1,%2"
1143 [(set_attr "type" "halfmul")])
1144
1145 (define_insn "*macchwu"
1146 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1147 (plus:SI (mult:SI (lshiftrt:SI
1148 (match_operand:SI 2 "gpc_reg_operand" "r")
1149 (const_int 16))
1150 (zero_extend:SI
1151 (match_operand:HI 1 "gpc_reg_operand" "r")))
1152 (match_operand:SI 3 "gpc_reg_operand" "0")))]
1153 "TARGET_MULHW"
1154 "macchwu %0,%1,%2"
1155 [(set_attr "type" "halfmul")])
1156
1157 (define_insn "*machhwc"
1158 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1159 (compare:CC (plus:SI (mult:SI (ashiftrt:SI
1160 (match_operand:SI 1 "gpc_reg_operand" "%r")
1161 (const_int 16))
1162 (ashiftrt:SI
1163 (match_operand:SI 2 "gpc_reg_operand" "r")
1164 (const_int 16)))
1165 (match_operand:SI 4 "gpc_reg_operand" "0"))
1166 (const_int 0)))
1167 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1168 (plus:SI (mult:SI (ashiftrt:SI
1169 (match_dup 1)
1170 (const_int 16))
1171 (ashiftrt:SI
1172 (match_dup 2)
1173 (const_int 16)))
1174 (match_dup 4)))]
1175 "TARGET_MULHW"
1176 "machhw. %0,%1,%2"
1177 [(set_attr "type" "halfmul")])
1178
1179 (define_insn "*machhw"
1180 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1181 (plus:SI (mult:SI (ashiftrt:SI
1182 (match_operand:SI 1 "gpc_reg_operand" "%r")
1183 (const_int 16))
1184 (ashiftrt:SI
1185 (match_operand:SI 2 "gpc_reg_operand" "r")
1186 (const_int 16)))
1187 (match_operand:SI 3 "gpc_reg_operand" "0")))]
1188 "TARGET_MULHW"
1189 "machhw %0,%1,%2"
1190 [(set_attr "type" "halfmul")])
1191
1192 (define_insn "*machhwuc"
1193 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1194 (compare:CC (plus:SI (mult:SI (lshiftrt:SI
1195 (match_operand:SI 1 "gpc_reg_operand" "%r")
1196 (const_int 16))
1197 (lshiftrt:SI
1198 (match_operand:SI 2 "gpc_reg_operand" "r")
1199 (const_int 16)))
1200 (match_operand:SI 4 "gpc_reg_operand" "0"))
1201 (const_int 0)))
1202 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1203 (plus:SI (mult:SI (lshiftrt:SI
1204 (match_dup 1)
1205 (const_int 16))
1206 (lshiftrt:SI
1207 (match_dup 2)
1208 (const_int 16)))
1209 (match_dup 4)))]
1210 "TARGET_MULHW"
1211 "machhwu. %0,%1,%2"
1212 [(set_attr "type" "halfmul")])
1213
1214 (define_insn "*machhwu"
1215 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1216 (plus:SI (mult:SI (lshiftrt:SI
1217 (match_operand:SI 1 "gpc_reg_operand" "%r")
1218 (const_int 16))
1219 (lshiftrt:SI
1220 (match_operand:SI 2 "gpc_reg_operand" "r")
1221 (const_int 16)))
1222 (match_operand:SI 3 "gpc_reg_operand" "0")))]
1223 "TARGET_MULHW"
1224 "machhwu %0,%1,%2"
1225 [(set_attr "type" "halfmul")])
1226
1227 (define_insn "*maclhwc"
1228 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1229 (compare:CC (plus:SI (mult:SI (sign_extend:SI
1230 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1231 (sign_extend:SI
1232 (match_operand:HI 2 "gpc_reg_operand" "r")))
1233 (match_operand:SI 4 "gpc_reg_operand" "0"))
1234 (const_int 0)))
1235 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1236 (plus:SI (mult:SI (sign_extend:SI
1237 (match_dup 1))
1238 (sign_extend:SI
1239 (match_dup 2)))
1240 (match_dup 4)))]
1241 "TARGET_MULHW"
1242 "maclhw. %0,%1,%2"
1243 [(set_attr "type" "halfmul")])
1244
1245 (define_insn "*maclhw"
1246 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1247 (plus:SI (mult:SI (sign_extend:SI
1248 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1249 (sign_extend:SI
1250 (match_operand:HI 2 "gpc_reg_operand" "r")))
1251 (match_operand:SI 3 "gpc_reg_operand" "0")))]
1252 "TARGET_MULHW"
1253 "maclhw %0,%1,%2"
1254 [(set_attr "type" "halfmul")])
1255
1256 (define_insn "*maclhwuc"
1257 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1258 (compare:CC (plus:SI (mult:SI (zero_extend:SI
1259 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1260 (zero_extend:SI
1261 (match_operand:HI 2 "gpc_reg_operand" "r")))
1262 (match_operand:SI 4 "gpc_reg_operand" "0"))
1263 (const_int 0)))
1264 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1265 (plus:SI (mult:SI (zero_extend:SI
1266 (match_dup 1))
1267 (zero_extend:SI
1268 (match_dup 2)))
1269 (match_dup 4)))]
1270 "TARGET_MULHW"
1271 "maclhwu. %0,%1,%2"
1272 [(set_attr "type" "halfmul")])
1273
1274 (define_insn "*maclhwu"
1275 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1276 (plus:SI (mult:SI (zero_extend:SI
1277 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1278 (zero_extend:SI
1279 (match_operand:HI 2 "gpc_reg_operand" "r")))
1280 (match_operand:SI 3 "gpc_reg_operand" "0")))]
1281 "TARGET_MULHW"
1282 "maclhwu %0,%1,%2"
1283 [(set_attr "type" "halfmul")])
1284
1285 (define_insn "*nmacchwc"
1286 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1287 (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
1288 (mult:SI (ashiftrt:SI
1289 (match_operand:SI 2 "gpc_reg_operand" "r")
1290 (const_int 16))
1291 (sign_extend:SI
1292 (match_operand:HI 1 "gpc_reg_operand" "r"))))
1293 (const_int 0)))
1294 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1295 (minus:SI (match_dup 4)
1296 (mult:SI (ashiftrt:SI
1297 (match_dup 2)
1298 (const_int 16))
1299 (sign_extend:SI
1300 (match_dup 1)))))]
1301 "TARGET_MULHW"
1302 "nmacchw. %0,%1,%2"
1303 [(set_attr "type" "halfmul")])
1304
1305 (define_insn "*nmacchw"
1306 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1307 (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
1308 (mult:SI (ashiftrt:SI
1309 (match_operand:SI 2 "gpc_reg_operand" "r")
1310 (const_int 16))
1311 (sign_extend:SI
1312 (match_operand:HI 1 "gpc_reg_operand" "r")))))]
1313 "TARGET_MULHW"
1314 "nmacchw %0,%1,%2"
1315 [(set_attr "type" "halfmul")])
1316
1317 (define_insn "*nmachhwc"
1318 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1319 (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
1320 (mult:SI (ashiftrt:SI
1321 (match_operand:SI 1 "gpc_reg_operand" "%r")
1322 (const_int 16))
1323 (ashiftrt:SI
1324 (match_operand:SI 2 "gpc_reg_operand" "r")
1325 (const_int 16))))
1326 (const_int 0)))
1327 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1328 (minus:SI (match_dup 4)
1329 (mult:SI (ashiftrt:SI
1330 (match_dup 1)
1331 (const_int 16))
1332 (ashiftrt:SI
1333 (match_dup 2)
1334 (const_int 16)))))]
1335 "TARGET_MULHW"
1336 "nmachhw. %0,%1,%2"
1337 [(set_attr "type" "halfmul")])
1338
1339 (define_insn "*nmachhw"
1340 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1341 (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
1342 (mult:SI (ashiftrt:SI
1343 (match_operand:SI 1 "gpc_reg_operand" "%r")
1344 (const_int 16))
1345 (ashiftrt:SI
1346 (match_operand:SI 2 "gpc_reg_operand" "r")
1347 (const_int 16)))))]
1348 "TARGET_MULHW"
1349 "nmachhw %0,%1,%2"
1350 [(set_attr "type" "halfmul")])
1351
1352 (define_insn "*nmaclhwc"
1353 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1354 (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
1355 (mult:SI (sign_extend:SI
1356 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1357 (sign_extend:SI
1358 (match_operand:HI 2 "gpc_reg_operand" "r"))))
1359 (const_int 0)))
1360 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1361 (minus:SI (match_dup 4)
1362 (mult:SI (sign_extend:SI
1363 (match_dup 1))
1364 (sign_extend:SI
1365 (match_dup 2)))))]
1366 "TARGET_MULHW"
1367 "nmaclhw. %0,%1,%2"
1368 [(set_attr "type" "halfmul")])
1369
1370 (define_insn "*nmaclhw"
1371 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1372 (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
1373 (mult:SI (sign_extend:SI
1374 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1375 (sign_extend:SI
1376 (match_operand:HI 2 "gpc_reg_operand" "r")))))]
1377 "TARGET_MULHW"
1378 "nmaclhw %0,%1,%2"
1379 [(set_attr "type" "halfmul")])
1380
1381 (define_insn "*mulchwc"
1382 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1383 (compare:CC (mult:SI (ashiftrt:SI
1384 (match_operand:SI 2 "gpc_reg_operand" "r")
1385 (const_int 16))
1386 (sign_extend:SI
1387 (match_operand:HI 1 "gpc_reg_operand" "r")))
1388 (const_int 0)))
1389 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1390 (mult:SI (ashiftrt:SI
1391 (match_dup 2)
1392 (const_int 16))
1393 (sign_extend:SI
1394 (match_dup 1))))]
1395 "TARGET_MULHW"
1396 "mulchw. %0,%1,%2"
1397 [(set_attr "type" "halfmul")])
1398
1399 (define_insn "*mulchw"
1400 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1401 (mult:SI (ashiftrt:SI
1402 (match_operand:SI 2 "gpc_reg_operand" "r")
1403 (const_int 16))
1404 (sign_extend:SI
1405 (match_operand:HI 1 "gpc_reg_operand" "r"))))]
1406 "TARGET_MULHW"
1407 "mulchw %0,%1,%2"
1408 [(set_attr "type" "halfmul")])
1409
1410 (define_insn "*mulchwuc"
1411 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1412 (compare:CC (mult:SI (lshiftrt:SI
1413 (match_operand:SI 2 "gpc_reg_operand" "r")
1414 (const_int 16))
1415 (zero_extend:SI
1416 (match_operand:HI 1 "gpc_reg_operand" "r")))
1417 (const_int 0)))
1418 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1419 (mult:SI (lshiftrt:SI
1420 (match_dup 2)
1421 (const_int 16))
1422 (zero_extend:SI
1423 (match_dup 1))))]
1424 "TARGET_MULHW"
1425 "mulchwu. %0,%1,%2"
1426 [(set_attr "type" "halfmul")])
1427
1428 (define_insn "*mulchwu"
1429 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1430 (mult:SI (lshiftrt:SI
1431 (match_operand:SI 2 "gpc_reg_operand" "r")
1432 (const_int 16))
1433 (zero_extend:SI
1434 (match_operand:HI 1 "gpc_reg_operand" "r"))))]
1435 "TARGET_MULHW"
1436 "mulchwu %0,%1,%2"
1437 [(set_attr "type" "halfmul")])
1438
1439 (define_insn "*mulhhwc"
1440 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1441 (compare:CC (mult:SI (ashiftrt:SI
1442 (match_operand:SI 1 "gpc_reg_operand" "%r")
1443 (const_int 16))
1444 (ashiftrt:SI
1445 (match_operand:SI 2 "gpc_reg_operand" "r")
1446 (const_int 16)))
1447 (const_int 0)))
1448 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1449 (mult:SI (ashiftrt:SI
1450 (match_dup 1)
1451 (const_int 16))
1452 (ashiftrt:SI
1453 (match_dup 2)
1454 (const_int 16))))]
1455 "TARGET_MULHW"
1456 "mulhhw. %0,%1,%2"
1457 [(set_attr "type" "halfmul")])
1458
1459 (define_insn "*mulhhw"
1460 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1461 (mult:SI (ashiftrt:SI
1462 (match_operand:SI 1 "gpc_reg_operand" "%r")
1463 (const_int 16))
1464 (ashiftrt:SI
1465 (match_operand:SI 2 "gpc_reg_operand" "r")
1466 (const_int 16))))]
1467 "TARGET_MULHW"
1468 "mulhhw %0,%1,%2"
1469 [(set_attr "type" "halfmul")])
1470
1471 (define_insn "*mulhhwuc"
1472 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1473 (compare:CC (mult:SI (lshiftrt:SI
1474 (match_operand:SI 1 "gpc_reg_operand" "%r")
1475 (const_int 16))
1476 (lshiftrt:SI
1477 (match_operand:SI 2 "gpc_reg_operand" "r")
1478 (const_int 16)))
1479 (const_int 0)))
1480 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1481 (mult:SI (lshiftrt:SI
1482 (match_dup 1)
1483 (const_int 16))
1484 (lshiftrt:SI
1485 (match_dup 2)
1486 (const_int 16))))]
1487 "TARGET_MULHW"
1488 "mulhhwu. %0,%1,%2"
1489 [(set_attr "type" "halfmul")])
1490
1491 (define_insn "*mulhhwu"
1492 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1493 (mult:SI (lshiftrt:SI
1494 (match_operand:SI 1 "gpc_reg_operand" "%r")
1495 (const_int 16))
1496 (lshiftrt:SI
1497 (match_operand:SI 2 "gpc_reg_operand" "r")
1498 (const_int 16))))]
1499 "TARGET_MULHW"
1500 "mulhhwu %0,%1,%2"
1501 [(set_attr "type" "halfmul")])
1502
1503 (define_insn "*mullhwc"
1504 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1505 (compare:CC (mult:SI (sign_extend:SI
1506 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1507 (sign_extend:SI
1508 (match_operand:HI 2 "gpc_reg_operand" "r")))
1509 (const_int 0)))
1510 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1511 (mult:SI (sign_extend:SI
1512 (match_dup 1))
1513 (sign_extend:SI
1514 (match_dup 2))))]
1515 "TARGET_MULHW"
1516 "mullhw. %0,%1,%2"
1517 [(set_attr "type" "halfmul")])
1518
1519 (define_insn "*mullhw"
1520 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1521 (mult:SI (sign_extend:SI
1522 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1523 (sign_extend:SI
1524 (match_operand:HI 2 "gpc_reg_operand" "r"))))]
1525 "TARGET_MULHW"
1526 "mullhw %0,%1,%2"
1527 [(set_attr "type" "halfmul")])
1528
1529 (define_insn "*mullhwuc"
1530 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1531 (compare:CC (mult:SI (zero_extend:SI
1532 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1533 (zero_extend:SI
1534 (match_operand:HI 2 "gpc_reg_operand" "r")))
1535 (const_int 0)))
1536 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1537 (mult:SI (zero_extend:SI
1538 (match_dup 1))
1539 (zero_extend:SI
1540 (match_dup 2))))]
1541 "TARGET_MULHW"
1542 "mullhwu. %0,%1,%2"
1543 [(set_attr "type" "halfmul")])
1544
1545 (define_insn "*mullhwu"
1546 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
1547 (mult:SI (zero_extend:SI
1548 (match_operand:HI 1 "gpc_reg_operand" "%r"))
1549 (zero_extend:SI
1550 (match_operand:HI 2 "gpc_reg_operand" "r"))))]
1551 "TARGET_MULHW"
1552 "mullhwu %0,%1,%2"
1553 [(set_attr "type" "halfmul")])
1554 \f
1555 ;; IBM 405, 440, 464 and 476 string-search dlmzb instruction support.
1556 (define_insn "dlmzb"
1557 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
1558 (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
1559 (match_operand:SI 2 "gpc_reg_operand" "r")]
1560 UNSPEC_DLMZB_CR))
1561 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
1562 (unspec:SI [(match_dup 1)
1563 (match_dup 2)]
1564 UNSPEC_DLMZB))]
1565 "TARGET_DLMZB"
1566 "dlmzb. %0,%1,%2")
1567
1568 (define_expand "strlensi"
1569 [(set (match_operand:SI 0 "gpc_reg_operand" "")
1570 (unspec:SI [(match_operand:BLK 1 "general_operand" "")
1571 (match_operand:QI 2 "const_int_operand" "")
1572 (match_operand 3 "const_int_operand" "")]
1573 UNSPEC_DLMZB_STRLEN))
1574 (clobber (match_scratch:CC 4 "=x"))]
1575 "TARGET_DLMZB && WORDS_BIG_ENDIAN && !optimize_size"
1576 {
1577 rtx result = operands[0];
1578 rtx src = operands[1];
1579 rtx search_char = operands[2];
1580 rtx align = operands[3];
1581 rtx addr, scratch_string, word1, word2, scratch_dlmzb;
1582 rtx loop_label, end_label, mem, cr0, cond;
1583 if (search_char != const0_rtx
1584 || GET_CODE (align) != CONST_INT
1585 || INTVAL (align) < 8)
1586 FAIL;
1587 word1 = gen_reg_rtx (SImode);
1588 word2 = gen_reg_rtx (SImode);
1589 scratch_dlmzb = gen_reg_rtx (SImode);
1590 scratch_string = gen_reg_rtx (Pmode);
1591 loop_label = gen_label_rtx ();
1592 end_label = gen_label_rtx ();
1593 addr = force_reg (Pmode, XEXP (src, 0));
1594 emit_move_insn (scratch_string, addr);
1595 emit_label (loop_label);
1596 mem = change_address (src, SImode, scratch_string);
1597 emit_move_insn (word1, mem);
1598 emit_move_insn (word2, adjust_address (mem, SImode, 4));
1599 cr0 = gen_rtx_REG (CCmode, CR0_REGNO);
1600 emit_insn (gen_dlmzb (scratch_dlmzb, word1, word2, cr0));
1601 cond = gen_rtx_NE (VOIDmode, cr0, const0_rtx);
1602 emit_jump_insn (gen_rtx_SET (pc_rtx,
1603 gen_rtx_IF_THEN_ELSE (VOIDmode,
1604 cond,
1605 gen_rtx_LABEL_REF
1606 (VOIDmode,
1607 end_label),
1608 pc_rtx)));
1609 emit_insn (gen_addsi3 (scratch_string, scratch_string, GEN_INT (8)));
1610 emit_jump_insn (gen_rtx_SET (pc_rtx,
1611 gen_rtx_LABEL_REF (VOIDmode, loop_label)));
1612 emit_barrier ();
1613 emit_label (end_label);
1614 emit_insn (gen_addsi3 (scratch_string, scratch_string, scratch_dlmzb));
1615 emit_insn (gen_subsi3 (result, scratch_string, addr));
1616 emit_insn (gen_addsi3 (result, result, constm1_rtx));
1617 DONE;
1618 })
1619 \f
1620 ;; Fixed-point arithmetic insns.
1621
1622 (define_expand "add<mode>3"
1623 [(set (match_operand:SDI 0 "gpc_reg_operand" "")
1624 (plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
1625 (match_operand:SDI 2 "reg_or_add_cint_operand" "")))]
1626 ""
1627 {
1628 if (<MODE>mode == DImode && !TARGET_POWERPC64)
1629 {
1630 rtx lo0 = gen_lowpart (SImode, operands[0]);
1631 rtx lo1 = gen_lowpart (SImode, operands[1]);
1632 rtx lo2 = gen_lowpart (SImode, operands[2]);
1633 rtx hi0 = gen_highpart (SImode, operands[0]);
1634 rtx hi1 = gen_highpart (SImode, operands[1]);
1635 rtx hi2 = gen_highpart_mode (SImode, DImode, operands[2]);
1636
1637 if (!reg_or_short_operand (lo2, SImode))
1638 lo2 = force_reg (SImode, lo2);
1639 if (!adde_operand (hi2, SImode))
1640 hi2 = force_reg (SImode, hi2);
1641
1642 emit_insn (gen_addsi3_carry (lo0, lo1, lo2));
1643 emit_insn (gen_addsi3_carry_in (hi0, hi1, hi2));
1644 DONE;
1645 }
1646
1647 if (CONST_INT_P (operands[2]) && !add_operand (operands[2], <MODE>mode))
1648 {
1649 rtx tmp = ((!can_create_pseudo_p ()
1650 || rtx_equal_p (operands[0], operands[1]))
1651 ? operands[0] : gen_reg_rtx (<MODE>mode));
1652
1653 HOST_WIDE_INT val = INTVAL (operands[2]);
1654 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
1655 HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
1656
1657 if (<MODE>mode == DImode && !satisfies_constraint_L (GEN_INT (rest)))
1658 FAIL;
1659
1660 /* The ordering here is important for the prolog expander.
1661 When space is allocated from the stack, adding 'low' first may
1662 produce a temporary deallocation (which would be bad). */
1663 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (rest)));
1664 emit_insn (gen_add<mode>3 (operands[0], tmp, GEN_INT (low)));
1665 DONE;
1666 }
1667 })
1668
1669 (define_insn "*add<mode>3"
1670 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
1671 (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
1672 (match_operand:GPR 2 "add_operand" "r,I,L")))]
1673 ""
1674 "@
1675 add %0,%1,%2
1676 addi %0,%1,%2
1677 addis %0,%1,%v2"
1678 [(set_attr "type" "add")])
1679
1680 (define_insn "addsi3_high"
1681 [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
1682 (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
1683 (high:SI (match_operand 2 "" ""))))]
1684 "TARGET_MACHO && !TARGET_64BIT"
1685 "addis %0,%1,ha16(%2)"
1686 [(set_attr "type" "add")])
1687
1688 (define_insn_and_split "*add<mode>3_dot"
1689 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
1690 (compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
1691 (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
1692 (const_int 0)))
1693 (clobber (match_scratch:GPR 0 "=r,r"))]
1694 "<MODE>mode == Pmode"
1695 "@
1696 add. %0,%1,%2
1697 #"
1698 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
1699 [(set (match_dup 0)
1700 (plus:GPR (match_dup 1)
1701 (match_dup 2)))
1702 (set (match_dup 3)
1703 (compare:CC (match_dup 0)
1704 (const_int 0)))]
1705 ""
1706 [(set_attr "type" "add")
1707 (set_attr "dot" "yes")
1708 (set_attr "length" "4,8")])
1709
1710 (define_insn_and_split "*add<mode>3_dot2"
1711 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
1712 (compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
1713 (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
1714 (const_int 0)))
1715 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
1716 (plus:GPR (match_dup 1)
1717 (match_dup 2)))]
1718 "<MODE>mode == Pmode"
1719 "@
1720 add. %0,%1,%2
1721 #"
1722 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
1723 [(set (match_dup 0)
1724 (plus:GPR (match_dup 1)
1725 (match_dup 2)))
1726 (set (match_dup 3)
1727 (compare:CC (match_dup 0)
1728 (const_int 0)))]
1729 ""
1730 [(set_attr "type" "add")
1731 (set_attr "dot" "yes")
1732 (set_attr "length" "4,8")])
1733
1734 (define_insn_and_split "*add<mode>3_imm_dot"
1735 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
1736 (compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b")
1737 (match_operand:GPR 2 "short_cint_operand" "I,I"))
1738 (const_int 0)))
1739 (clobber (match_scratch:GPR 0 "=r,r"))
1740 (clobber (reg:GPR CA_REGNO))]
1741 "<MODE>mode == Pmode"
1742 "@
1743 addic. %0,%1,%2
1744 #"
1745 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
1746 [(set (match_dup 0)
1747 (plus:GPR (match_dup 1)
1748 (match_dup 2)))
1749 (set (match_dup 3)
1750 (compare:CC (match_dup 0)
1751 (const_int 0)))]
1752 ""
1753 [(set_attr "type" "add")
1754 (set_attr "dot" "yes")
1755 (set_attr "length" "4,8")])
1756
1757 (define_insn_and_split "*add<mode>3_imm_dot2"
1758 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
1759 (compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b")
1760 (match_operand:GPR 2 "short_cint_operand" "I,I"))
1761 (const_int 0)))
1762 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
1763 (plus:GPR (match_dup 1)
1764 (match_dup 2)))
1765 (clobber (reg:GPR CA_REGNO))]
1766 "<MODE>mode == Pmode"
1767 "@
1768 addic. %0,%1,%2
1769 #"
1770 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
1771 [(set (match_dup 0)
1772 (plus:GPR (match_dup 1)
1773 (match_dup 2)))
1774 (set (match_dup 3)
1775 (compare:CC (match_dup 0)
1776 (const_int 0)))]
1777 ""
1778 [(set_attr "type" "add")
1779 (set_attr "dot" "yes")
1780 (set_attr "length" "4,8")])
1781
1782 ;; Split an add that we can't do in one insn into two insns, each of which
1783 ;; does one 16-bit part. This is used by combine. Note that the low-order
1784 ;; add should be last in case the result gets used in an address.
1785
1786 (define_split
1787 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
1788 (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
1789 (match_operand:GPR 2 "non_add_cint_operand" "")))]
1790 ""
1791 [(set (match_dup 0) (plus:GPR (match_dup 1) (match_dup 3)))
1792 (set (match_dup 0) (plus:GPR (match_dup 0) (match_dup 4)))]
1793 {
1794 HOST_WIDE_INT val = INTVAL (operands[2]);
1795 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
1796 HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
1797
1798 operands[4] = GEN_INT (low);
1799 if (<MODE>mode == SImode || satisfies_constraint_L (GEN_INT (rest)))
1800 operands[3] = GEN_INT (rest);
1801 else if (can_create_pseudo_p ())
1802 {
1803 operands[3] = gen_reg_rtx (DImode);
1804 emit_move_insn (operands[3], operands[2]);
1805 emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
1806 DONE;
1807 }
1808 else
1809 FAIL;
1810 })
1811
1812
1813 (define_insn "add<mode>3_carry"
1814 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
1815 (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
1816 (match_operand:P 2 "reg_or_short_operand" "rI")))
1817 (set (reg:P CA_REGNO)
1818 (ltu:P (plus:P (match_dup 1)
1819 (match_dup 2))
1820 (match_dup 1)))]
1821 ""
1822 "add%I2c %0,%1,%2"
1823 [(set_attr "type" "add")])
1824
1825 (define_insn "*add<mode>3_imm_carry_pos"
1826 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
1827 (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
1828 (match_operand:P 2 "short_cint_operand" "n")))
1829 (set (reg:P CA_REGNO)
1830 (geu:P (match_dup 1)
1831 (match_operand:P 3 "const_int_operand" "n")))]
1832 "INTVAL (operands[2]) > 0
1833 && INTVAL (operands[2]) + INTVAL (operands[3]) == 0"
1834 "addic %0,%1,%2"
1835 [(set_attr "type" "add")])
1836
1837 (define_insn "*add<mode>3_imm_carry_0"
1838 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
1839 (match_operand:P 1 "gpc_reg_operand" "r"))
1840 (set (reg:P CA_REGNO)
1841 (const_int 0))]
1842 ""
1843 "addic %0,%1,0"
1844 [(set_attr "type" "add")])
1845
1846 (define_insn "*add<mode>3_imm_carry_m1"
1847 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
1848 (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
1849 (const_int -1)))
1850 (set (reg:P CA_REGNO)
1851 (ne:P (match_dup 1)
1852 (const_int 0)))]
1853 ""
1854 "addic %0,%1,-1"
1855 [(set_attr "type" "add")])
1856
1857 (define_insn "*add<mode>3_imm_carry_neg"
1858 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
1859 (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
1860 (match_operand:P 2 "short_cint_operand" "n")))
1861 (set (reg:P CA_REGNO)
1862 (gtu:P (match_dup 1)
1863 (match_operand:P 3 "const_int_operand" "n")))]
1864 "INTVAL (operands[2]) < 0
1865 && INTVAL (operands[2]) + INTVAL (operands[3]) == -1"
1866 "addic %0,%1,%2"
1867 [(set_attr "type" "add")])
1868
1869
1870 (define_expand "add<mode>3_carry_in"
1871 [(parallel [
1872 (set (match_operand:GPR 0 "gpc_reg_operand")
1873 (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand")
1874 (match_operand:GPR 2 "adde_operand"))
1875 (reg:GPR CA_REGNO)))
1876 (clobber (reg:GPR CA_REGNO))])]
1877 ""
1878 {
1879 if (operands[2] == const0_rtx)
1880 {
1881 emit_insn (gen_add<mode>3_carry_in_0 (operands[0], operands[1]));
1882 DONE;
1883 }
1884 if (operands[2] == constm1_rtx)
1885 {
1886 emit_insn (gen_add<mode>3_carry_in_m1 (operands[0], operands[1]));
1887 DONE;
1888 }
1889 })
1890
1891 (define_insn "*add<mode>3_carry_in_internal"
1892 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
1893 (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
1894 (match_operand:GPR 2 "gpc_reg_operand" "r"))
1895 (reg:GPR CA_REGNO)))
1896 (clobber (reg:GPR CA_REGNO))]
1897 ""
1898 "adde %0,%1,%2"
1899 [(set_attr "type" "add")])
1900
1901 (define_insn "add<mode>3_carry_in_0"
1902 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
1903 (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
1904 (reg:GPR CA_REGNO)))
1905 (clobber (reg:GPR CA_REGNO))]
1906 ""
1907 "addze %0,%1"
1908 [(set_attr "type" "add")])
1909
1910 (define_insn "add<mode>3_carry_in_m1"
1911 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
1912 (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
1913 (reg:GPR CA_REGNO))
1914 (const_int -1)))
1915 (clobber (reg:GPR CA_REGNO))]
1916 ""
1917 "addme %0,%1"
1918 [(set_attr "type" "add")])
1919
1920
1921 (define_expand "one_cmpl<mode>2"
1922 [(set (match_operand:SDI 0 "gpc_reg_operand" "")
1923 (not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
1924 ""
1925 {
1926 if (<MODE>mode == DImode && !TARGET_POWERPC64)
1927 {
1928 rs6000_split_logical (operands, NOT, false, false, false);
1929 DONE;
1930 }
1931 })
1932
1933 (define_insn "*one_cmpl<mode>2"
1934 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
1935 (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
1936 ""
1937 "not %0,%1")
1938
1939 (define_insn_and_split "*one_cmpl<mode>2_dot"
1940 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
1941 (compare:CC (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
1942 (const_int 0)))
1943 (clobber (match_scratch:GPR 0 "=r,r"))]
1944 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
1945 "@
1946 not. %0,%1
1947 #"
1948 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
1949 [(set (match_dup 0)
1950 (not:GPR (match_dup 1)))
1951 (set (match_dup 2)
1952 (compare:CC (match_dup 0)
1953 (const_int 0)))]
1954 ""
1955 [(set_attr "type" "logical")
1956 (set_attr "dot" "yes")
1957 (set_attr "length" "4,8")])
1958
1959 (define_insn_and_split "*one_cmpl<mode>2_dot2"
1960 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
1961 (compare:CC (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
1962 (const_int 0)))
1963 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
1964 (not:GPR (match_dup 1)))]
1965 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
1966 "@
1967 not. %0,%1
1968 #"
1969 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
1970 [(set (match_dup 0)
1971 (not:GPR (match_dup 1)))
1972 (set (match_dup 2)
1973 (compare:CC (match_dup 0)
1974 (const_int 0)))]
1975 ""
1976 [(set_attr "type" "logical")
1977 (set_attr "dot" "yes")
1978 (set_attr "length" "4,8")])
1979
1980
1981 (define_expand "sub<mode>3"
1982 [(set (match_operand:SDI 0 "gpc_reg_operand" "")
1983 (minus:SDI (match_operand:SDI 1 "reg_or_short_operand" "")
1984 (match_operand:SDI 2 "gpc_reg_operand" "")))]
1985 ""
1986 {
1987 if (<MODE>mode == DImode && !TARGET_POWERPC64)
1988 {
1989 rtx lo0 = gen_lowpart (SImode, operands[0]);
1990 rtx lo1 = gen_lowpart (SImode, operands[1]);
1991 rtx lo2 = gen_lowpart (SImode, operands[2]);
1992 rtx hi0 = gen_highpart (SImode, operands[0]);
1993 rtx hi1 = gen_highpart_mode (SImode, DImode, operands[1]);
1994 rtx hi2 = gen_highpart (SImode, operands[2]);
1995
1996 if (!reg_or_short_operand (lo1, SImode))
1997 lo1 = force_reg (SImode, lo1);
1998 if (!adde_operand (hi1, SImode))
1999 hi1 = force_reg (SImode, hi1);
2000
2001 emit_insn (gen_subfsi3_carry (lo0, lo2, lo1));
2002 emit_insn (gen_subfsi3_carry_in (hi0, hi2, hi1));
2003 DONE;
2004 }
2005
2006 if (short_cint_operand (operands[1], <MODE>mode))
2007 {
2008 emit_insn (gen_subf<mode>3_imm (operands[0], operands[2], operands[1]));
2009 DONE;
2010 }
2011 })
2012
2013 (define_insn "*subf<mode>3"
2014 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2015 (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r")
2016 (match_operand:GPR 1 "gpc_reg_operand" "r")))]
2017 ""
2018 "subf %0,%1,%2"
2019 [(set_attr "type" "add")])
2020
2021 (define_insn_and_split "*subf<mode>3_dot"
2022 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
2023 (compare:CC (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r")
2024 (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
2025 (const_int 0)))
2026 (clobber (match_scratch:GPR 0 "=r,r"))]
2027 "<MODE>mode == Pmode"
2028 "@
2029 subf. %0,%1,%2
2030 #"
2031 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
2032 [(set (match_dup 0)
2033 (minus:GPR (match_dup 2)
2034 (match_dup 1)))
2035 (set (match_dup 3)
2036 (compare:CC (match_dup 0)
2037 (const_int 0)))]
2038 ""
2039 [(set_attr "type" "add")
2040 (set_attr "dot" "yes")
2041 (set_attr "length" "4,8")])
2042
2043 (define_insn_and_split "*subf<mode>3_dot2"
2044 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
2045 (compare:CC (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r")
2046 (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
2047 (const_int 0)))
2048 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
2049 (minus:GPR (match_dup 2)
2050 (match_dup 1)))]
2051 "<MODE>mode == Pmode"
2052 "@
2053 subf. %0,%1,%2
2054 #"
2055 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
2056 [(set (match_dup 0)
2057 (minus:GPR (match_dup 2)
2058 (match_dup 1)))
2059 (set (match_dup 3)
2060 (compare:CC (match_dup 0)
2061 (const_int 0)))]
2062 ""
2063 [(set_attr "type" "add")
2064 (set_attr "dot" "yes")
2065 (set_attr "length" "4,8")])
2066
2067 (define_insn "subf<mode>3_imm"
2068 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2069 (minus:GPR (match_operand:GPR 2 "short_cint_operand" "I")
2070 (match_operand:GPR 1 "gpc_reg_operand" "r")))
2071 (clobber (reg:GPR CA_REGNO))]
2072 ""
2073 "subfic %0,%1,%2"
2074 [(set_attr "type" "add")])
2075
2076 (define_insn_and_split "subf<mode>3_carry_dot2"
2077 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
2078 (compare:CC (minus:P (match_operand:P 2 "gpc_reg_operand" "r,r")
2079 (match_operand:P 1 "gpc_reg_operand" "r,r"))
2080 (const_int 0)))
2081 (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
2082 (minus:P (match_dup 2)
2083 (match_dup 1)))
2084 (set (reg:P CA_REGNO)
2085 (leu:P (match_dup 1)
2086 (match_dup 2)))]
2087 "<MODE>mode == Pmode"
2088 "@
2089 subfc. %0,%1,%2
2090 #"
2091 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
2092 [(parallel [(set (match_dup 0)
2093 (minus:P (match_dup 2)
2094 (match_dup 1)))
2095 (set (reg:P CA_REGNO)
2096 (leu:P (match_dup 1)
2097 (match_dup 2)))])
2098 (set (match_dup 3)
2099 (compare:CC (match_dup 0)
2100 (const_int 0)))]
2101 ""
2102 [(set_attr "type" "add")
2103 (set_attr "dot" "yes")
2104 (set_attr "length" "4,8")])
2105
2106 (define_insn "subf<mode>3_carry"
2107 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
2108 (minus:P (match_operand:P 2 "reg_or_short_operand" "rI")
2109 (match_operand:P 1 "gpc_reg_operand" "r")))
2110 (set (reg:P CA_REGNO)
2111 (leu:P (match_dup 1)
2112 (match_dup 2)))]
2113 ""
2114 "subf%I2c %0,%1,%2"
2115 [(set_attr "type" "add")])
2116
2117 (define_insn "*subf<mode>3_imm_carry_0"
2118 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
2119 (neg:P (match_operand:P 1 "gpc_reg_operand" "r")))
2120 (set (reg:P CA_REGNO)
2121 (eq:P (match_dup 1)
2122 (const_int 0)))]
2123 ""
2124 "subfic %0,%1,0"
2125 [(set_attr "type" "add")])
2126
2127 (define_insn "*subf<mode>3_imm_carry_m1"
2128 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
2129 (not:P (match_operand:P 1 "gpc_reg_operand" "r")))
2130 (set (reg:P CA_REGNO)
2131 (const_int 1))]
2132 ""
2133 "subfic %0,%1,-1"
2134 [(set_attr "type" "add")])
2135
2136
2137 (define_expand "subf<mode>3_carry_in"
2138 [(parallel [
2139 (set (match_operand:GPR 0 "gpc_reg_operand")
2140 (plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand"))
2141 (reg:GPR CA_REGNO))
2142 (match_operand:GPR 2 "adde_operand")))
2143 (clobber (reg:GPR CA_REGNO))])]
2144 ""
2145 {
2146 if (operands[2] == const0_rtx)
2147 {
2148 emit_insn (gen_subf<mode>3_carry_in_0 (operands[0], operands[1]));
2149 DONE;
2150 }
2151 if (operands[2] == constm1_rtx)
2152 {
2153 emit_insn (gen_subf<mode>3_carry_in_m1 (operands[0], operands[1]));
2154 DONE;
2155 }
2156 })
2157
2158 (define_insn "*subf<mode>3_carry_in_internal"
2159 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2160 (plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
2161 (reg:GPR CA_REGNO))
2162 (match_operand:GPR 2 "gpc_reg_operand" "r")))
2163 (clobber (reg:GPR CA_REGNO))]
2164 ""
2165 "subfe %0,%1,%2"
2166 [(set_attr "type" "add")])
2167
2168 (define_insn "subf<mode>3_carry_in_0"
2169 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2170 (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
2171 (reg:GPR CA_REGNO)))
2172 (clobber (reg:GPR CA_REGNO))]
2173 ""
2174 "subfze %0,%1"
2175 [(set_attr "type" "add")])
2176
2177 (define_insn "subf<mode>3_carry_in_m1"
2178 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2179 (plus:GPR (minus:GPR (reg:GPR CA_REGNO)
2180 (match_operand:GPR 1 "gpc_reg_operand" "r"))
2181 (const_int -2)))
2182 (clobber (reg:GPR CA_REGNO))]
2183 ""
2184 "subfme %0,%1"
2185 [(set_attr "type" "add")])
2186
2187 (define_insn "subf<mode>3_carry_in_xx"
2188 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2189 (plus:GPR (reg:GPR CA_REGNO)
2190 (const_int -1)))
2191 (clobber (reg:GPR CA_REGNO))]
2192 ""
2193 "subfe %0,%0,%0"
2194 [(set_attr "type" "add")])
2195
2196
2197 (define_insn "neg<mode>2"
2198 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2199 (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
2200 ""
2201 "neg %0,%1"
2202 [(set_attr "type" "add")])
2203
2204 (define_insn_and_split "*neg<mode>2_dot"
2205 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
2206 (compare:CC (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
2207 (const_int 0)))
2208 (clobber (match_scratch:GPR 0 "=r,r"))]
2209 "<MODE>mode == Pmode"
2210 "@
2211 neg. %0,%1
2212 #"
2213 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
2214 [(set (match_dup 0)
2215 (neg:GPR (match_dup 1)))
2216 (set (match_dup 2)
2217 (compare:CC (match_dup 0)
2218 (const_int 0)))]
2219 ""
2220 [(set_attr "type" "add")
2221 (set_attr "dot" "yes")
2222 (set_attr "length" "4,8")])
2223
2224 (define_insn_and_split "*neg<mode>2_dot2"
2225 [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
2226 (compare:CC (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
2227 (const_int 0)))
2228 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
2229 (neg:GPR (match_dup 1)))]
2230 "<MODE>mode == Pmode"
2231 "@
2232 neg. %0,%1
2233 #"
2234 "&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
2235 [(set (match_dup 0)
2236 (neg:GPR (match_dup 1)))
2237 (set (match_dup 2)
2238 (compare:CC (match_dup 0)
2239 (const_int 0)))]
2240 ""
2241 [(set_attr "type" "add")
2242 (set_attr "dot" "yes")
2243 (set_attr "length" "4,8")])
2244
2245
2246 (define_insn "clz<mode>2"
2247 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2248 (clz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
2249 ""
2250 "cntlz<wd> %0,%1"
2251 [(set_attr "type" "cntlz")])
2252
2253 (define_expand "ctz<mode>2"
2254 [(set (match_operand:GPR 0 "gpc_reg_operand")
2255 (ctz:GPR (match_operand:GPR 1 "gpc_reg_operand")))]
2256 ""
2257 {
2258 if (TARGET_CTZ)
2259 {
2260 emit_insn (gen_ctz<mode>2_hw (operands[0], operands[1]));
2261 DONE;
2262 }
2263
2264 rtx tmp1 = gen_reg_rtx (<MODE>mode);
2265 rtx tmp2 = gen_reg_rtx (<MODE>mode);
2266 rtx tmp3 = gen_reg_rtx (<MODE>mode);
2267
2268 if (TARGET_POPCNTD)
2269 {
2270 emit_insn (gen_add<mode>3 (tmp1, operands[1], constm1_rtx));
2271 emit_insn (gen_one_cmpl<mode>2 (tmp2, operands[1]));
2272 emit_insn (gen_and<mode>3 (tmp3, tmp1, tmp2));
2273 emit_insn (gen_popcntd<mode>2 (operands[0], tmp3));
2274 }
2275 else
2276 {
2277 emit_insn (gen_neg<mode>2 (tmp1, operands[1]));
2278 emit_insn (gen_and<mode>3 (tmp2, operands[1], tmp1));
2279 emit_insn (gen_clz<mode>2 (tmp3, tmp2));
2280 emit_insn (gen_sub<mode>3 (operands[0], GEN_INT (<bits> - 1), tmp3));
2281 }
2282
2283 DONE;
2284 })
2285
2286 (define_insn "ctz<mode>2_hw"
2287 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2288 (ctz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
2289 "TARGET_CTZ"
2290 "cnttz<wd> %0,%1"
2291 [(set_attr "type" "cntlz")])
2292
2293 (define_expand "ffs<mode>2"
2294 [(set (match_operand:GPR 0 "gpc_reg_operand")
2295 (ffs:GPR (match_operand:GPR 1 "gpc_reg_operand")))]
2296 ""
2297 {
2298 rtx tmp1 = gen_reg_rtx (<MODE>mode);
2299 rtx tmp2 = gen_reg_rtx (<MODE>mode);
2300 rtx tmp3 = gen_reg_rtx (<MODE>mode);
2301 emit_insn (gen_neg<mode>2 (tmp1, operands[1]));
2302 emit_insn (gen_and<mode>3 (tmp2, operands[1], tmp1));
2303 emit_insn (gen_clz<mode>2 (tmp3, tmp2));
2304 emit_insn (gen_sub<mode>3 (operands[0], GEN_INT (<bits>), tmp3));
2305 DONE;
2306 })
2307
2308
2309 (define_expand "popcount<mode>2"
2310 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
2311 (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
2312 "TARGET_POPCNTB || TARGET_POPCNTD"
2313 {
2314 rs6000_emit_popcount (operands[0], operands[1]);
2315 DONE;
2316 })
2317
2318 (define_insn "popcntb<mode>2"
2319 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2320 (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
2321 UNSPEC_POPCNTB))]
2322 "TARGET_POPCNTB"
2323 "popcntb %0,%1"
2324 [(set_attr "type" "popcnt")])
2325
2326 (define_insn "popcntd<mode>2"
2327 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2328 (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
2329 "TARGET_POPCNTD"
2330 "popcnt<wd> %0,%1"
2331 [(set_attr "type" "popcnt")])
2332
2333
2334 (define_expand "parity<mode>2"
2335 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
2336 (parity:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
2337 "TARGET_POPCNTB"
2338 {
2339 rs6000_emit_parity (operands[0], operands[1]);
2340 DONE;
2341 })
2342
2343 (define_insn "parity<mode>2_cmpb"
2344 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2345 (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")] UNSPEC_PARITY))]
2346 "TARGET_CMPB && TARGET_POPCNTB"
2347 "prty<wd> %0,%1"
2348 [(set_attr "type" "popcnt")])
2349
2350 (define_insn "cmpb<mode>3"
2351 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2352 (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")
2353 (match_operand:GPR 2 "gpc_reg_operand" "r")] UNSPEC_CMPB))]
2354 "TARGET_CMPB"
2355 "cmpb %0,%1,%2"
2356 [(set_attr "type" "cmp")])
2357
2358 ;; Since the hardware zeros the upper part of the register, save generating the
2359 ;; AND immediate if we are converting to unsigned
2360 (define_insn "*bswap<mode>2_extenddi"
2361 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
2362 (zero_extend:DI
2363 (bswap:HSI (match_operand:HSI 1 "memory_operand" "Z"))))]
2364 "TARGET_POWERPC64"
2365 "l<wd>brx %0,%y1"
2366 [(set_attr "length" "4")
2367 (set_attr "type" "load")])
2368
2369 (define_insn "*bswaphi2_extendsi"
2370 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
2371 (zero_extend:SI
2372 (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
2373 ""
2374 "lhbrx %0,%y1"
2375 [(set_attr "length" "4")
2376 (set_attr "type" "load")])
2377
2378 ;; Separate the bswap patterns into load, store, and gpr<-gpr. This prevents
2379 ;; the register allocator from converting a gpr<-gpr swap into a store and then
2380 ;; load with byte swap, which can be slower than doing it in the registers. It
2381 ;; also prevents certain failures with the RELOAD register allocator.
2382
2383 (define_expand "bswap<mode>2"
2384 [(use (match_operand:HSI 0 "reg_or_mem_operand"))
2385 (use (match_operand:HSI 1 "reg_or_mem_operand"))]
2386 ""
2387 {
2388 rtx dest = operands[0];
2389 rtx src = operands[1];
2390
2391 if (!REG_P (dest) && !REG_P (src))
2392 src = force_reg (<MODE>mode, src);
2393
2394 if (MEM_P (src))
2395 emit_insn (gen_bswap<mode>2_load (dest, src));
2396 else if (MEM_P (dest))
2397 emit_insn (gen_bswap<mode>2_store (dest, src));
2398 else
2399 emit_insn (gen_bswap<mode>2_reg (dest, src));
2400 DONE;
2401 })
2402
2403 (define_insn "bswap<mode>2_load"
2404 [(set (match_operand:HSI 0 "gpc_reg_operand" "=r")
2405 (bswap:HSI (match_operand:HSI 1 "memory_operand" "Z")))]
2406 ""
2407 "l<wd>brx %0,%y1"
2408 [(set_attr "type" "load")])
2409
2410 (define_insn "bswap<mode>2_store"
2411 [(set (match_operand:HSI 0 "memory_operand" "=Z")
2412 (bswap:HSI (match_operand:HSI 1 "gpc_reg_operand" "r")))]
2413 ""
2414 "st<wd>brx %1,%y0"
2415 [(set_attr "type" "store")])
2416
2417 (define_insn_and_split "bswaphi2_reg"
2418 [(set (match_operand:HI 0 "gpc_reg_operand" "=&r")
2419 (bswap:HI
2420 (match_operand:HI 1 "gpc_reg_operand" "r")))
2421 (clobber (match_scratch:SI 2 "=&r"))]
2422 ""
2423 "#"
2424 "reload_completed"
2425 [(set (match_dup 3)
2426 (and:SI (lshiftrt:SI (match_dup 4)
2427 (const_int 8))
2428 (const_int 255)))
2429 (set (match_dup 2)
2430 (and:SI (ashift:SI (match_dup 4)
2431 (const_int 8))
2432 (const_int 65280))) ;; 0xff00
2433 (set (match_dup 3)
2434 (ior:SI (match_dup 3)
2435 (match_dup 2)))]
2436 {
2437 operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
2438 operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
2439 }
2440 [(set_attr "length" "12")
2441 (set_attr "type" "*")])
2442
2443 ;; We are always BITS_BIG_ENDIAN, so the bit positions below in
2444 ;; zero_extract insns do not change for -mlittle.
2445 (define_insn_and_split "bswapsi2_reg"
2446 [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
2447 (bswap:SI
2448 (match_operand:SI 1 "gpc_reg_operand" "r")))]
2449 ""
2450 "#"
2451 "reload_completed"
2452 [(set (match_dup 0) ; DABC
2453 (rotate:SI (match_dup 1)
2454 (const_int 24)))
2455 (set (match_dup 0) ; DCBC
2456 (ior:SI (and:SI (ashift:SI (match_dup 1)
2457 (const_int 8))
2458 (const_int 16711680))
2459 (and:SI (match_dup 0)
2460 (const_int -16711681))))
2461 (set (match_dup 0) ; DCBA
2462 (ior:SI (and:SI (lshiftrt:SI (match_dup 1)
2463 (const_int 24))
2464 (const_int 255))
2465 (and:SI (match_dup 0)
2466 (const_int -256))))]
2467 "")
2468
2469 ;; On systems with LDBRX/STDBRX generate the loads/stores directly, just like
2470 ;; we do for L{H,W}BRX and ST{H,W}BRX above. If not, we have to generate more
2471 ;; complex code.
2472
2473 (define_expand "bswapdi2"
2474 [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "")
2475 (bswap:DI
2476 (match_operand:DI 1 "reg_or_mem_operand" "")))
2477 (clobber (match_scratch:DI 2 ""))
2478 (clobber (match_scratch:DI 3 ""))])]
2479 ""
2480 {
2481 rtx dest = operands[0];
2482 rtx src = operands[1];
2483
2484 if (!REG_P (dest) && !REG_P (src))
2485 operands[1] = src = force_reg (DImode, src);
2486
2487 if (TARGET_POWERPC64 && TARGET_LDBRX)
2488 {
2489 if (MEM_P (src))
2490 emit_insn (gen_bswapdi2_load (dest, src));
2491 else if (MEM_P (dest))
2492 emit_insn (gen_bswapdi2_store (dest, src));
2493 else
2494 emit_insn (gen_bswapdi2_reg (dest, src));
2495 DONE;
2496 }
2497
2498 if (!TARGET_POWERPC64)
2499 {
2500 /* 32-bit mode needs fewer scratch registers, but 32-bit addressing mode
2501 that uses 64-bit registers needs the same scratch registers as 64-bit
2502 mode. */
2503 emit_insn (gen_bswapdi2_32bit (dest, src));
2504 DONE;
2505 }
2506 })
2507
2508 ;; Power7/cell has ldbrx/stdbrx, so use it directly
2509 (define_insn "bswapdi2_load"
2510 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
2511 (bswap:DI (match_operand:DI 1 "memory_operand" "Z")))]
2512 "TARGET_POWERPC64 && TARGET_LDBRX"
2513 "ldbrx %0,%y1"
2514 [(set_attr "type" "load")])
2515
2516 (define_insn "bswapdi2_store"
2517 [(set (match_operand:DI 0 "memory_operand" "=Z")
2518 (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
2519 "TARGET_POWERPC64 && TARGET_LDBRX"
2520 "stdbrx %1,%y0"
2521 [(set_attr "type" "store")])
2522
2523 (define_insn "bswapdi2_reg"
2524 [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
2525 (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
2526 (clobber (match_scratch:DI 2 "=&r"))
2527 (clobber (match_scratch:DI 3 "=&r"))]
2528 "TARGET_POWERPC64 && TARGET_LDBRX"
2529 "#"
2530 [(set_attr "length" "36")])
2531
2532 ;; Non-power7/cell, fall back to use lwbrx/stwbrx
2533 (define_insn "*bswapdi2_64bit"
2534 [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,Z,&r")
2535 (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
2536 (clobber (match_scratch:DI 2 "=&b,&b,&r"))
2537 (clobber (match_scratch:DI 3 "=&r,&r,&r"))]
2538 "TARGET_POWERPC64 && !TARGET_LDBRX
2539 && (REG_P (operands[0]) || REG_P (operands[1]))
2540 && !(MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2541 && !(MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))"
2542 "#"
2543 [(set_attr "length" "16,12,36")])
2544
2545 (define_split
2546 [(set (match_operand:DI 0 "gpc_reg_operand" "")
2547 (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
2548 (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
2549 (clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
2550 "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
2551 [(const_int 0)]
2552 "
2553 {
2554 rtx dest = operands[0];
2555 rtx src = operands[1];
2556 rtx op2 = operands[2];
2557 rtx op3 = operands[3];
2558 rtx op3_32 = simplify_gen_subreg (SImode, op3, DImode,
2559 BYTES_BIG_ENDIAN ? 4 : 0);
2560 rtx dest_32 = simplify_gen_subreg (SImode, dest, DImode,
2561 BYTES_BIG_ENDIAN ? 4 : 0);
2562 rtx addr1;
2563 rtx addr2;
2564 rtx word1;
2565 rtx word2;
2566
2567 addr1 = XEXP (src, 0);
2568 if (GET_CODE (addr1) == PLUS)
2569 {
2570 emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
2571 if (TARGET_AVOID_XFORM)
2572 {
2573 emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
2574 addr2 = op2;
2575 }
2576 else
2577 addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1));
2578 }
2579 else if (TARGET_AVOID_XFORM)
2580 {
2581 emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
2582 addr2 = op2;
2583 }
2584 else
2585 {
2586 emit_move_insn (op2, GEN_INT (4));
2587 addr2 = gen_rtx_PLUS (Pmode, op2, addr1);
2588 }
2589
2590 word1 = change_address (src, SImode, addr1);
2591 word2 = change_address (src, SImode, addr2);
2592
2593 if (BYTES_BIG_ENDIAN)
2594 {
2595 emit_insn (gen_bswapsi2 (op3_32, word2));
2596 emit_insn (gen_bswapsi2 (dest_32, word1));
2597 }
2598 else
2599 {
2600 emit_insn (gen_bswapsi2 (op3_32, word1));
2601 emit_insn (gen_bswapsi2 (dest_32, word2));
2602 }
2603
2604 emit_insn (gen_ashldi3 (op3, op3, GEN_INT (32)));
2605 emit_insn (gen_iordi3 (dest, dest, op3));
2606 DONE;
2607 }")
2608
2609 (define_split
2610 [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
2611 (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
2612 (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
2613 (clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
2614 "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
2615 [(const_int 0)]
2616 "
2617 {
2618 rtx dest = operands[0];
2619 rtx src = operands[1];
2620 rtx op2 = operands[2];
2621 rtx op3 = operands[3];
2622 rtx src_si = simplify_gen_subreg (SImode, src, DImode,
2623 BYTES_BIG_ENDIAN ? 4 : 0);
2624 rtx op3_si = simplify_gen_subreg (SImode, op3, DImode,
2625 BYTES_BIG_ENDIAN ? 4 : 0);
2626 rtx addr1;
2627 rtx addr2;
2628 rtx word1;
2629 rtx word2;
2630
2631 addr1 = XEXP (dest, 0);
2632 if (GET_CODE (addr1) == PLUS)
2633 {
2634 emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
2635 if (TARGET_AVOID_XFORM)
2636 {
2637 emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
2638 addr2 = op2;
2639 }
2640 else
2641 addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1));
2642 }
2643 else if (TARGET_AVOID_XFORM)
2644 {
2645 emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
2646 addr2 = op2;
2647 }
2648 else
2649 {
2650 emit_move_insn (op2, GEN_INT (4));
2651 addr2 = gen_rtx_PLUS (Pmode, op2, addr1);
2652 }
2653
2654 word1 = change_address (dest, SImode, addr1);
2655 word2 = change_address (dest, SImode, addr2);
2656
2657 emit_insn (gen_lshrdi3 (op3, src, GEN_INT (32)));
2658
2659 if (BYTES_BIG_ENDIAN)
2660 {
2661 emit_insn (gen_bswapsi2 (word1, src_si));
2662 emit_insn (gen_bswapsi2 (word2, op3_si));
2663 }
2664 else
2665 {
2666 emit_insn (gen_bswapsi2 (word2, src_si));
2667 emit_insn (gen_bswapsi2 (word1, op3_si));
2668 }
2669 DONE;
2670 }")
2671
2672 (define_split
2673 [(set (match_operand:DI 0 "gpc_reg_operand" "")
2674 (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
2675 (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
2676 (clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
2677 "TARGET_POWERPC64 && reload_completed"
2678 [(const_int 0)]
2679 "
2680 {
2681 rtx dest = operands[0];
2682 rtx src = operands[1];
2683 rtx op2 = operands[2];
2684 rtx op3 = operands[3];
2685 int lo_off = BYTES_BIG_ENDIAN ? 4 : 0;
2686 rtx dest_si = simplify_gen_subreg (SImode, dest, DImode, lo_off);
2687 rtx src_si = simplify_gen_subreg (SImode, src, DImode, lo_off);
2688 rtx op2_si = simplify_gen_subreg (SImode, op2, DImode, lo_off);
2689 rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, lo_off);
2690
2691 emit_insn (gen_lshrdi3 (op2, src, GEN_INT (32)));
2692 emit_insn (gen_bswapsi2 (dest_si, src_si));
2693 emit_insn (gen_bswapsi2 (op3_si, op2_si));
2694 emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32)));
2695 emit_insn (gen_iordi3 (dest, dest, op3));
2696 DONE;
2697 }")
2698
2699 (define_insn "bswapdi2_32bit"
2700 [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,Z,?&r")
2701 (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
2702 (clobber (match_scratch:SI 2 "=&b,&b,X"))]
2703 "!TARGET_POWERPC64 && (REG_P (operands[0]) || REG_P (operands[1]))"
2704 "#"
2705 [(set_attr "length" "16,12,36")])
2706
2707 (define_split
2708 [(set (match_operand:DI 0 "gpc_reg_operand" "")
2709 (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
2710 (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
2711 "!TARGET_POWERPC64 && reload_completed"
2712 [(const_int 0)]
2713 "
2714 {
2715 rtx dest = operands[0];
2716 rtx src = operands[1];
2717 rtx op2 = operands[2];
2718 rtx dest1 = simplify_gen_subreg (SImode, dest, DImode, 0);
2719 rtx dest2 = simplify_gen_subreg (SImode, dest, DImode, 4);
2720 rtx addr1;
2721 rtx addr2;
2722 rtx word1;
2723 rtx word2;
2724
2725 addr1 = XEXP (src, 0);
2726 if (GET_CODE (addr1) == PLUS)
2727 {
2728 emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
2729 if (TARGET_AVOID_XFORM
2730 || REGNO (XEXP (addr1, 1)) == REGNO (dest2))
2731 {
2732 emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
2733 addr2 = op2;
2734 }
2735 else
2736 addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1));
2737 }
2738 else if (TARGET_AVOID_XFORM
2739 || REGNO (addr1) == REGNO (dest2))
2740 {
2741 emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
2742 addr2 = op2;
2743 }
2744 else
2745 {
2746 emit_move_insn (op2, GEN_INT (4));
2747 addr2 = gen_rtx_PLUS (SImode, op2, addr1);
2748 }
2749
2750 word1 = change_address (src, SImode, addr1);
2751 word2 = change_address (src, SImode, addr2);
2752
2753 emit_insn (gen_bswapsi2 (dest2, word1));
2754 /* The REGNO (dest2) tests above ensure that addr2 has not been trashed,
2755 thus allowing us to omit an early clobber on the output. */
2756 emit_insn (gen_bswapsi2 (dest1, word2));
2757 DONE;
2758 }")
2759
2760 (define_split
2761 [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
2762 (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
2763 (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
2764 "!TARGET_POWERPC64 && reload_completed"
2765 [(const_int 0)]
2766 "
2767 {
2768 rtx dest = operands[0];
2769 rtx src = operands[1];
2770 rtx op2 = operands[2];
2771 rtx src1 = simplify_gen_subreg (SImode, src, DImode, 0);
2772 rtx src2 = simplify_gen_subreg (SImode, src, DImode, 4);
2773 rtx addr1;
2774 rtx addr2;
2775 rtx word1;
2776 rtx word2;
2777
2778 addr1 = XEXP (dest, 0);
2779 if (GET_CODE (addr1) == PLUS)
2780 {
2781 emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
2782 if (TARGET_AVOID_XFORM)
2783 {
2784 emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
2785 addr2 = op2;
2786 }
2787 else
2788 addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1));
2789 }
2790 else if (TARGET_AVOID_XFORM)
2791 {
2792 emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
2793 addr2 = op2;
2794 }
2795 else
2796 {
2797 emit_move_insn (op2, GEN_INT (4));
2798 addr2 = gen_rtx_PLUS (SImode, op2, addr1);
2799 }
2800
2801 word1 = change_address (dest, SImode, addr1);
2802 word2 = change_address (dest, SImode, addr2);
2803
2804 emit_insn (gen_bswapsi2 (word2, src1));
2805 emit_insn (gen_bswapsi2 (word1, src2));
2806 DONE;
2807 }")
2808
2809 (define_split
2810 [(set (match_operand:DI 0 "gpc_reg_operand" "")
2811 (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
2812 (clobber (match_operand:SI 2 "" ""))]
2813 "!TARGET_POWERPC64 && reload_completed"
2814 [(const_int 0)]
2815 "
2816 {
2817 rtx dest = operands[0];
2818 rtx src = operands[1];
2819 rtx src1 = simplify_gen_subreg (SImode, src, DImode, 0);
2820 rtx src2 = simplify_gen_subreg (SImode, src, DImode, 4);
2821 rtx dest1 = simplify_gen_subreg (SImode, dest, DImode, 0);
2822 rtx dest2 = simplify_gen_subreg (SImode, dest, DImode, 4);
2823
2824 emit_insn (gen_bswapsi2 (dest1, src2));
2825 emit_insn (gen_bswapsi2 (dest2, src1));
2826 DONE;
2827 }")
2828
2829
2830 (define_insn "mul<mode>3"
2831 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
2832 (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
2833 (match_operand:GPR 2 "reg_or_short_operand" "r,I")))]
2834 ""
2835 "@
2836 mull<wd> %0,%1,%2
2837 mulli %0,%1,%2"
2838 [(set_attr "type" "mul")
2839 (set (attr "size")
2840 (cond [(match_operand:GPR 2 "s8bit_cint_operand" "")
2841 (const_string "8")
2842 (match_operand:GPR 2 "short_cint_operand" "")
2843 (const_string "16")]
2844 (const_string "<bits>")))])
2845
2846 (define_insn_and_split "*mul<mode>3_dot"
2847 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
2848 (compare:CC (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
2849 (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
2850 (const_int 0)))
2851 (clobber (match_scratch:GPR 0 "=r,r"))]
2852 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
2853 "@
2854 mull<wd>. %0,%1,%2
2855 #"
2856 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
2857 [(set (match_dup 0)
2858 (mult:GPR (match_dup 1)
2859 (match_dup 2)))
2860 (set (match_dup 3)
2861 (compare:CC (match_dup 0)
2862 (const_int 0)))]
2863 ""
2864 [(set_attr "type" "mul")
2865 (set_attr "size" "<bits>")
2866 (set_attr "dot" "yes")
2867 (set_attr "length" "4,8")])
2868
2869 (define_insn_and_split "*mul<mode>3_dot2"
2870 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
2871 (compare:CC (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
2872 (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
2873 (const_int 0)))
2874 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
2875 (mult:GPR (match_dup 1)
2876 (match_dup 2)))]
2877 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
2878 "@
2879 mull<wd>. %0,%1,%2
2880 #"
2881 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
2882 [(set (match_dup 0)
2883 (mult:GPR (match_dup 1)
2884 (match_dup 2)))
2885 (set (match_dup 3)
2886 (compare:CC (match_dup 0)
2887 (const_int 0)))]
2888 ""
2889 [(set_attr "type" "mul")
2890 (set_attr "size" "<bits>")
2891 (set_attr "dot" "yes")
2892 (set_attr "length" "4,8")])
2893
2894
2895 (define_expand "<su>mul<mode>3_highpart"
2896 [(set (match_operand:GPR 0 "gpc_reg_operand")
2897 (subreg:GPR
2898 (mult:<DMODE> (any_extend:<DMODE>
2899 (match_operand:GPR 1 "gpc_reg_operand"))
2900 (any_extend:<DMODE>
2901 (match_operand:GPR 2 "gpc_reg_operand")))
2902 0))]
2903 ""
2904 {
2905 if (<MODE>mode == SImode && TARGET_POWERPC64)
2906 {
2907 emit_insn (gen_<su>mulsi3_highpart_64 (operands[0], operands[1],
2908 operands[2]));
2909 DONE;
2910 }
2911
2912 if (!WORDS_BIG_ENDIAN)
2913 {
2914 emit_insn (gen_<su>mul<mode>3_highpart_le (operands[0], operands[1],
2915 operands[2]));
2916 DONE;
2917 }
2918 })
2919
2920 (define_insn "*<su>mul<mode>3_highpart"
2921 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2922 (subreg:GPR
2923 (mult:<DMODE> (any_extend:<DMODE>
2924 (match_operand:GPR 1 "gpc_reg_operand" "r"))
2925 (any_extend:<DMODE>
2926 (match_operand:GPR 2 "gpc_reg_operand" "r")))
2927 0))]
2928 "WORDS_BIG_ENDIAN && !(<MODE>mode == SImode && TARGET_POWERPC64)"
2929 "mulh<wd><u> %0,%1,%2"
2930 [(set_attr "type" "mul")
2931 (set_attr "size" "<bits>")])
2932
2933 (define_insn "<su>mulsi3_highpart_le"
2934 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
2935 (subreg:SI
2936 (mult:DI (any_extend:DI
2937 (match_operand:SI 1 "gpc_reg_operand" "r"))
2938 (any_extend:DI
2939 (match_operand:SI 2 "gpc_reg_operand" "r")))
2940 4))]
2941 "!WORDS_BIG_ENDIAN && !TARGET_POWERPC64"
2942 "mulhw<u> %0,%1,%2"
2943 [(set_attr "type" "mul")])
2944
2945 (define_insn "<su>muldi3_highpart_le"
2946 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
2947 (subreg:DI
2948 (mult:TI (any_extend:TI
2949 (match_operand:DI 1 "gpc_reg_operand" "r"))
2950 (any_extend:TI
2951 (match_operand:DI 2 "gpc_reg_operand" "r")))
2952 8))]
2953 "!WORDS_BIG_ENDIAN && TARGET_POWERPC64"
2954 "mulhd<u> %0,%1,%2"
2955 [(set_attr "type" "mul")
2956 (set_attr "size" "64")])
2957
2958 (define_insn "<su>mulsi3_highpart_64"
2959 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
2960 (truncate:SI
2961 (lshiftrt:DI
2962 (mult:DI (any_extend:DI
2963 (match_operand:SI 1 "gpc_reg_operand" "r"))
2964 (any_extend:DI
2965 (match_operand:SI 2 "gpc_reg_operand" "r")))
2966 (const_int 32))))]
2967 "TARGET_POWERPC64"
2968 "mulhw<u> %0,%1,%2"
2969 [(set_attr "type" "mul")])
2970
2971 (define_expand "<u>mul<mode><dmode>3"
2972 [(set (match_operand:<DMODE> 0 "gpc_reg_operand")
2973 (mult:<DMODE> (any_extend:<DMODE>
2974 (match_operand:GPR 1 "gpc_reg_operand"))
2975 (any_extend:<DMODE>
2976 (match_operand:GPR 2 "gpc_reg_operand"))))]
2977 "!(<MODE>mode == SImode && TARGET_POWERPC64)"
2978 {
2979 rtx l = gen_reg_rtx (<MODE>mode);
2980 rtx h = gen_reg_rtx (<MODE>mode);
2981 emit_insn (gen_mul<mode>3 (l, operands[1], operands[2]));
2982 emit_insn (gen_<su>mul<mode>3_highpart (h, operands[1], operands[2]));
2983 emit_move_insn (gen_lowpart (<MODE>mode, operands[0]), l);
2984 emit_move_insn (gen_highpart (<MODE>mode, operands[0]), h);
2985 DONE;
2986 })
2987
2988 (define_insn "*maddld4"
2989 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
2990 (plus:DI (mult:DI (match_operand:DI 1 "gpc_reg_operand" "r")
2991 (match_operand:DI 2 "gpc_reg_operand" "r"))
2992 (match_operand:DI 3 "gpc_reg_operand" "r")))]
2993 "TARGET_MADDLD"
2994 "maddld %0,%1,%2,%3"
2995 [(set_attr "type" "mul")])
2996
2997 (define_insn "udiv<mode>3"
2998 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
2999 (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3000 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
3001 ""
3002 "div<wd>u %0,%1,%2"
3003 [(set_attr "type" "div")
3004 (set_attr "size" "<bits>")])
3005
3006
3007 ;; For powers of two we can do sra[wd]i/addze for divide and then adjust for
3008 ;; modulus. If it isn't a power of two, force operands into register and do
3009 ;; a normal divide.
3010 (define_expand "div<mode>3"
3011 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
3012 (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
3013 (match_operand:GPR 2 "reg_or_cint_operand" "")))]
3014 ""
3015 {
3016 if (CONST_INT_P (operands[2])
3017 && INTVAL (operands[2]) > 0
3018 && exact_log2 (INTVAL (operands[2])) >= 0)
3019 {
3020 emit_insn (gen_div<mode>3_sra (operands[0], operands[1], operands[2]));
3021 DONE;
3022 }
3023
3024 operands[2] = force_reg (<MODE>mode, operands[2]);
3025 })
3026
3027 (define_insn "*div<mode>3"
3028 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3029 (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3030 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
3031 ""
3032 "div<wd> %0,%1,%2"
3033 [(set_attr "type" "div")
3034 (set_attr "size" "<bits>")])
3035
3036 (define_insn "div<mode>3_sra"
3037 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3038 (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3039 (match_operand:GPR 2 "exact_log2_cint_operand" "N")))
3040 (clobber (reg:GPR CA_REGNO))]
3041 ""
3042 "sra<wd>i %0,%1,%p2\;addze %0,%0"
3043 [(set_attr "type" "two")
3044 (set_attr "length" "8")])
3045
3046 (define_insn_and_split "*div<mode>3_sra_dot"
3047 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
3048 (compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
3049 (match_operand:GPR 2 "exact_log2_cint_operand" "N,N"))
3050 (const_int 0)))
3051 (clobber (match_scratch:GPR 0 "=r,r"))
3052 (clobber (reg:GPR CA_REGNO))]
3053 "<MODE>mode == Pmode"
3054 "@
3055 sra<wd>i %0,%1,%p2\;addze. %0,%0
3056 #"
3057 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3058 [(parallel [(set (match_dup 0)
3059 (div:GPR (match_dup 1)
3060 (match_dup 2)))
3061 (clobber (reg:GPR CA_REGNO))])
3062 (set (match_dup 3)
3063 (compare:CC (match_dup 0)
3064 (const_int 0)))]
3065 ""
3066 [(set_attr "type" "two")
3067 (set_attr "length" "8,12")
3068 (set_attr "cell_micro" "not")])
3069
3070 (define_insn_and_split "*div<mode>3_sra_dot2"
3071 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
3072 (compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
3073 (match_operand:GPR 2 "exact_log2_cint_operand" "N,N"))
3074 (const_int 0)))
3075 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3076 (div:GPR (match_dup 1)
3077 (match_dup 2)))
3078 (clobber (reg:GPR CA_REGNO))]
3079 "<MODE>mode == Pmode"
3080 "@
3081 sra<wd>i %0,%1,%p2\;addze. %0,%0
3082 #"
3083 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3084 [(parallel [(set (match_dup 0)
3085 (div:GPR (match_dup 1)
3086 (match_dup 2)))
3087 (clobber (reg:GPR CA_REGNO))])
3088 (set (match_dup 3)
3089 (compare:CC (match_dup 0)
3090 (const_int 0)))]
3091 ""
3092 [(set_attr "type" "two")
3093 (set_attr "length" "8,12")
3094 (set_attr "cell_micro" "not")])
3095
3096 (define_expand "mod<mode>3"
3097 [(set (match_operand:GPR 0 "gpc_reg_operand")
3098 (mod:GPR (match_operand:GPR 1 "gpc_reg_operand")
3099 (match_operand:GPR 2 "reg_or_cint_operand")))]
3100 ""
3101 {
3102 int i;
3103 rtx temp1;
3104 rtx temp2;
3105
3106 if (GET_CODE (operands[2]) != CONST_INT
3107 || INTVAL (operands[2]) <= 0
3108 || (i = exact_log2 (INTVAL (operands[2]))) < 0)
3109 {
3110 if (!TARGET_MODULO)
3111 FAIL;
3112
3113 operands[2] = force_reg (<MODE>mode, operands[2]);
3114 }
3115 else
3116 {
3117 temp1 = gen_reg_rtx (<MODE>mode);
3118 temp2 = gen_reg_rtx (<MODE>mode);
3119
3120 emit_insn (gen_div<mode>3 (temp1, operands[1], operands[2]));
3121 emit_insn (gen_ashl<mode>3 (temp2, temp1, GEN_INT (i)));
3122 emit_insn (gen_sub<mode>3 (operands[0], operands[1], temp2));
3123 DONE;
3124 }
3125 })
3126
3127 ;; In order to enable using a peephole2 for combining div/mod to eliminate the
3128 ;; mod, prefer putting the result of mod into a different register
3129 (define_insn "*mod<mode>3"
3130 [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
3131 (mod:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3132 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
3133 "TARGET_MODULO"
3134 "mods<wd> %0,%1,%2"
3135 [(set_attr "type" "div")
3136 (set_attr "size" "<bits>")])
3137
3138
3139 (define_insn "umod<mode>3"
3140 [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
3141 (umod:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3142 (match_operand:GPR 2 "gpc_reg_operand" "r")))]
3143 "TARGET_MODULO"
3144 "modu<wd> %0,%1,%2"
3145 [(set_attr "type" "div")
3146 (set_attr "size" "<bits>")])
3147
3148 ;; On machines with modulo support, do a combined div/mod the old fashioned
3149 ;; method, since the multiply/subtract is faster than doing the mod instruction
3150 ;; after a divide.
3151
3152 (define_peephole2
3153 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
3154 (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
3155 (match_operand:GPR 2 "gpc_reg_operand" "")))
3156 (set (match_operand:GPR 3 "gpc_reg_operand" "")
3157 (mod:GPR (match_dup 1)
3158 (match_dup 2)))]
3159 "TARGET_MODULO
3160 && ! reg_mentioned_p (operands[0], operands[1])
3161 && ! reg_mentioned_p (operands[0], operands[2])
3162 && ! reg_mentioned_p (operands[3], operands[1])
3163 && ! reg_mentioned_p (operands[3], operands[2])"
3164 [(set (match_dup 0)
3165 (div:GPR (match_dup 1)
3166 (match_dup 2)))
3167 (set (match_dup 3)
3168 (mult:GPR (match_dup 0)
3169 (match_dup 2)))
3170 (set (match_dup 3)
3171 (minus:GPR (match_dup 1)
3172 (match_dup 3)))])
3173
3174 (define_peephole2
3175 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
3176 (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
3177 (match_operand:GPR 2 "gpc_reg_operand" "")))
3178 (set (match_operand:GPR 3 "gpc_reg_operand" "")
3179 (umod:GPR (match_dup 1)
3180 (match_dup 2)))]
3181 "TARGET_MODULO
3182 && ! reg_mentioned_p (operands[0], operands[1])
3183 && ! reg_mentioned_p (operands[0], operands[2])
3184 && ! reg_mentioned_p (operands[3], operands[1])
3185 && ! reg_mentioned_p (operands[3], operands[2])"
3186 [(set (match_dup 0)
3187 (udiv:GPR (match_dup 1)
3188 (match_dup 2)))
3189 (set (match_dup 3)
3190 (mult:GPR (match_dup 0)
3191 (match_dup 2)))
3192 (set (match_dup 3)
3193 (minus:GPR (match_dup 1)
3194 (match_dup 3)))])
3195
3196 \f
3197 ;; Logical instructions
3198 ;; The logical instructions are mostly combined by using match_operator,
3199 ;; but the plain AND insns are somewhat different because there is no
3200 ;; plain 'andi' (only 'andi.'), no plain 'andis', and there are all
3201 ;; those rotate-and-mask operations. Thus, the AND insns come first.
3202
3203 (define_expand "and<mode>3"
3204 [(set (match_operand:SDI 0 "gpc_reg_operand" "")
3205 (and:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
3206 (match_operand:SDI 2 "reg_or_cint_operand" "")))]
3207 ""
3208 {
3209 if (<MODE>mode == DImode && !TARGET_POWERPC64)
3210 {
3211 rs6000_split_logical (operands, AND, false, false, false);
3212 DONE;
3213 }
3214
3215 if (CONST_INT_P (operands[2]))
3216 {
3217 if (rs6000_is_valid_and_mask (operands[2], <MODE>mode))
3218 {
3219 emit_insn (gen_and<mode>3_mask (operands[0], operands[1], operands[2]));
3220 DONE;
3221 }
3222
3223 if (logical_const_operand (operands[2], <MODE>mode)
3224 && rs6000_gen_cell_microcode)
3225 {
3226 emit_insn (gen_and<mode>3_imm (operands[0], operands[1], operands[2]));
3227 DONE;
3228 }
3229
3230 if (rs6000_is_valid_2insn_and (operands[2], <MODE>mode))
3231 {
3232 rs6000_emit_2insn_and (<MODE>mode, operands, true, 0);
3233 DONE;
3234 }
3235
3236 operands[2] = force_reg (<MODE>mode, operands[2]);
3237 }
3238 })
3239
3240
3241 (define_insn "and<mode>3_imm"
3242 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3243 (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
3244 (match_operand:GPR 2 "logical_const_operand" "n")))
3245 (clobber (match_scratch:CC 3 "=x"))]
3246 "rs6000_gen_cell_microcode
3247 && !rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3248 "andi%e2. %0,%1,%u2"
3249 [(set_attr "type" "logical")
3250 (set_attr "dot" "yes")])
3251
3252 (define_insn_and_split "*and<mode>3_imm_dot"
3253 [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
3254 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3255 (match_operand:GPR 2 "logical_const_operand" "n,n"))
3256 (const_int 0)))
3257 (clobber (match_scratch:GPR 0 "=r,r"))
3258 (clobber (match_scratch:CC 4 "=X,x"))]
3259 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3260 && rs6000_gen_cell_microcode
3261 && !rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3262 "@
3263 andi%e2. %0,%1,%u2
3264 #"
3265 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3266 [(parallel [(set (match_dup 0)
3267 (and:GPR (match_dup 1)
3268 (match_dup 2)))
3269 (clobber (match_dup 4))])
3270 (set (match_dup 3)
3271 (compare:CC (match_dup 0)
3272 (const_int 0)))]
3273 ""
3274 [(set_attr "type" "logical")
3275 (set_attr "dot" "yes")
3276 (set_attr "length" "4,8")])
3277
3278 (define_insn_and_split "*and<mode>3_imm_dot2"
3279 [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
3280 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3281 (match_operand:GPR 2 "logical_const_operand" "n,n"))
3282 (const_int 0)))
3283 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3284 (and:GPR (match_dup 1)
3285 (match_dup 2)))
3286 (clobber (match_scratch:CC 4 "=X,x"))]
3287 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3288 && rs6000_gen_cell_microcode
3289 && !rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3290 "@
3291 andi%e2. %0,%1,%u2
3292 #"
3293 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3294 [(parallel [(set (match_dup 0)
3295 (and:GPR (match_dup 1)
3296 (match_dup 2)))
3297 (clobber (match_dup 4))])
3298 (set (match_dup 3)
3299 (compare:CC (match_dup 0)
3300 (const_int 0)))]
3301 ""
3302 [(set_attr "type" "logical")
3303 (set_attr "dot" "yes")
3304 (set_attr "length" "4,8")])
3305
3306 (define_insn_and_split "*and<mode>3_imm_mask_dot"
3307 [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
3308 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3309 (match_operand:GPR 2 "logical_const_operand" "n,n"))
3310 (const_int 0)))
3311 (clobber (match_scratch:GPR 0 "=r,r"))]
3312 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3313 && rs6000_gen_cell_microcode
3314 && rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3315 "@
3316 andi%e2. %0,%1,%u2
3317 #"
3318 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3319 [(set (match_dup 0)
3320 (and:GPR (match_dup 1)
3321 (match_dup 2)))
3322 (set (match_dup 3)
3323 (compare:CC (match_dup 0)
3324 (const_int 0)))]
3325 ""
3326 [(set_attr "type" "logical")
3327 (set_attr "dot" "yes")
3328 (set_attr "length" "4,8")])
3329
3330 (define_insn_and_split "*and<mode>3_imm_mask_dot2"
3331 [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
3332 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3333 (match_operand:GPR 2 "logical_const_operand" "n,n"))
3334 (const_int 0)))
3335 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3336 (and:GPR (match_dup 1)
3337 (match_dup 2)))]
3338 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3339 && rs6000_gen_cell_microcode
3340 && rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3341 "@
3342 andi%e2. %0,%1,%u2
3343 #"
3344 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3345 [(set (match_dup 0)
3346 (and:GPR (match_dup 1)
3347 (match_dup 2)))
3348 (set (match_dup 3)
3349 (compare:CC (match_dup 0)
3350 (const_int 0)))]
3351 ""
3352 [(set_attr "type" "logical")
3353 (set_attr "dot" "yes")
3354 (set_attr "length" "4,8")])
3355
3356 (define_insn "*and<mode>3_imm_dot_shifted"
3357 [(set (match_operand:CC 3 "cc_reg_operand" "=x")
3358 (compare:CC
3359 (and:GPR
3360 (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
3361 (match_operand:SI 4 "const_int_operand" "n"))
3362 (match_operand:GPR 2 "const_int_operand" "n"))
3363 (const_int 0)))
3364 (clobber (match_scratch:GPR 0 "=r"))]
3365 "logical_const_operand (GEN_INT (UINTVAL (operands[2])
3366 << INTVAL (operands[4])),
3367 DImode)
3368 && (<MODE>mode == Pmode
3369 || (UINTVAL (operands[2]) << INTVAL (operands[4])) <= 0x7fffffff)
3370 && rs6000_gen_cell_microcode"
3371 {
3372 operands[2] = GEN_INT (UINTVAL (operands[2]) << INTVAL (operands[4]));
3373 return "andi%e2. %0,%1,%u2";
3374 }
3375 [(set_attr "type" "logical")
3376 (set_attr "dot" "yes")])
3377
3378
3379 (define_insn "and<mode>3_mask"
3380 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3381 (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
3382 (match_operand:GPR 2 "const_int_operand" "n")))]
3383 "rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3384 {
3385 return rs6000_insn_for_and_mask (<MODE>mode, operands, false);
3386 }
3387 [(set_attr "type" "shift")])
3388
3389 (define_insn_and_split "*and<mode>3_mask_dot"
3390 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
3391 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3392 (match_operand:GPR 2 "const_int_operand" "n,n"))
3393 (const_int 0)))
3394 (clobber (match_scratch:GPR 0 "=r,r"))]
3395 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3396 && rs6000_gen_cell_microcode
3397 && !logical_const_operand (operands[2], <MODE>mode)
3398 && rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3399 {
3400 if (which_alternative == 0)
3401 return rs6000_insn_for_and_mask (<MODE>mode, operands, true);
3402 else
3403 return "#";
3404 }
3405 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3406 [(set (match_dup 0)
3407 (and:GPR (match_dup 1)
3408 (match_dup 2)))
3409 (set (match_dup 3)
3410 (compare:CC (match_dup 0)
3411 (const_int 0)))]
3412 ""
3413 [(set_attr "type" "shift")
3414 (set_attr "dot" "yes")
3415 (set_attr "length" "4,8")])
3416
3417 (define_insn_and_split "*and<mode>3_mask_dot2"
3418 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
3419 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3420 (match_operand:GPR 2 "const_int_operand" "n,n"))
3421 (const_int 0)))
3422 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3423 (and:GPR (match_dup 1)
3424 (match_dup 2)))]
3425 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3426 && rs6000_gen_cell_microcode
3427 && !logical_const_operand (operands[2], <MODE>mode)
3428 && rs6000_is_valid_and_mask (operands[2], <MODE>mode)"
3429 {
3430 if (which_alternative == 0)
3431 return rs6000_insn_for_and_mask (<MODE>mode, operands, true);
3432 else
3433 return "#";
3434 }
3435 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
3436 [(set (match_dup 0)
3437 (and:GPR (match_dup 1)
3438 (match_dup 2)))
3439 (set (match_dup 3)
3440 (compare:CC (match_dup 0)
3441 (const_int 0)))]
3442 ""
3443 [(set_attr "type" "shift")
3444 (set_attr "dot" "yes")
3445 (set_attr "length" "4,8")])
3446
3447
3448 (define_insn_and_split "*and<mode>3_2insn"
3449 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3450 (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
3451 (match_operand:GPR 2 "const_int_operand" "n")))]
3452 "rs6000_is_valid_2insn_and (operands[2], <MODE>mode)
3453 && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode)
3454 || (logical_const_operand (operands[2], <MODE>mode)
3455 && rs6000_gen_cell_microcode))"
3456 "#"
3457 "&& 1"
3458 [(pc)]
3459 {
3460 rs6000_emit_2insn_and (<MODE>mode, operands, false, 0);
3461 DONE;
3462 }
3463 [(set_attr "type" "shift")
3464 (set_attr "length" "8")])
3465
3466 (define_insn_and_split "*and<mode>3_2insn_dot"
3467 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
3468 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3469 (match_operand:GPR 2 "const_int_operand" "n,n"))
3470 (const_int 0)))
3471 (clobber (match_scratch:GPR 0 "=r,r"))]
3472 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3473 && rs6000_gen_cell_microcode
3474 && rs6000_is_valid_2insn_and (operands[2], <MODE>mode)
3475 && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode)
3476 || (logical_const_operand (operands[2], <MODE>mode)
3477 && rs6000_gen_cell_microcode))"
3478 "#"
3479 "&& reload_completed"
3480 [(pc)]
3481 {
3482 rs6000_emit_2insn_and (<MODE>mode, operands, false, 1);
3483 DONE;
3484 }
3485 [(set_attr "type" "shift")
3486 (set_attr "dot" "yes")
3487 (set_attr "length" "8,12")])
3488
3489 (define_insn_and_split "*and<mode>3_2insn_dot2"
3490 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
3491 (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
3492 (match_operand:GPR 2 "const_int_operand" "n,n"))
3493 (const_int 0)))
3494 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3495 (and:GPR (match_dup 1)
3496 (match_dup 2)))]
3497 "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
3498 && rs6000_gen_cell_microcode
3499 && rs6000_is_valid_2insn_and (operands[2], <MODE>mode)
3500 && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode)
3501 || (logical_const_operand (operands[2], <MODE>mode)
3502 && rs6000_gen_cell_microcode))"
3503 "#"
3504 "&& reload_completed"
3505 [(pc)]
3506 {
3507 rs6000_emit_2insn_and (<MODE>mode, operands, false, 2);
3508 DONE;
3509 }
3510 [(set_attr "type" "shift")
3511 (set_attr "dot" "yes")
3512 (set_attr "length" "8,12")])
3513
3514
3515 (define_expand "<code><mode>3"
3516 [(set (match_operand:SDI 0 "gpc_reg_operand" "")
3517 (iorxor:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
3518 (match_operand:SDI 2 "reg_or_cint_operand" "")))]
3519 ""
3520 {
3521 if (<MODE>mode == DImode && !TARGET_POWERPC64)
3522 {
3523 rs6000_split_logical (operands, <CODE>, false, false, false);
3524 DONE;
3525 }
3526
3527 if (non_logical_cint_operand (operands[2], <MODE>mode))
3528 {
3529 rtx tmp = ((!can_create_pseudo_p ()
3530 || rtx_equal_p (operands[0], operands[1]))
3531 ? operands[0] : gen_reg_rtx (<MODE>mode));
3532
3533 HOST_WIDE_INT value = INTVAL (operands[2]);
3534 HOST_WIDE_INT lo = value & 0xffff;
3535 HOST_WIDE_INT hi = value - lo;
3536
3537 emit_insn (gen_<code><mode>3 (tmp, operands[1], GEN_INT (hi)));
3538 emit_insn (gen_<code><mode>3 (operands[0], tmp, GEN_INT (lo)));
3539 DONE;
3540 }
3541
3542 if (!reg_or_logical_cint_operand (operands[2], <MODE>mode))
3543 operands[2] = force_reg (<MODE>mode, operands[2]);
3544 })
3545
3546 (define_split
3547 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
3548 (iorxor:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
3549 (match_operand:GPR 2 "non_logical_cint_operand" "")))]
3550 ""
3551 [(set (match_dup 3)
3552 (iorxor:GPR (match_dup 1)
3553 (match_dup 4)))
3554 (set (match_dup 0)
3555 (iorxor:GPR (match_dup 3)
3556 (match_dup 5)))]
3557 {
3558 operands[3] = ((!can_create_pseudo_p ()
3559 || rtx_equal_p (operands[0], operands[1]))
3560 ? operands[0] : gen_reg_rtx (<MODE>mode));
3561
3562 HOST_WIDE_INT value = INTVAL (operands[2]);
3563 HOST_WIDE_INT lo = value & 0xffff;
3564 HOST_WIDE_INT hi = value - lo;
3565
3566 operands[4] = GEN_INT (hi);
3567 operands[5] = GEN_INT (lo);
3568 })
3569
3570 (define_insn "*bool<mode>3_imm"
3571 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3572 (match_operator:GPR 3 "boolean_or_operator"
3573 [(match_operand:GPR 1 "gpc_reg_operand" "%r")
3574 (match_operand:GPR 2 "logical_const_operand" "n")]))]
3575 ""
3576 "%q3i%e2 %0,%1,%u2"
3577 [(set_attr "type" "logical")])
3578
3579 (define_insn "*bool<mode>3"
3580 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3581 (match_operator:GPR 3 "boolean_operator"
3582 [(match_operand:GPR 1 "gpc_reg_operand" "r")
3583 (match_operand:GPR 2 "gpc_reg_operand" "r")]))]
3584 ""
3585 "%q3 %0,%1,%2"
3586 [(set_attr "type" "logical")])
3587
3588 (define_insn_and_split "*bool<mode>3_dot"
3589 [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
3590 (compare:CC (match_operator:GPR 3 "boolean_operator"
3591 [(match_operand:GPR 1 "gpc_reg_operand" "r,r")
3592 (match_operand:GPR 2 "gpc_reg_operand" "r,r")])
3593 (const_int 0)))
3594 (clobber (match_scratch:GPR 0 "=r,r"))]
3595 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
3596 "@
3597 %q3. %0,%1,%2
3598 #"
3599 "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
3600 [(set (match_dup 0)
3601 (match_dup 3))
3602 (set (match_dup 4)
3603 (compare:CC (match_dup 0)
3604 (const_int 0)))]
3605 ""
3606 [(set_attr "type" "logical")
3607 (set_attr "dot" "yes")
3608 (set_attr "length" "4,8")])
3609
3610 (define_insn_and_split "*bool<mode>3_dot2"
3611 [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
3612 (compare:CC (match_operator:GPR 3 "boolean_operator"
3613 [(match_operand:GPR 1 "gpc_reg_operand" "r,r")
3614 (match_operand:GPR 2 "gpc_reg_operand" "r,r")])
3615 (const_int 0)))
3616 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3617 (match_dup 3))]
3618 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
3619 "@
3620 %q3. %0,%1,%2
3621 #"
3622 "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
3623 [(set (match_dup 0)
3624 (match_dup 3))
3625 (set (match_dup 4)
3626 (compare:CC (match_dup 0)
3627 (const_int 0)))]
3628 ""
3629 [(set_attr "type" "logical")
3630 (set_attr "dot" "yes")
3631 (set_attr "length" "4,8")])
3632
3633
3634 (define_insn "*boolc<mode>3"
3635 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3636 (match_operator:GPR 3 "boolean_operator"
3637 [(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))
3638 (match_operand:GPR 1 "gpc_reg_operand" "r")]))]
3639 ""
3640 "%q3 %0,%1,%2"
3641 [(set_attr "type" "logical")])
3642
3643 (define_insn_and_split "*boolc<mode>3_dot"
3644 [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
3645 (compare:CC (match_operator:GPR 3 "boolean_operator"
3646 [(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
3647 (match_operand:GPR 1 "gpc_reg_operand" "r,r")])
3648 (const_int 0)))
3649 (clobber (match_scratch:GPR 0 "=r,r"))]
3650 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
3651 "@
3652 %q3. %0,%1,%2
3653 #"
3654 "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
3655 [(set (match_dup 0)
3656 (match_dup 3))
3657 (set (match_dup 4)
3658 (compare:CC (match_dup 0)
3659 (const_int 0)))]
3660 ""
3661 [(set_attr "type" "logical")
3662 (set_attr "dot" "yes")
3663 (set_attr "length" "4,8")])
3664
3665 (define_insn_and_split "*boolc<mode>3_dot2"
3666 [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
3667 (compare:CC (match_operator:GPR 3 "boolean_operator"
3668 [(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
3669 (match_operand:GPR 1 "gpc_reg_operand" "r,r")])
3670 (const_int 0)))
3671 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3672 (match_dup 3))]
3673 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
3674 "@
3675 %q3. %0,%1,%2
3676 #"
3677 "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
3678 [(set (match_dup 0)
3679 (match_dup 3))
3680 (set (match_dup 4)
3681 (compare:CC (match_dup 0)
3682 (const_int 0)))]
3683 ""
3684 [(set_attr "type" "logical")
3685 (set_attr "dot" "yes")
3686 (set_attr "length" "4,8")])
3687
3688
3689 (define_insn "*boolcc<mode>3"
3690 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3691 (match_operator:GPR 3 "boolean_operator"
3692 [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
3693 (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))]))]
3694 ""
3695 "%q3 %0,%1,%2"
3696 [(set_attr "type" "logical")])
3697
3698 (define_insn_and_split "*boolcc<mode>3_dot"
3699 [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
3700 (compare:CC (match_operator:GPR 3 "boolean_operator"
3701 [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
3702 (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))])
3703 (const_int 0)))
3704 (clobber (match_scratch:GPR 0 "=r,r"))]
3705 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
3706 "@
3707 %q3. %0,%1,%2
3708 #"
3709 "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
3710 [(set (match_dup 0)
3711 (match_dup 3))
3712 (set (match_dup 4)
3713 (compare:CC (match_dup 0)
3714 (const_int 0)))]
3715 ""
3716 [(set_attr "type" "logical")
3717 (set_attr "dot" "yes")
3718 (set_attr "length" "4,8")])
3719
3720 (define_insn_and_split "*boolcc<mode>3_dot2"
3721 [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
3722 (compare:CC (match_operator:GPR 3 "boolean_operator"
3723 [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
3724 (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))])
3725 (const_int 0)))
3726 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3727 (match_dup 3))]
3728 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
3729 "@
3730 %q3. %0,%1,%2
3731 #"
3732 "&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
3733 [(set (match_dup 0)
3734 (match_dup 3))
3735 (set (match_dup 4)
3736 (compare:CC (match_dup 0)
3737 (const_int 0)))]
3738 ""
3739 [(set_attr "type" "logical")
3740 (set_attr "dot" "yes")
3741 (set_attr "length" "4,8")])
3742
3743
3744 ;; TODO: Should have dots of this as well.
3745 (define_insn "*eqv<mode>3"
3746 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3747 (not:GPR (xor:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3748 (match_operand:GPR 2 "gpc_reg_operand" "r"))))]
3749 ""
3750 "eqv %0,%1,%2"
3751 [(set_attr "type" "logical")])
3752 \f
3753 ;; Rotate-and-mask and insert.
3754
3755 (define_insn "*rotl<mode>3_mask"
3756 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3757 (and:GPR (match_operator:GPR 4 "rotate_mask_operator"
3758 [(match_operand:GPR 1 "gpc_reg_operand" "r")
3759 (match_operand:SI 2 "reg_or_cint_operand" "rn")])
3760 (match_operand:GPR 3 "const_int_operand" "n")))]
3761 "rs6000_is_valid_shift_mask (operands[3], operands[4], <MODE>mode)"
3762 {
3763 return rs6000_insn_for_shift_mask (<MODE>mode, operands, false);
3764 }
3765 [(set_attr "type" "shift")
3766 (set_attr "maybe_var_shift" "yes")])
3767
3768 (define_insn_and_split "*rotl<mode>3_mask_dot"
3769 [(set (match_operand:CC 5 "cc_reg_operand" "=x,?y")
3770 (compare:CC
3771 (and:GPR (match_operator:GPR 4 "rotate_mask_operator"
3772 [(match_operand:GPR 1 "gpc_reg_operand" "r,r")
3773 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")])
3774 (match_operand:GPR 3 "const_int_operand" "n,n"))
3775 (const_int 0)))
3776 (clobber (match_scratch:GPR 0 "=r,r"))]
3777 "(<MODE>mode == Pmode || UINTVAL (operands[3]) <= 0x7fffffff)
3778 && rs6000_gen_cell_microcode
3779 && rs6000_is_valid_shift_mask (operands[3], operands[4], <MODE>mode)"
3780 {
3781 if (which_alternative == 0)
3782 return rs6000_insn_for_shift_mask (<MODE>mode, operands, true);
3783 else
3784 return "#";
3785 }
3786 "&& reload_completed && cc_reg_not_cr0_operand (operands[5], CCmode)"
3787 [(set (match_dup 0)
3788 (and:GPR (match_dup 4)
3789 (match_dup 3)))
3790 (set (match_dup 5)
3791 (compare:CC (match_dup 0)
3792 (const_int 0)))]
3793 ""
3794 [(set_attr "type" "shift")
3795 (set_attr "maybe_var_shift" "yes")
3796 (set_attr "dot" "yes")
3797 (set_attr "length" "4,8")])
3798
3799 (define_insn_and_split "*rotl<mode>3_mask_dot2"
3800 [(set (match_operand:CC 5 "cc_reg_operand" "=x,?y")
3801 (compare:CC
3802 (and:GPR (match_operator:GPR 4 "rotate_mask_operator"
3803 [(match_operand:GPR 1 "gpc_reg_operand" "r,r")
3804 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn")])
3805 (match_operand:GPR 3 "const_int_operand" "n,n"))
3806 (const_int 0)))
3807 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
3808 (and:GPR (match_dup 4)
3809 (match_dup 3)))]
3810 "(<MODE>mode == Pmode || UINTVAL (operands[3]) <= 0x7fffffff)
3811 && rs6000_gen_cell_microcode
3812 && rs6000_is_valid_shift_mask (operands[3], operands[4], <MODE>mode)"
3813 {
3814 if (which_alternative == 0)
3815 return rs6000_insn_for_shift_mask (<MODE>mode, operands, true);
3816 else
3817 return "#";
3818 }
3819 "&& reload_completed && cc_reg_not_cr0_operand (operands[5], CCmode)"
3820 [(set (match_dup 0)
3821 (and:GPR (match_dup 4)
3822 (match_dup 3)))
3823 (set (match_dup 5)
3824 (compare:CC (match_dup 0)
3825 (const_int 0)))]
3826 ""
3827 [(set_attr "type" "shift")
3828 (set_attr "maybe_var_shift" "yes")
3829 (set_attr "dot" "yes")
3830 (set_attr "length" "4,8")])
3831
3832 ; Special case for less-than-0. We can do it with just one machine
3833 ; instruction, but the generic optimizers do not realise it is cheap.
3834 (define_insn "*lt0_disi"
3835 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
3836 (lt:DI (match_operand:SI 1 "gpc_reg_operand" "r")
3837 (const_int 0)))]
3838 "TARGET_POWERPC64"
3839 "rlwinm %0,%1,1,31,31"
3840 [(set_attr "type" "shift")])
3841
3842
3843
3844 ; Two forms for insert (the two arms of the IOR are not canonicalized,
3845 ; both are an AND so are the same precedence).
3846 (define_insn "*rotl<mode>3_insert"
3847 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3848 (ior:GPR (and:GPR (match_operator:GPR 4 "rotate_mask_operator"
3849 [(match_operand:GPR 1 "gpc_reg_operand" "r")
3850 (match_operand:SI 2 "const_int_operand" "n")])
3851 (match_operand:GPR 3 "const_int_operand" "n"))
3852 (and:GPR (match_operand:GPR 5 "gpc_reg_operand" "0")
3853 (match_operand:GPR 6 "const_int_operand" "n"))))]
3854 "rs6000_is_valid_insert_mask (operands[3], operands[4], <MODE>mode)
3855 && UINTVAL (operands[3]) + UINTVAL (operands[6]) + 1 == 0"
3856 {
3857 return rs6000_insn_for_insert_mask (<MODE>mode, operands, false);
3858 }
3859 [(set_attr "type" "insert")])
3860 ; FIXME: this needs an attr "size", so that the scheduler can see the
3861 ; difference between rlwimi and rldimi. We also might want dot forms,
3862 ; but not for rlwimi on POWER4 and similar processors.
3863
3864 (define_insn "*rotl<mode>3_insert_2"
3865 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3866 (ior:GPR (and:GPR (match_operand:GPR 5 "gpc_reg_operand" "0")
3867 (match_operand:GPR 6 "const_int_operand" "n"))
3868 (and:GPR (match_operator:GPR 4 "rotate_mask_operator"
3869 [(match_operand:GPR 1 "gpc_reg_operand" "r")
3870 (match_operand:SI 2 "const_int_operand" "n")])
3871 (match_operand:GPR 3 "const_int_operand" "n"))))]
3872 "rs6000_is_valid_insert_mask (operands[3], operands[4], <MODE>mode)
3873 && UINTVAL (operands[3]) + UINTVAL (operands[6]) + 1 == 0"
3874 {
3875 return rs6000_insn_for_insert_mask (<MODE>mode, operands, false);
3876 }
3877 [(set_attr "type" "insert")])
3878
3879 ; There are also some forms without one of the ANDs.
3880 (define_insn "*rotl<mode>3_insert_3"
3881 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3882 (ior:GPR (and:GPR (match_operand:GPR 3 "gpc_reg_operand" "0")
3883 (match_operand:GPR 4 "const_int_operand" "n"))
3884 (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3885 (match_operand:SI 2 "const_int_operand" "n"))))]
3886 "INTVAL (operands[2]) == exact_log2 (UINTVAL (operands[4]) + 1)"
3887 {
3888 if (<MODE>mode == SImode)
3889 return "rlwimi %0,%1,%h2,0,31-%h2";
3890 else
3891 return "rldimi %0,%1,%H2,0";
3892 }
3893 [(set_attr "type" "insert")])
3894
3895 (define_insn "*rotl<mode>3_insert_4"
3896 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
3897 (ior:GPR (and:GPR (match_operand:GPR 3 "gpc_reg_operand" "0")
3898 (match_operand:GPR 4 "const_int_operand" "n"))
3899 (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
3900 (match_operand:SI 2 "const_int_operand" "n"))))]
3901 "<MODE>mode == SImode &&
3902 GET_MODE_PRECISION (<MODE>mode)
3903 == INTVAL (operands[2]) + exact_log2 (-UINTVAL (operands[4]))"
3904 {
3905 operands[2] = GEN_INT (GET_MODE_PRECISION (<MODE>mode)
3906 - INTVAL (operands[2]));
3907 if (<MODE>mode == SImode)
3908 return "rlwimi %0,%1,%h2,32-%h2,31";
3909 else
3910 return "rldimi %0,%1,%H2,64-%H2";
3911 }
3912 [(set_attr "type" "insert")])
3913
3914 (define_insn "*rotlsi3_insert_5"
3915 [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
3916 (ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0,r")
3917 (match_operand:SI 2 "const_int_operand" "n,n"))
3918 (and:SI (match_operand:SI 3 "gpc_reg_operand" "r,0")
3919 (match_operand:SI 4 "const_int_operand" "n,n"))))]
3920 "rs6000_is_valid_mask (operands[2], NULL, NULL, SImode)
3921 && UINTVAL (operands[2]) != 0 && UINTVAL (operands[4]) != 0
3922 && UINTVAL (operands[2]) + UINTVAL (operands[4]) + 1 == 0"
3923 "@
3924 rlwimi %0,%3,0,%4
3925 rlwimi %0,%1,0,%2"
3926 [(set_attr "type" "insert")])
3927
3928 (define_insn "*rotldi3_insert_6"
3929 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
3930 (ior:DI (and:DI (match_operand:DI 1 "gpc_reg_operand" "0")
3931 (match_operand:DI 2 "const_int_operand" "n"))
3932 (and:DI (match_operand:DI 3 "gpc_reg_operand" "r")
3933 (match_operand:DI 4 "const_int_operand" "n"))))]
3934 "exact_log2 (-UINTVAL (operands[2])) > 0
3935 && UINTVAL (operands[2]) + UINTVAL (operands[4]) + 1 == 0"
3936 {
3937 operands[5] = GEN_INT (64 - exact_log2 (-UINTVAL (operands[2])));
3938 return "rldimi %0,%3,0,%5";
3939 }
3940 [(set_attr "type" "insert")
3941 (set_attr "size" "64")])
3942
3943 (define_insn "*rotldi3_insert_7"
3944 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
3945 (ior:DI (and:DI (match_operand:DI 3 "gpc_reg_operand" "r")
3946 (match_operand:DI 4 "const_int_operand" "n"))
3947 (and:DI (match_operand:DI 1 "gpc_reg_operand" "0")
3948 (match_operand:DI 2 "const_int_operand" "n"))))]
3949 "exact_log2 (-UINTVAL (operands[2])) > 0
3950 && UINTVAL (operands[2]) + UINTVAL (operands[4]) + 1 == 0"
3951 {
3952 operands[5] = GEN_INT (64 - exact_log2 (-UINTVAL (operands[2])));
3953 return "rldimi %0,%3,0,%5";
3954 }
3955 [(set_attr "type" "insert")
3956 (set_attr "size" "64")])
3957
3958
3959 ; This handles the important case of multiple-precision shifts. There is
3960 ; no canonicalization rule for ASHIFT vs. LSHIFTRT, so two patterns.
3961 (define_split
3962 [(set (match_operand:GPR 0 "gpc_reg_operand")
3963 (ior:GPR (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand")
3964 (match_operand:SI 3 "const_int_operand"))
3965 (lshiftrt:GPR (match_operand:GPR 2 "gpc_reg_operand")
3966 (match_operand:SI 4 "const_int_operand"))))]
3967 "can_create_pseudo_p ()
3968 && INTVAL (operands[3]) + INTVAL (operands[4])
3969 >= GET_MODE_PRECISION (<MODE>mode)"
3970 [(set (match_dup 5)
3971 (lshiftrt:GPR (match_dup 2)
3972 (match_dup 4)))
3973 (set (match_dup 0)
3974 (ior:GPR (and:GPR (match_dup 5)
3975 (match_dup 6))
3976 (ashift:GPR (match_dup 1)
3977 (match_dup 3))))]
3978 {
3979 unsigned HOST_WIDE_INT mask = 1;
3980 mask = (mask << INTVAL (operands[3])) - 1;
3981 operands[5] = gen_reg_rtx (<MODE>mode);
3982 operands[6] = GEN_INT (mask);
3983 })
3984
3985 (define_split
3986 [(set (match_operand:GPR 0 "gpc_reg_operand")
3987 (ior:GPR (lshiftrt:GPR (match_operand:GPR 2 "gpc_reg_operand")
3988 (match_operand:SI 4 "const_int_operand"))
3989 (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand")
3990 (match_operand:SI 3 "const_int_operand"))))]
3991 "can_create_pseudo_p ()
3992 && INTVAL (operands[3]) + INTVAL (operands[4])
3993 >= GET_MODE_PRECISION (<MODE>mode)"
3994 [(set (match_dup 5)
3995 (lshiftrt:GPR (match_dup 2)
3996 (match_dup 4)))
3997 (set (match_dup 0)
3998 (ior:GPR (and:GPR (match_dup 5)
3999 (match_dup 6))
4000 (ashift:GPR (match_dup 1)
4001 (match_dup 3))))]
4002 {
4003 unsigned HOST_WIDE_INT mask = 1;
4004 mask = (mask << INTVAL (operands[3])) - 1;
4005 operands[5] = gen_reg_rtx (<MODE>mode);
4006 operands[6] = GEN_INT (mask);
4007 })
4008
4009
4010 ; Another important case is setting some bits to 1; we can do that with
4011 ; an insert instruction, in many cases.
4012 (define_insn_and_split "*ior<mode>_mask"
4013 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4014 (ior:GPR (match_operand:GPR 1 "gpc_reg_operand" "0")
4015 (match_operand:GPR 2 "const_int_operand" "n")))
4016 (clobber (match_scratch:GPR 3 "=r"))]
4017 "!logical_const_operand (operands[2], <MODE>mode)
4018 && rs6000_is_valid_mask (operands[2], NULL, NULL, <MODE>mode)"
4019 "#"
4020 "&& 1"
4021 [(set (match_dup 3)
4022 (const_int -1))
4023 (set (match_dup 0)
4024 (ior:GPR (and:GPR (rotate:GPR (match_dup 3)
4025 (match_dup 4))
4026 (match_dup 2))
4027 (and:GPR (match_dup 1)
4028 (match_dup 5))))]
4029 {
4030 int nb, ne;
4031 rs6000_is_valid_mask (operands[2], &nb, &ne, <MODE>mode);
4032 if (GET_CODE (operands[3]) == SCRATCH)
4033 operands[3] = gen_reg_rtx (<MODE>mode);
4034 operands[4] = GEN_INT (ne);
4035 operands[5] = GEN_INT (~UINTVAL (operands[2]));
4036 }
4037 [(set_attr "type" "two")
4038 (set_attr "length" "8")])
4039
4040
4041 ;; Now the simple shifts.
4042
4043 (define_insn "rotl<mode>3"
4044 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4045 (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
4046 (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
4047 ""
4048 "rotl<wd>%I2 %0,%1,%<hH>2"
4049 [(set_attr "type" "shift")
4050 (set_attr "maybe_var_shift" "yes")])
4051
4052 (define_insn "*rotlsi3_64"
4053 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
4054 (zero_extend:DI
4055 (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
4056 (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
4057 "TARGET_POWERPC64"
4058 "rotlw%I2 %0,%1,%h2"
4059 [(set_attr "type" "shift")
4060 (set_attr "maybe_var_shift" "yes")])
4061
4062 (define_insn_and_split "*rotl<mode>3_dot"
4063 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4064 (compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4065 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4066 (const_int 0)))
4067 (clobber (match_scratch:GPR 0 "=r,r"))]
4068 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4069 "@
4070 rotl<wd>%I2. %0,%1,%<hH>2
4071 #"
4072 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4073 [(set (match_dup 0)
4074 (rotate:GPR (match_dup 1)
4075 (match_dup 2)))
4076 (set (match_dup 3)
4077 (compare:CC (match_dup 0)
4078 (const_int 0)))]
4079 ""
4080 [(set_attr "type" "shift")
4081 (set_attr "maybe_var_shift" "yes")
4082 (set_attr "dot" "yes")
4083 (set_attr "length" "4,8")])
4084
4085 (define_insn_and_split "*rotl<mode>3_dot2"
4086 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4087 (compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4088 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4089 (const_int 0)))
4090 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
4091 (rotate:GPR (match_dup 1)
4092 (match_dup 2)))]
4093 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4094 "@
4095 rotl<wd>%I2. %0,%1,%<hH>2
4096 #"
4097 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4098 [(set (match_dup 0)
4099 (rotate:GPR (match_dup 1)
4100 (match_dup 2)))
4101 (set (match_dup 3)
4102 (compare:CC (match_dup 0)
4103 (const_int 0)))]
4104 ""
4105 [(set_attr "type" "shift")
4106 (set_attr "maybe_var_shift" "yes")
4107 (set_attr "dot" "yes")
4108 (set_attr "length" "4,8")])
4109
4110
4111 (define_insn "ashl<mode>3"
4112 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4113 (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
4114 (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
4115 ""
4116 "sl<wd>%I2 %0,%1,%<hH>2"
4117 [(set_attr "type" "shift")
4118 (set_attr "maybe_var_shift" "yes")])
4119
4120 (define_insn "*ashlsi3_64"
4121 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
4122 (zero_extend:DI
4123 (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
4124 (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
4125 "TARGET_POWERPC64"
4126 "slw%I2 %0,%1,%h2"
4127 [(set_attr "type" "shift")
4128 (set_attr "maybe_var_shift" "yes")])
4129
4130 (define_insn_and_split "*ashl<mode>3_dot"
4131 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4132 (compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4133 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4134 (const_int 0)))
4135 (clobber (match_scratch:GPR 0 "=r,r"))]
4136 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4137 "@
4138 sl<wd>%I2. %0,%1,%<hH>2
4139 #"
4140 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4141 [(set (match_dup 0)
4142 (ashift:GPR (match_dup 1)
4143 (match_dup 2)))
4144 (set (match_dup 3)
4145 (compare:CC (match_dup 0)
4146 (const_int 0)))]
4147 ""
4148 [(set_attr "type" "shift")
4149 (set_attr "maybe_var_shift" "yes")
4150 (set_attr "dot" "yes")
4151 (set_attr "length" "4,8")])
4152
4153 (define_insn_and_split "*ashl<mode>3_dot2"
4154 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4155 (compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4156 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4157 (const_int 0)))
4158 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
4159 (ashift:GPR (match_dup 1)
4160 (match_dup 2)))]
4161 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4162 "@
4163 sl<wd>%I2. %0,%1,%<hH>2
4164 #"
4165 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4166 [(set (match_dup 0)
4167 (ashift:GPR (match_dup 1)
4168 (match_dup 2)))
4169 (set (match_dup 3)
4170 (compare:CC (match_dup 0)
4171 (const_int 0)))]
4172 ""
4173 [(set_attr "type" "shift")
4174 (set_attr "maybe_var_shift" "yes")
4175 (set_attr "dot" "yes")
4176 (set_attr "length" "4,8")])
4177
4178 ;; Pretend we have a memory form of extswsli until register allocation is done
4179 ;; so that we use LWZ to load the value from memory, instead of LWA.
4180 (define_insn_and_split "ashdi3_extswsli"
4181 [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
4182 (ashift:DI
4183 (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "r,m"))
4184 (match_operand:DI 2 "u6bit_cint_operand" "n,n")))]
4185 "TARGET_EXTSWSLI"
4186 "@
4187 extswsli %0,%1,%2
4188 #"
4189 "&& reload_completed && MEM_P (operands[1])"
4190 [(set (match_dup 3)
4191 (match_dup 1))
4192 (set (match_dup 0)
4193 (ashift:DI (sign_extend:DI (match_dup 3))
4194 (match_dup 2)))]
4195 {
4196 operands[3] = gen_lowpart (SImode, operands[0]);
4197 }
4198 [(set_attr "type" "shift")
4199 (set_attr "maybe_var_shift" "no")])
4200
4201
4202 (define_insn_and_split "ashdi3_extswsli_dot"
4203 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y,?x,??y")
4204 (compare:CC
4205 (ashift:DI
4206 (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "r,r,m,m"))
4207 (match_operand:DI 2 "u6bit_cint_operand" "n,n,n,n"))
4208 (const_int 0)))
4209 (clobber (match_scratch:DI 0 "=r,r,r,r"))]
4210 "TARGET_EXTSWSLI"
4211 "@
4212 extswsli. %0,%1,%2
4213 #
4214 #
4215 #"
4216 "&& reload_completed
4217 && (cc_reg_not_cr0_operand (operands[3], CCmode)
4218 || memory_operand (operands[1], SImode))"
4219 [(pc)]
4220 {
4221 rtx dest = operands[0];
4222 rtx src = operands[1];
4223 rtx shift = operands[2];
4224 rtx cr = operands[3];
4225 rtx src2;
4226
4227 if (!MEM_P (src))
4228 src2 = src;
4229 else
4230 {
4231 src2 = gen_lowpart (SImode, dest);
4232 emit_move_insn (src2, src);
4233 }
4234
4235 if (REGNO (cr) == CR0_REGNO)
4236 {
4237 emit_insn (gen_ashdi3_extswsli_dot2 (dest, src2, shift, cr));
4238 DONE;
4239 }
4240
4241 emit_insn (gen_ashdi3_extswsli (dest, src2, shift));
4242 emit_insn (gen_rtx_SET (cr, gen_rtx_COMPARE (CCmode, dest, const0_rtx)));
4243 DONE;
4244 }
4245 [(set_attr "type" "shift")
4246 (set_attr "maybe_var_shift" "no")
4247 (set_attr "dot" "yes")
4248 (set_attr "length" "4,8,8,12")])
4249
4250 (define_insn_and_split "ashdi3_extswsli_dot2"
4251 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y,?x,??y")
4252 (compare:CC
4253 (ashift:DI
4254 (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "r,r,m,m"))
4255 (match_operand:DI 2 "u6bit_cint_operand" "n,n,n,n"))
4256 (const_int 0)))
4257 (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
4258 (ashift:DI (sign_extend:DI (match_dup 1))
4259 (match_dup 2)))]
4260 "TARGET_EXTSWSLI"
4261 "@
4262 extswsli. %0,%1,%2
4263 #
4264 #
4265 #"
4266 "&& reload_completed
4267 && (cc_reg_not_cr0_operand (operands[3], CCmode)
4268 || memory_operand (operands[1], SImode))"
4269 [(pc)]
4270 {
4271 rtx dest = operands[0];
4272 rtx src = operands[1];
4273 rtx shift = operands[2];
4274 rtx cr = operands[3];
4275 rtx src2;
4276
4277 if (!MEM_P (src))
4278 src2 = src;
4279 else
4280 {
4281 src2 = gen_lowpart (SImode, dest);
4282 emit_move_insn (src2, src);
4283 }
4284
4285 if (REGNO (cr) == CR0_REGNO)
4286 {
4287 emit_insn (gen_ashdi3_extswsli_dot2 (dest, src2, shift, cr));
4288 DONE;
4289 }
4290
4291 emit_insn (gen_ashdi3_extswsli (dest, src2, shift));
4292 emit_insn (gen_rtx_SET (cr, gen_rtx_COMPARE (CCmode, dest, const0_rtx)));
4293 DONE;
4294 }
4295 [(set_attr "type" "shift")
4296 (set_attr "maybe_var_shift" "no")
4297 (set_attr "dot" "yes")
4298 (set_attr "length" "4,8,8,12")])
4299
4300 (define_insn "lshr<mode>3"
4301 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4302 (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
4303 (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
4304 ""
4305 "sr<wd>%I2 %0,%1,%<hH>2"
4306 [(set_attr "type" "shift")
4307 (set_attr "maybe_var_shift" "yes")])
4308
4309 (define_insn "*lshrsi3_64"
4310 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
4311 (zero_extend:DI
4312 (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
4313 (match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
4314 "TARGET_POWERPC64"
4315 "srw%I2 %0,%1,%h2"
4316 [(set_attr "type" "shift")
4317 (set_attr "maybe_var_shift" "yes")])
4318
4319 (define_insn_and_split "*lshr<mode>3_dot"
4320 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4321 (compare:CC (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4322 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4323 (const_int 0)))
4324 (clobber (match_scratch:GPR 0 "=r,r"))]
4325 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4326 "@
4327 sr<wd>%I2. %0,%1,%<hH>2
4328 #"
4329 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4330 [(set (match_dup 0)
4331 (lshiftrt:GPR (match_dup 1)
4332 (match_dup 2)))
4333 (set (match_dup 3)
4334 (compare:CC (match_dup 0)
4335 (const_int 0)))]
4336 ""
4337 [(set_attr "type" "shift")
4338 (set_attr "maybe_var_shift" "yes")
4339 (set_attr "dot" "yes")
4340 (set_attr "length" "4,8")])
4341
4342 (define_insn_and_split "*lshr<mode>3_dot2"
4343 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4344 (compare:CC (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4345 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4346 (const_int 0)))
4347 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
4348 (lshiftrt:GPR (match_dup 1)
4349 (match_dup 2)))]
4350 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4351 "@
4352 sr<wd>%I2. %0,%1,%<hH>2
4353 #"
4354 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4355 [(set (match_dup 0)
4356 (lshiftrt:GPR (match_dup 1)
4357 (match_dup 2)))
4358 (set (match_dup 3)
4359 (compare:CC (match_dup 0)
4360 (const_int 0)))]
4361 ""
4362 [(set_attr "type" "shift")
4363 (set_attr "maybe_var_shift" "yes")
4364 (set_attr "dot" "yes")
4365 (set_attr "length" "4,8")])
4366
4367
4368 (define_insn "ashr<mode>3"
4369 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4370 (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
4371 (match_operand:SI 2 "reg_or_cint_operand" "rn")))
4372 (clobber (reg:GPR CA_REGNO))]
4373 ""
4374 "sra<wd>%I2 %0,%1,%<hH>2"
4375 [(set_attr "type" "shift")
4376 (set_attr "maybe_var_shift" "yes")])
4377
4378 (define_insn "*ashrsi3_64"
4379 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
4380 (sign_extend:DI
4381 (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
4382 (match_operand:SI 2 "reg_or_cint_operand" "rn"))))
4383 (clobber (reg:SI CA_REGNO))]
4384 "TARGET_POWERPC64"
4385 "sraw%I2 %0,%1,%h2"
4386 [(set_attr "type" "shift")
4387 (set_attr "maybe_var_shift" "yes")])
4388
4389 (define_insn_and_split "*ashr<mode>3_dot"
4390 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4391 (compare:CC (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4392 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4393 (const_int 0)))
4394 (clobber (match_scratch:GPR 0 "=r,r"))
4395 (clobber (reg:GPR CA_REGNO))]
4396 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4397 "@
4398 sra<wd>%I2. %0,%1,%<hH>2
4399 #"
4400 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4401 [(parallel [(set (match_dup 0)
4402 (ashiftrt:GPR (match_dup 1)
4403 (match_dup 2)))
4404 (clobber (reg:GPR CA_REGNO))])
4405 (set (match_dup 3)
4406 (compare:CC (match_dup 0)
4407 (const_int 0)))]
4408 ""
4409 [(set_attr "type" "shift")
4410 (set_attr "maybe_var_shift" "yes")
4411 (set_attr "dot" "yes")
4412 (set_attr "length" "4,8")])
4413
4414 (define_insn_and_split "*ashr<mode>3_dot2"
4415 [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
4416 (compare:CC (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
4417 (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
4418 (const_int 0)))
4419 (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
4420 (ashiftrt:GPR (match_dup 1)
4421 (match_dup 2)))
4422 (clobber (reg:GPR CA_REGNO))]
4423 "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
4424 "@
4425 sra<wd>%I2. %0,%1,%<hH>2
4426 #"
4427 "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
4428 [(parallel [(set (match_dup 0)
4429 (ashiftrt:GPR (match_dup 1)
4430 (match_dup 2)))
4431 (clobber (reg:GPR CA_REGNO))])
4432 (set (match_dup 3)
4433 (compare:CC (match_dup 0)
4434 (const_int 0)))]
4435 ""
4436 [(set_attr "type" "shift")
4437 (set_attr "maybe_var_shift" "yes")
4438 (set_attr "dot" "yes")
4439 (set_attr "length" "4,8")])
4440 \f
4441 ;; Builtins to replace a division to generate FRE reciprocal estimate
4442 ;; instructions and the necessary fixup instructions
4443 (define_expand "recip<mode>3"
4444 [(match_operand:RECIPF 0 "gpc_reg_operand" "")
4445 (match_operand:RECIPF 1 "gpc_reg_operand" "")
4446 (match_operand:RECIPF 2 "gpc_reg_operand" "")]
4447 "RS6000_RECIP_HAVE_RE_P (<MODE>mode)"
4448 {
4449 rs6000_emit_swdiv (operands[0], operands[1], operands[2], false);
4450 DONE;
4451 })
4452
4453 ;; Split to create division from FRE/FRES/etc. and fixup instead of the normal
4454 ;; hardware division. This is only done before register allocation and with
4455 ;; -ffast-math. This must appear before the divsf3/divdf3 insns.
4456 ;; We used to also check optimize_insn_for_speed_p () but problems with guessed
4457 ;; frequencies (pr68212/pr77536) yields that unreliable so it was removed.
4458 (define_split
4459 [(set (match_operand:RECIPF 0 "gpc_reg_operand" "")
4460 (div:RECIPF (match_operand 1 "gpc_reg_operand" "")
4461 (match_operand 2 "gpc_reg_operand" "")))]
4462 "RS6000_RECIP_AUTO_RE_P (<MODE>mode)
4463 && can_create_pseudo_p () && flag_finite_math_only
4464 && !flag_trapping_math && flag_reciprocal_math"
4465 [(const_int 0)]
4466 {
4467 rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
4468 DONE;
4469 })
4470
4471 ;; Builtins to replace 1/sqrt(x) with instructions using RSQRTE and the
4472 ;; appropriate fixup.
4473 (define_expand "rsqrt<mode>2"
4474 [(match_operand:RECIPF 0 "gpc_reg_operand" "")
4475 (match_operand:RECIPF 1 "gpc_reg_operand" "")]
4476 "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
4477 {
4478 rs6000_emit_swsqrt (operands[0], operands[1], 1);
4479 DONE;
4480 })
4481 \f
4482 ;; Floating-point insns, excluding normal data motion. We combine the SF/DF
4483 ;; modes here, and also add in conditional vsx/power8-vector support to access
4484 ;; values in the traditional Altivec registers if the appropriate
4485 ;; -mupper-regs-{df,sf} option is enabled.
4486
4487 (define_expand "abs<mode>2"
4488 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4489 (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
4490 "TARGET_<MODE>_INSN"
4491 "")
4492
4493 (define_insn "*abs<mode>2_fpr"
4494 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
4495 (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
4496 "TARGET_<MODE>_FPR"
4497 "@
4498 fabs %0,%1
4499 xsabsdp %x0,%x1"
4500 [(set_attr "type" "fpsimple")
4501 (set_attr "fp_type" "fp_addsub_<Fs>")])
4502
4503 (define_insn "*nabs<mode>2_fpr"
4504 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
4505 (neg:SFDF
4506 (abs:SFDF
4507 (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))]
4508 "TARGET_<MODE>_FPR"
4509 "@
4510 fnabs %0,%1
4511 xsnabsdp %x0,%x1"
4512 [(set_attr "type" "fpsimple")
4513 (set_attr "fp_type" "fp_addsub_<Fs>")])
4514
4515 (define_expand "neg<mode>2"
4516 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4517 (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
4518 "TARGET_<MODE>_INSN"
4519 "")
4520
4521 (define_insn "*neg<mode>2_fpr"
4522 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
4523 (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
4524 "TARGET_<MODE>_FPR"
4525 "@
4526 fneg %0,%1
4527 xsnegdp %x0,%x1"
4528 [(set_attr "type" "fpsimple")
4529 (set_attr "fp_type" "fp_addsub_<Fs>")])
4530
4531 (define_expand "add<mode>3"
4532 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4533 (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
4534 (match_operand:SFDF 2 "gpc_reg_operand" "")))]
4535 "TARGET_<MODE>_INSN"
4536 "")
4537
4538 (define_insn "*add<mode>3_fpr"
4539 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4540 (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>")
4541 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
4542 "TARGET_<MODE>_FPR"
4543 "@
4544 fadd<Ftrad> %0,%1,%2
4545 xsadd<Fvsx> %x0,%x1,%x2"
4546 [(set_attr "type" "fp")
4547 (set_attr "fp_type" "fp_addsub_<Fs>")])
4548
4549 (define_expand "sub<mode>3"
4550 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4551 (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
4552 (match_operand:SFDF 2 "gpc_reg_operand" "")))]
4553 "TARGET_<MODE>_INSN"
4554 "")
4555
4556 (define_insn "*sub<mode>3_fpr"
4557 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4558 (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
4559 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
4560 "TARGET_<MODE>_FPR"
4561 "@
4562 fsub<Ftrad> %0,%1,%2
4563 xssub<Fvsx> %x0,%x1,%x2"
4564 [(set_attr "type" "fp")
4565 (set_attr "fp_type" "fp_addsub_<Fs>")])
4566
4567 (define_expand "mul<mode>3"
4568 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4569 (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
4570 (match_operand:SFDF 2 "gpc_reg_operand" "")))]
4571 "TARGET_<MODE>_INSN"
4572 "")
4573
4574 (define_insn "*mul<mode>3_fpr"
4575 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4576 (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>")
4577 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
4578 "TARGET_<MODE>_FPR"
4579 "@
4580 fmul<Ftrad> %0,%1,%2
4581 xsmul<Fvsx> %x0,%x1,%x2"
4582 [(set_attr "type" "dmul")
4583 (set_attr "fp_type" "fp_mul_<Fs>")])
4584
4585 (define_expand "div<mode>3"
4586 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4587 (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
4588 (match_operand:SFDF 2 "gpc_reg_operand" "")))]
4589 "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU"
4590 {
4591 if (RS6000_RECIP_AUTO_RE_P (<MODE>mode)
4592 && can_create_pseudo_p () && flag_finite_math_only
4593 && !flag_trapping_math && flag_reciprocal_math)
4594 {
4595 rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
4596 DONE;
4597 }
4598 })
4599
4600 (define_insn "*div<mode>3_fpr"
4601 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4602 (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
4603 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
4604 "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU"
4605 "@
4606 fdiv<Ftrad> %0,%1,%2
4607 xsdiv<Fvsx> %x0,%x1,%x2"
4608 [(set_attr "type" "<Fs>div")
4609 (set_attr "fp_type" "fp_div_<Fs>")])
4610
4611 (define_insn "*sqrt<mode>2_internal"
4612 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4613 (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")))]
4614 "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
4615 && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
4616 "@
4617 fsqrt<Ftrad> %0,%1
4618 xssqrt<Fvsx> %x0,%x1"
4619 [(set_attr "type" "<Fs>sqrt")
4620 (set_attr "fp_type" "fp_sqrt_<Fs>")])
4621
4622 (define_expand "sqrt<mode>2"
4623 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4624 (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
4625 "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
4626 && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
4627 {
4628 if (<MODE>mode == SFmode
4629 && TARGET_RECIP_PRECISION
4630 && RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)
4631 && !optimize_function_for_size_p (cfun)
4632 && flag_finite_math_only && !flag_trapping_math
4633 && flag_unsafe_math_optimizations)
4634 {
4635 rs6000_emit_swsqrt (operands[0], operands[1], 0);
4636 DONE;
4637 }
4638 })
4639
4640 ;; Floating point reciprocal approximation
4641 (define_insn "fre<Fs>"
4642 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4643 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
4644 UNSPEC_FRES))]
4645 "TARGET_<FFRE>"
4646 "@
4647 fre<Ftrad> %0,%1
4648 xsre<Fvsx> %x0,%x1"
4649 [(set_attr "type" "fp")])
4650
4651 (define_insn "*rsqrt<mode>2"
4652 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
4653 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
4654 UNSPEC_RSQRT))]
4655 "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
4656 "@
4657 frsqrte<Ftrad> %0,%1
4658 xsrsqrte<Fvsx> %x0,%x1"
4659 [(set_attr "type" "fp")])
4660
4661 ;; Floating point comparisons
4662 (define_insn "*cmp<mode>_fpr"
4663 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
4664 (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
4665 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
4666 "TARGET_<MODE>_FPR"
4667 "@
4668 fcmpu %0,%1,%2
4669 xscmpudp %0,%x1,%x2"
4670 [(set_attr "type" "fpcompare")])
4671
4672 ;; Floating point conversions
4673 (define_expand "extendsfdf2"
4674 [(set (match_operand:DF 0 "gpc_reg_operand")
4675 (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand")))]
4676 "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
4677 {
4678 if (HONOR_SNANS (SFmode))
4679 operands[1] = force_reg (SFmode, operands[1]);
4680 })
4681
4682 (define_insn_and_split "*extendsfdf2_fpr"
4683 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wu,wb")
4684 (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z,wY")))]
4685 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
4686 && !HONOR_SNANS (SFmode)"
4687 "@
4688 #
4689 fmr %0,%1
4690 lfs%U1%X1 %0,%1
4691 #
4692 xscpsgndp %x0,%x1,%x1
4693 lxsspx %x0,%y1
4694 lxssp %0,%1"
4695 "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
4696 [(const_int 0)]
4697 {
4698 emit_note (NOTE_INSN_DELETED);
4699 DONE;
4700 }
4701 [(set_attr "type" "fp,fpsimple,fpload,fp,fpsimple,fpload,fpload")])
4702
4703 (define_insn "*extendsfdf2_snan"
4704 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
4705 (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f,wy")))]
4706 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
4707 && HONOR_SNANS (SFmode)"
4708 "@
4709 frsp %0,%1
4710 xsrsp %x0,%x1"
4711 [(set_attr "type" "fp")])
4712
4713 (define_expand "truncdfsf2"
4714 [(set (match_operand:SF 0 "gpc_reg_operand" "")
4715 (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))]
4716 "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
4717 "")
4718
4719 (define_insn "*truncdfsf2_fpr"
4720 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy")
4721 (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d,ws")))]
4722 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
4723 "@
4724 frsp %0,%1
4725 xsrsp %x0,%x1"
4726 [(set_attr "type" "fp")])
4727
4728 ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
4729 ;; builtins.c and optabs.c that are not correct for IBM long double
4730 ;; when little-endian.
4731 (define_expand "signbit<mode>2"
4732 [(set (match_dup 2)
4733 (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))
4734 (set (match_dup 3)
4735 (subreg:DI (match_dup 2) 0))
4736 (set (match_dup 4)
4737 (match_dup 5))
4738 (set (match_operand:SI 0 "gpc_reg_operand" "")
4739 (match_dup 6))]
4740 "TARGET_HARD_FLOAT
4741 && (TARGET_FPRS || TARGET_E500_DOUBLE)
4742 && (!FLOAT128_IEEE_P (<MODE>mode)
4743 || (TARGET_POWERPC64 && TARGET_DIRECT_MOVE))"
4744 {
4745 if (FLOAT128_IEEE_P (<MODE>mode))
4746 {
4747 if (<MODE>mode == KFmode)
4748 emit_insn (gen_signbitkf2_dm (operands[0], operands[1]));
4749 else if (<MODE>mode == TFmode)
4750 emit_insn (gen_signbittf2_dm (operands[0], operands[1]));
4751 else
4752 gcc_unreachable ();
4753 DONE;
4754 }
4755 operands[2] = gen_reg_rtx (DFmode);
4756 operands[3] = gen_reg_rtx (DImode);
4757 if (TARGET_POWERPC64)
4758 {
4759 operands[4] = gen_reg_rtx (DImode);
4760 operands[5] = gen_rtx_LSHIFTRT (DImode, operands[3], GEN_INT (63));
4761 operands[6] = gen_rtx_SUBREG (SImode, operands[4],
4762 WORDS_BIG_ENDIAN ? 4 : 0);
4763 }
4764 else
4765 {
4766 operands[4] = gen_reg_rtx (SImode);
4767 operands[5] = gen_rtx_SUBREG (SImode, operands[3],
4768 WORDS_BIG_ENDIAN ? 0 : 4);
4769 operands[6] = gen_rtx_LSHIFTRT (SImode, operands[4], GEN_INT (31));
4770 }
4771 })
4772
4773 (define_expand "copysign<mode>3"
4774 [(set (match_dup 3)
4775 (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))
4776 (set (match_dup 4)
4777 (neg:SFDF (abs:SFDF (match_dup 1))))
4778 (set (match_operand:SFDF 0 "gpc_reg_operand" "")
4779 (if_then_else:SFDF (ge (match_operand:SFDF 2 "gpc_reg_operand" "")
4780 (match_dup 5))
4781 (match_dup 3)
4782 (match_dup 4)))]
4783 "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
4784 && ((TARGET_PPC_GFXOPT
4785 && !HONOR_NANS (<MODE>mode)
4786 && !HONOR_SIGNED_ZEROS (<MODE>mode))
4787 || TARGET_CMPB
4788 || VECTOR_UNIT_VSX_P (<MODE>mode))"
4789 {
4790 if (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))
4791 {
4792 emit_insn (gen_copysign<mode>3_fcpsgn (operands[0], operands[1],
4793 operands[2]));
4794 DONE;
4795 }
4796
4797 operands[3] = gen_reg_rtx (<MODE>mode);
4798 operands[4] = gen_reg_rtx (<MODE>mode);
4799 operands[5] = CONST0_RTX (<MODE>mode);
4800 })
4801
4802 ;; Optimize signbit on 64-bit systems with direct move to avoid doing the store
4803 ;; and load.
4804 (define_insn_and_split "signbit<mode>2_dm"
4805 [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
4806 (unspec:SI
4807 [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")]
4808 UNSPEC_SIGNBIT))]
4809 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
4810 "#"
4811 "&& reload_completed"
4812 [(const_int 0)]
4813 {
4814 rs6000_split_signbit (operands[0], operands[1]);
4815 DONE;
4816 }
4817 [(set_attr "length" "8,8,4")
4818 (set_attr "type" "mftgpr,load,integer")])
4819
4820 (define_insn_and_split "*signbit<mode>2_dm_<su>ext"
4821 [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
4822 (any_extend:DI
4823 (unspec:SI
4824 [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")]
4825 UNSPEC_SIGNBIT)))]
4826 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
4827 "#"
4828 "&& reload_completed"
4829 [(const_int 0)]
4830 {
4831 rs6000_split_signbit (operands[0], operands[1]);
4832 DONE;
4833 }
4834 [(set_attr "length" "8,8,4")
4835 (set_attr "type" "mftgpr,load,integer")])
4836
4837 ;; TARGET_MODES_TIEABLE_P doesn't allow DImode to be tied with the various
4838 ;; floating point types, which makes normal SUBREG's problematical. Instead
4839 ;; use a special pattern to avoid using a normal movdi.
4840 (define_insn "signbit<mode>2_dm2"
4841 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
4842 (unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa")
4843 (const_int 0)]
4844 UNSPEC_SIGNBIT))]
4845 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
4846 "mfvsrd %0,%x1"
4847 [(set_attr "type" "mftgpr")])
4848
4849
4850 ;; Use an unspec rather providing an if-then-else in RTL, to prevent the
4851 ;; compiler from optimizing -0.0
4852 (define_insn "copysign<mode>3_fcpsgn"
4853 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
4854 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
4855 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")]
4856 UNSPEC_COPYSIGN))]
4857 "TARGET_<MODE>_FPR && (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))"
4858 "@
4859 fcpsgn %0,%2,%1
4860 xscpsgndp %x0,%x2,%x1"
4861 [(set_attr "type" "fpsimple")])
4862
4863 ;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
4864 ;; fsel instruction and some auxiliary computations. Then we just have a
4865 ;; single DEFINE_INSN for fsel and the define_splits to make them if made by
4866 ;; combine.
4867 ;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we
4868 ;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary
4869 ;; computations. Then we just have a single DEFINE_INSN for fsel and the
4870 ;; define_splits to make them if made by combine. On VSX machines we have the
4871 ;; min/max instructions.
4872 ;;
4873 ;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector
4874 ;; to allow either DF/SF to use only traditional registers.
4875
4876 (define_expand "s<minmax><mode>3"
4877 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4878 (fp_minmax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
4879 (match_operand:SFDF 2 "gpc_reg_operand" "")))]
4880 "TARGET_MINMAX_<MODE>"
4881 {
4882 rs6000_emit_minmax (operands[0], <SMINMAX>, operands[1], operands[2]);
4883 DONE;
4884 })
4885
4886 (define_insn "*s<minmax><mode>3_vsx"
4887 [(set (match_operand:SFDF 0 "vsx_register_operand" "=<Fv>")
4888 (fp_minmax:SFDF (match_operand:SFDF 1 "vsx_register_operand" "<Fv>")
4889 (match_operand:SFDF 2 "vsx_register_operand" "<Fv>")))]
4890 "TARGET_VSX && TARGET_<MODE>_FPR"
4891 {
4892 return (TARGET_P9_MINMAX
4893 ? "xs<minmax>cdp %x0,%x1,%x2"
4894 : "xs<minmax>dp %x0,%x1,%x2");
4895 }
4896 [(set_attr "type" "fp")])
4897
4898 ;; The conditional move instructions allow us to perform max and min operations
4899 ;; even when we don't have the appropriate max/min instruction using the FSEL
4900 ;; instruction.
4901
4902 (define_insn_and_split "*s<minmax><mode>3_fpr"
4903 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
4904 (fp_minmax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
4905 (match_operand:SFDF 2 "gpc_reg_operand" "")))]
4906 "!TARGET_VSX && TARGET_MINMAX_<MODE>"
4907 "#"
4908 "&& 1"
4909 [(const_int 0)]
4910 {
4911 rs6000_emit_minmax (operands[0], <SMINMAX>, operands[1], operands[2]);
4912 DONE;
4913 })
4914
4915 (define_expand "mov<mode>cc"
4916 [(set (match_operand:GPR 0 "gpc_reg_operand" "")
4917 (if_then_else:GPR (match_operand 1 "comparison_operator" "")
4918 (match_operand:GPR 2 "gpc_reg_operand" "")
4919 (match_operand:GPR 3 "gpc_reg_operand" "")))]
4920 "TARGET_ISEL<sel>"
4921 "
4922 {
4923 if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
4924 DONE;
4925 else
4926 FAIL;
4927 }")
4928
4929 ;; We use the BASE_REGS for the isel input operands because, if rA is
4930 ;; 0, the value of 0 is placed in rD upon truth. Similarly for rB
4931 ;; because we may switch the operands and rB may end up being rA.
4932 ;;
4933 ;; We need 2 patterns: an unsigned and a signed pattern. We could
4934 ;; leave out the mode in operand 4 and use one pattern, but reload can
4935 ;; change the mode underneath our feet and then gets confused trying
4936 ;; to reload the value.
4937 (define_insn "isel_signed_<mode>"
4938 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
4939 (if_then_else:GPR
4940 (match_operator 1 "scc_comparison_operator"
4941 [(match_operand:CC 4 "cc_reg_operand" "y,y")
4942 (const_int 0)])
4943 (match_operand:GPR 2 "reg_or_cint_operand" "O,b")
4944 (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
4945 "TARGET_ISEL<sel>"
4946 "*
4947 { return output_isel (operands); }"
4948 [(set_attr "type" "isel")
4949 (set_attr "length" "4")])
4950
4951 (define_insn "isel_unsigned_<mode>"
4952 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
4953 (if_then_else:GPR
4954 (match_operator 1 "scc_comparison_operator"
4955 [(match_operand:CCUNS 4 "cc_reg_operand" "y,y")
4956 (const_int 0)])
4957 (match_operand:GPR 2 "reg_or_cint_operand" "O,b")
4958 (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
4959 "TARGET_ISEL<sel>"
4960 "*
4961 { return output_isel (operands); }"
4962 [(set_attr "type" "isel")
4963 (set_attr "length" "4")])
4964
4965 ;; These patterns can be useful for combine; they let combine know that
4966 ;; isel can handle reversed comparisons so long as the operands are
4967 ;; registers.
4968
4969 (define_insn "*isel_reversed_signed_<mode>"
4970 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4971 (if_then_else:GPR
4972 (match_operator 1 "scc_rev_comparison_operator"
4973 [(match_operand:CC 4 "cc_reg_operand" "y")
4974 (const_int 0)])
4975 (match_operand:GPR 2 "gpc_reg_operand" "b")
4976 (match_operand:GPR 3 "gpc_reg_operand" "b")))]
4977 "TARGET_ISEL<sel>"
4978 "*
4979 { return output_isel (operands); }"
4980 [(set_attr "type" "isel")
4981 (set_attr "length" "4")])
4982
4983 (define_insn "*isel_reversed_unsigned_<mode>"
4984 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
4985 (if_then_else:GPR
4986 (match_operator 1 "scc_rev_comparison_operator"
4987 [(match_operand:CCUNS 4 "cc_reg_operand" "y")
4988 (const_int 0)])
4989 (match_operand:GPR 2 "gpc_reg_operand" "b")
4990 (match_operand:GPR 3 "gpc_reg_operand" "b")))]
4991 "TARGET_ISEL<sel>"
4992 "*
4993 { return output_isel (operands); }"
4994 [(set_attr "type" "isel")
4995 (set_attr "length" "4")])
4996
4997 ;; Floating point conditional move
4998 (define_expand "mov<mode>cc"
4999 [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
5000 (if_then_else:SFDF (match_operand 1 "comparison_operator" "")
5001 (match_operand:SFDF 2 "gpc_reg_operand" "")
5002 (match_operand:SFDF 3 "gpc_reg_operand" "")))]
5003 "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT"
5004 "
5005 {
5006 if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
5007 DONE;
5008 else
5009 FAIL;
5010 }")
5011
5012 (define_insn "*fsel<SFDF:mode><SFDF2:mode>4"
5013 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=&<SFDF:rreg2>")
5014 (if_then_else:SFDF
5015 (ge (match_operand:SFDF2 1 "gpc_reg_operand" "<SFDF2:rreg2>")
5016 (match_operand:SFDF2 4 "zero_fp_constant" "F"))
5017 (match_operand:SFDF 2 "gpc_reg_operand" "<SFDF:rreg2>")
5018 (match_operand:SFDF 3 "gpc_reg_operand" "<SFDF:rreg2>")))]
5019 "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT"
5020 "fsel %0,%1,%2,%3"
5021 [(set_attr "type" "fp")])
5022
5023 (define_insn_and_split "*mov<SFDF:mode><SFDF2:mode>cc_p9"
5024 [(set (match_operand:SFDF 0 "vsx_register_operand" "=&<SFDF:Fv>,<SFDF:Fv>")
5025 (if_then_else:SFDF
5026 (match_operator:CCFP 1 "fpmask_comparison_operator"
5027 [(match_operand:SFDF2 2 "vsx_register_operand" "<SFDF2:Fv>,<SFDF2:Fv>")
5028 (match_operand:SFDF2 3 "vsx_register_operand" "<SFDF2:Fv>,<SFDF2:Fv>")])
5029 (match_operand:SFDF 4 "vsx_register_operand" "<SFDF:Fv>,<SFDF:Fv>")
5030 (match_operand:SFDF 5 "vsx_register_operand" "<SFDF:Fv>,<SFDF:Fv>")))
5031 (clobber (match_scratch:V2DI 6 "=0,&wa"))]
5032 "TARGET_P9_MINMAX"
5033 "#"
5034 ""
5035 [(set (match_dup 6)
5036 (if_then_else:V2DI (match_dup 1)
5037 (match_dup 7)
5038 (match_dup 8)))
5039 (set (match_dup 0)
5040 (if_then_else:SFDF (ne (match_dup 6)
5041 (match_dup 8))
5042 (match_dup 4)
5043 (match_dup 5)))]
5044 {
5045 if (GET_CODE (operands[6]) == SCRATCH)
5046 operands[6] = gen_reg_rtx (V2DImode);
5047
5048 operands[7] = CONSTM1_RTX (V2DImode);
5049 operands[8] = CONST0_RTX (V2DImode);
5050 }
5051 [(set_attr "length" "8")
5052 (set_attr "type" "vecperm")])
5053
5054 ;; Handle inverting the fpmask comparisons.
5055 (define_insn_and_split "*mov<SFDF:mode><SFDF2:mode>cc_invert_p9"
5056 [(set (match_operand:SFDF 0 "vsx_register_operand" "=&<SFDF:Fv>,<SFDF:Fv>")
5057 (if_then_else:SFDF
5058 (match_operator:CCFP 1 "invert_fpmask_comparison_operator"
5059 [(match_operand:SFDF2 2 "vsx_register_operand" "<SFDF2:Fv>,<SFDF2:Fv>")
5060 (match_operand:SFDF2 3 "vsx_register_operand" "<SFDF2:Fv>,<SFDF2:Fv>")])
5061 (match_operand:SFDF 4 "vsx_register_operand" "<SFDF:Fv>,<SFDF:Fv>")
5062 (match_operand:SFDF 5 "vsx_register_operand" "<SFDF:Fv>,<SFDF:Fv>")))
5063 (clobber (match_scratch:V2DI 6 "=0,&wa"))]
5064 "TARGET_P9_MINMAX"
5065 "#"
5066 "&& 1"
5067 [(set (match_dup 6)
5068 (if_then_else:V2DI (match_dup 9)
5069 (match_dup 7)
5070 (match_dup 8)))
5071 (set (match_dup 0)
5072 (if_then_else:SFDF (ne (match_dup 6)
5073 (match_dup 8))
5074 (match_dup 5)
5075 (match_dup 4)))]
5076 {
5077 rtx op1 = operands[1];
5078 enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1));
5079
5080 if (GET_CODE (operands[6]) == SCRATCH)
5081 operands[6] = gen_reg_rtx (V2DImode);
5082
5083 operands[7] = CONSTM1_RTX (V2DImode);
5084 operands[8] = CONST0_RTX (V2DImode);
5085
5086 operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]);
5087 }
5088 [(set_attr "length" "8")
5089 (set_attr "type" "vecperm")])
5090
5091 (define_insn "*fpmask<mode>"
5092 [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
5093 (if_then_else:V2DI
5094 (match_operator:CCFP 1 "fpmask_comparison_operator"
5095 [(match_operand:SFDF 2 "vsx_register_operand" "<Fv>")
5096 (match_operand:SFDF 3 "vsx_register_operand" "<Fv>")])
5097 (match_operand:V2DI 4 "all_ones_constant" "")
5098 (match_operand:V2DI 5 "zero_constant" "")))]
5099 "TARGET_P9_MINMAX"
5100 "xscmp%V1dp %x0,%x2,%x3"
5101 [(set_attr "type" "fpcompare")])
5102
5103 (define_insn "*xxsel<mode>"
5104 [(set (match_operand:SFDF 0 "vsx_register_operand" "=<Fv>")
5105 (if_then_else:SFDF (ne (match_operand:V2DI 1 "vsx_register_operand" "wa")
5106 (match_operand:V2DI 2 "zero_constant" ""))
5107 (match_operand:SFDF 3 "vsx_register_operand" "<Fv>")
5108 (match_operand:SFDF 4 "vsx_register_operand" "<Fv>")))]
5109 "TARGET_P9_MINMAX"
5110 "xxsel %x0,%x4,%x3,%x1"
5111 [(set_attr "type" "vecmove")])
5112
5113 \f
5114 ;; Conversions to and from floating-point.
5115
5116 ; We don't define lfiwax/lfiwzx with the normal definition, because we
5117 ; don't want to support putting SImode in FPR registers.
5118 (define_insn "lfiwax"
5119 [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,wj,wK")
5120 (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wK")]
5121 UNSPEC_LFIWAX))]
5122 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX"
5123 "@
5124 lfiwax %0,%y1
5125 lxsiwax %x0,%y1
5126 mtvsrwa %x0,%1
5127 vextsw2d %0,%1"
5128 [(set_attr "type" "fpload,fpload,mffgpr,vecexts")])
5129
5130 ; This split must be run before register allocation because it allocates the
5131 ; memory slot that is needed to move values to/from the FPR. We don't allocate
5132 ; it earlier to allow for the combiner to merge insns together where it might
5133 ; not be needed and also in case the insns are deleted as dead code.
5134
5135 (define_insn_and_split "floatsi<mode>2_lfiwax"
5136 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
5137 (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
5138 (clobber (match_scratch:DI 2 "=wi"))]
5139 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
5140 && <SI_CONVERT_FP> && can_create_pseudo_p ()"
5141 "#"
5142 ""
5143 [(pc)]
5144 "
5145 {
5146 rtx dest = operands[0];
5147 rtx src = operands[1];
5148 rtx tmp;
5149
5150 if (!MEM_P (src) && TARGET_POWERPC64
5151 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
5152 tmp = convert_to_mode (DImode, src, false);
5153 else
5154 {
5155 tmp = operands[2];
5156 if (GET_CODE (tmp) == SCRATCH)
5157 tmp = gen_reg_rtx (DImode);
5158 if (MEM_P (src))
5159 {
5160 src = rs6000_address_for_fpconvert (src);
5161 emit_insn (gen_lfiwax (tmp, src));
5162 }
5163 else
5164 {
5165 rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
5166 emit_move_insn (stack, src);
5167 emit_insn (gen_lfiwax (tmp, stack));
5168 }
5169 }
5170 emit_insn (gen_floatdi<mode>2 (dest, tmp));
5171 DONE;
5172 }"
5173 [(set_attr "length" "12")
5174 (set_attr "type" "fpload")])
5175
5176 (define_insn_and_split "floatsi<mode>2_lfiwax_mem"
5177 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
5178 (float:SFDF
5179 (sign_extend:DI
5180 (match_operand:SI 1 "indexed_or_indirect_operand" "Z"))))
5181 (clobber (match_scratch:DI 2 "=wi"))]
5182 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX
5183 && <SI_CONVERT_FP>"
5184 "#"
5185 ""
5186 [(pc)]
5187 "
5188 {
5189 operands[1] = rs6000_address_for_fpconvert (operands[1]);
5190 if (GET_CODE (operands[2]) == SCRATCH)
5191 operands[2] = gen_reg_rtx (DImode);
5192 if (TARGET_VSX_SMALL_INTEGER)
5193 emit_insn (gen_extendsidi2 (operands[2], operands[1]));
5194 else
5195 emit_insn (gen_lfiwax (operands[2], operands[1]));
5196 emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
5197 DONE;
5198 }"
5199 [(set_attr "length" "8")
5200 (set_attr "type" "fpload")])
5201
5202 (define_insn "lfiwzx"
5203 [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,wj,wJwK")
5204 (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wJwK")]
5205 UNSPEC_LFIWZX))]
5206 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX"
5207 "@
5208 lfiwzx %0,%y1
5209 lxsiwzx %x0,%y1
5210 mtvsrwz %x0,%1
5211 xxextractuw %x0,%x1,4"
5212 [(set_attr "type" "fpload,fpload,mftgpr,vecexts")])
5213
5214 (define_insn_and_split "floatunssi<mode>2_lfiwzx"
5215 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
5216 (unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
5217 (clobber (match_scratch:DI 2 "=wi"))]
5218 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
5219 && <SI_CONVERT_FP>"
5220 "#"
5221 ""
5222 [(pc)]
5223 "
5224 {
5225 rtx dest = operands[0];
5226 rtx src = operands[1];
5227 rtx tmp;
5228
5229 if (!MEM_P (src) && TARGET_POWERPC64
5230 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
5231 tmp = convert_to_mode (DImode, src, true);
5232 else
5233 {
5234 tmp = operands[2];
5235 if (GET_CODE (tmp) == SCRATCH)
5236 tmp = gen_reg_rtx (DImode);
5237 if (MEM_P (src))
5238 {
5239 src = rs6000_address_for_fpconvert (src);
5240 emit_insn (gen_lfiwzx (tmp, src));
5241 }
5242 else
5243 {
5244 rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
5245 emit_move_insn (stack, src);
5246 emit_insn (gen_lfiwzx (tmp, stack));
5247 }
5248 }
5249 emit_insn (gen_floatdi<mode>2 (dest, tmp));
5250 DONE;
5251 }"
5252 [(set_attr "length" "12")
5253 (set_attr "type" "fpload")])
5254
5255 (define_insn_and_split "floatunssi<mode>2_lfiwzx_mem"
5256 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
5257 (unsigned_float:SFDF
5258 (zero_extend:DI
5259 (match_operand:SI 1 "indexed_or_indirect_operand" "Z"))))
5260 (clobber (match_scratch:DI 2 "=wi"))]
5261 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX
5262 && <SI_CONVERT_FP>"
5263 "#"
5264 ""
5265 [(pc)]
5266 "
5267 {
5268 operands[1] = rs6000_address_for_fpconvert (operands[1]);
5269 if (GET_CODE (operands[2]) == SCRATCH)
5270 operands[2] = gen_reg_rtx (DImode);
5271 if (TARGET_VSX_SMALL_INTEGER)
5272 emit_insn (gen_zero_extendsidi2 (operands[2], operands[1]));
5273 else
5274 emit_insn (gen_lfiwzx (operands[2], operands[1]));
5275 emit_insn (gen_floatdi<mode>2 (operands[0], operands[2]));
5276 DONE;
5277 }"
5278 [(set_attr "length" "8")
5279 (set_attr "type" "fpload")])
5280
5281 ; For each of these conversions, there is a define_expand, a define_insn
5282 ; with a '#' template, and a define_split (with C code). The idea is
5283 ; to allow constant folding with the template of the define_insn,
5284 ; then to have the insns split later (between sched1 and final).
5285
5286 (define_expand "floatsidf2"
5287 [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
5288 (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
5289 (use (match_dup 2))
5290 (use (match_dup 3))
5291 (clobber (match_dup 4))
5292 (clobber (match_dup 5))
5293 (clobber (match_dup 6))])]
5294 "TARGET_HARD_FLOAT
5295 && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
5296 "
5297 {
5298 if (TARGET_E500_DOUBLE)
5299 {
5300 if (!REG_P (operands[1]))
5301 operands[1] = force_reg (SImode, operands[1]);
5302 emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
5303 DONE;
5304 }
5305 else if (TARGET_LFIWAX && TARGET_FCFID)
5306 {
5307 emit_insn (gen_floatsidf2_lfiwax (operands[0], operands[1]));
5308 DONE;
5309 }
5310 else if (TARGET_FCFID)
5311 {
5312 rtx dreg = operands[1];
5313 if (!REG_P (dreg))
5314 dreg = force_reg (SImode, dreg);
5315 dreg = convert_to_mode (DImode, dreg, false);
5316 emit_insn (gen_floatdidf2 (operands[0], dreg));
5317 DONE;
5318 }
5319
5320 if (!REG_P (operands[1]))
5321 operands[1] = force_reg (SImode, operands[1]);
5322 operands[2] = force_reg (SImode, GEN_INT (0x43300000));
5323 operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode));
5324 operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
5325 operands[5] = gen_reg_rtx (DFmode);
5326 operands[6] = gen_reg_rtx (SImode);
5327 }")
5328
5329 (define_insn_and_split "*floatsidf2_internal"
5330 [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
5331 (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
5332 (use (match_operand:SI 2 "gpc_reg_operand" "r"))
5333 (use (match_operand:DF 3 "gpc_reg_operand" "d"))
5334 (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
5335 (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))
5336 (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
5337 "! TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
5338 "#"
5339 ""
5340 [(pc)]
5341 "
5342 {
5343 rtx lowword, highword;
5344 gcc_assert (MEM_P (operands[4]));
5345 highword = adjust_address (operands[4], SImode, 0);
5346 lowword = adjust_address (operands[4], SImode, 4);
5347 if (! WORDS_BIG_ENDIAN)
5348 std::swap (lowword, highword);
5349
5350 emit_insn (gen_xorsi3 (operands[6], operands[1],
5351 GEN_INT (~ (HOST_WIDE_INT) 0x7fffffff)));
5352 emit_move_insn (lowword, operands[6]);
5353 emit_move_insn (highword, operands[2]);
5354 emit_move_insn (operands[5], operands[4]);
5355 emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
5356 DONE;
5357 }"
5358 [(set_attr "length" "24")
5359 (set_attr "type" "fp")])
5360
5361 ;; If we don't have a direct conversion to single precision, don't enable this
5362 ;; conversion for 32-bit without fast math, because we don't have the insn to
5363 ;; generate the fixup swizzle to avoid double rounding problems.
5364 (define_expand "floatunssisf2"
5365 [(set (match_operand:SF 0 "gpc_reg_operand" "")
5366 (unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
5367 "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
5368 && (!TARGET_FPRS
5369 || (TARGET_FPRS
5370 && ((TARGET_FCFIDUS && TARGET_LFIWZX)
5371 || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
5372 && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
5373 "
5374 {
5375 if (!TARGET_FPRS)
5376 {
5377 if (!REG_P (operands[1]))
5378 operands[1] = force_reg (SImode, operands[1]);
5379 }
5380 else if (TARGET_LFIWZX && TARGET_FCFIDUS)
5381 {
5382 emit_insn (gen_floatunssisf2_lfiwzx (operands[0], operands[1]));
5383 DONE;
5384 }
5385 else
5386 {
5387 rtx dreg = operands[1];
5388 if (!REG_P (dreg))
5389 dreg = force_reg (SImode, dreg);
5390 dreg = convert_to_mode (DImode, dreg, true);
5391 emit_insn (gen_floatdisf2 (operands[0], dreg));
5392 DONE;
5393 }
5394 }")
5395
5396 (define_expand "floatunssidf2"
5397 [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
5398 (unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
5399 (use (match_dup 2))
5400 (use (match_dup 3))
5401 (clobber (match_dup 4))
5402 (clobber (match_dup 5))])]
5403 "TARGET_HARD_FLOAT
5404 && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
5405 "
5406 {
5407 if (TARGET_E500_DOUBLE)
5408 {
5409 if (!REG_P (operands[1]))
5410 operands[1] = force_reg (SImode, operands[1]);
5411 emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
5412 DONE;
5413 }
5414 else if (TARGET_LFIWZX && TARGET_FCFID)
5415 {
5416 emit_insn (gen_floatunssidf2_lfiwzx (operands[0], operands[1]));
5417 DONE;
5418 }
5419 else if (TARGET_FCFID)
5420 {
5421 rtx dreg = operands[1];
5422 if (!REG_P (dreg))
5423 dreg = force_reg (SImode, dreg);
5424 dreg = convert_to_mode (DImode, dreg, true);
5425 emit_insn (gen_floatdidf2 (operands[0], dreg));
5426 DONE;
5427 }
5428
5429 if (!REG_P (operands[1]))
5430 operands[1] = force_reg (SImode, operands[1]);
5431 operands[2] = force_reg (SImode, GEN_INT (0x43300000));
5432 operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode));
5433 operands[4] = rs6000_allocate_stack_temp (DFmode, true, false);
5434 operands[5] = gen_reg_rtx (DFmode);
5435 }")
5436
5437 (define_insn_and_split "*floatunssidf2_internal"
5438 [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
5439 (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
5440 (use (match_operand:SI 2 "gpc_reg_operand" "r"))
5441 (use (match_operand:DF 3 "gpc_reg_operand" "d"))
5442 (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
5443 (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
5444 "! TARGET_FCFIDU && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5445 && !(TARGET_FCFID && TARGET_POWERPC64)"
5446 "#"
5447 ""
5448 [(pc)]
5449 "
5450 {
5451 rtx lowword, highword;
5452 gcc_assert (MEM_P (operands[4]));
5453 highword = adjust_address (operands[4], SImode, 0);
5454 lowword = adjust_address (operands[4], SImode, 4);
5455 if (! WORDS_BIG_ENDIAN)
5456 std::swap (lowword, highword);
5457
5458 emit_move_insn (lowword, operands[1]);
5459 emit_move_insn (highword, operands[2]);
5460 emit_move_insn (operands[5], operands[4]);
5461 emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
5462 DONE;
5463 }"
5464 [(set_attr "length" "20")
5465 (set_attr "type" "fp")])
5466
5467 ;; ISA 3.0 adds instructions lxsi[bh]zx to directly load QImode and HImode to
5468 ;; vector registers. These insns favor doing the sign/zero extension in
5469 ;; the vector registers, rather then loading up a GPR, doing a sign/zero
5470 ;; extension and then a direct move.
5471
5472 (define_expand "float<QHI:mode><FP_ISA3:mode>2"
5473 [(parallel [(set (match_operand:FP_ISA3 0 "vsx_register_operand")
5474 (float:FP_ISA3
5475 (match_operand:QHI 1 "input_operand")))
5476 (clobber (match_scratch:DI 2))
5477 (clobber (match_scratch:DI 3))
5478 (clobber (match_scratch:<QHI:MODE> 4))])]
5479 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
5480 && TARGET_VSX_SMALL_INTEGER"
5481 {
5482 if (MEM_P (operands[1]))
5483 operands[1] = rs6000_address_for_fpconvert (operands[1]);
5484 })
5485
5486 (define_insn_and_split "*float<QHI:mode><FP_ISA3:mode>2_internal"
5487 [(set (match_operand:FP_ISA3 0 "vsx_register_operand" "=<Fv>,<Fv>,<Fv>")
5488 (float:FP_ISA3
5489 (match_operand:QHI 1 "reg_or_indexed_operand" "wK,r,Z")))
5490 (clobber (match_scratch:DI 2 "=wK,wi,wK"))
5491 (clobber (match_scratch:DI 3 "=X,r,X"))
5492 (clobber (match_scratch:<QHI:MODE> 4 "=X,X,wK"))]
5493 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
5494 && TARGET_UPPER_REGS_DI && TARGET_VSX_SMALL_INTEGER"
5495 "#"
5496 "&& reload_completed"
5497 [(const_int 0)]
5498 {
5499 rtx result = operands[0];
5500 rtx input = operands[1];
5501 rtx di = operands[2];
5502
5503 if (!MEM_P (input))
5504 {
5505 rtx tmp = operands[3];
5506 if (altivec_register_operand (input, <QHI:MODE>mode))
5507 emit_insn (gen_extend<QHI:mode>di2 (di, input));
5508 else if (GET_CODE (tmp) == SCRATCH)
5509 emit_insn (gen_extend<QHI:mode>di2 (di, input));
5510 else
5511 {
5512 emit_insn (gen_extend<QHI:mode>di2 (tmp, input));
5513 emit_move_insn (di, tmp);
5514 }
5515 }
5516 else
5517 {
5518 rtx tmp = operands[4];
5519 emit_move_insn (tmp, input);
5520 emit_insn (gen_extend<QHI:mode>di2 (di, tmp));
5521 }
5522
5523 emit_insn (gen_floatdi<FP_ISA3:mode>2 (result, di));
5524 DONE;
5525 })
5526
5527 (define_expand "floatuns<QHI:mode><FP_ISA3:mode>2"
5528 [(parallel [(set (match_operand:FP_ISA3 0 "vsx_register_operand")
5529 (unsigned_float:FP_ISA3
5530 (match_operand:QHI 1 "input_operand" "")))
5531 (clobber (match_scratch:DI 2 ""))
5532 (clobber (match_scratch:DI 3 ""))])]
5533 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
5534 && TARGET_VSX_SMALL_INTEGER"
5535 {
5536 if (MEM_P (operands[1]))
5537 operands[1] = rs6000_address_for_fpconvert (operands[1]);
5538 })
5539
5540 (define_insn_and_split "*floatuns<QHI:mode><FP_ISA3:mode>2_internal"
5541 [(set (match_operand:FP_ISA3 0 "vsx_register_operand" "=<Fv>,<Fv>,<Fv>")
5542 (unsigned_float:FP_ISA3
5543 (match_operand:QHI 1 "reg_or_indexed_operand" "wK,r,Z")))
5544 (clobber (match_scratch:DI 2 "=wK,wi,wJwK"))
5545 (clobber (match_scratch:DI 3 "=X,r,X"))]
5546 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
5547 && TARGET_VSX_SMALL_INTEGER"
5548 "#"
5549 "&& reload_completed"
5550 [(const_int 0)]
5551 {
5552 rtx result = operands[0];
5553 rtx input = operands[1];
5554 rtx di = operands[2];
5555
5556 if (MEM_P (input) || altivec_register_operand (input, <QHI:MODE>mode))
5557 emit_insn (gen_zero_extend<QHI:mode>di2 (di, input));
5558 else
5559 {
5560 rtx tmp = operands[3];
5561 if (GET_CODE (tmp) == SCRATCH)
5562 emit_insn (gen_extend<QHI:mode>di2 (di, input));
5563 else
5564 {
5565 emit_insn (gen_zero_extend<QHI:mode>di2 (tmp, input));
5566 emit_move_insn (di, tmp);
5567 }
5568 }
5569
5570 emit_insn (gen_floatdi<FP_ISA3:mode>2 (result, di));
5571 DONE;
5572 })
5573
5574 (define_expand "fix_trunc<mode>si2"
5575 [(set (match_operand:SI 0 "gpc_reg_operand" "")
5576 (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
5577 "TARGET_HARD_FLOAT && ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
5578 "
5579 {
5580 if (!<E500_CONVERT> && !TARGET_VSX_SMALL_INTEGER)
5581 {
5582 rtx src = force_reg (<MODE>mode, operands[1]);
5583
5584 if (TARGET_STFIWX)
5585 emit_insn (gen_fix_trunc<mode>si2_stfiwx (operands[0], src));
5586 else
5587 {
5588 rtx tmp = gen_reg_rtx (DImode);
5589 rtx stack = rs6000_allocate_stack_temp (DImode, true, false);
5590 emit_insn (gen_fix_trunc<mode>si2_internal (operands[0], src,
5591 tmp, stack));
5592 }
5593 DONE;
5594 }
5595 }")
5596
5597 ; Like the convert to float patterns, this insn must be split before
5598 ; register allocation so that it can allocate the memory slot if it
5599 ; needed
5600 (define_insn_and_split "fix_trunc<mode>si2_stfiwx"
5601 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5602 (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
5603 (clobber (match_scratch:DI 2 "=d"))]
5604 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5605 && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
5606 && TARGET_STFIWX && can_create_pseudo_p ()
5607 && !TARGET_VSX_SMALL_INTEGER"
5608 "#"
5609 ""
5610 [(pc)]
5611 {
5612 rtx dest = operands[0];
5613 rtx src = operands[1];
5614 rtx tmp = operands[2];
5615
5616 if (GET_CODE (tmp) == SCRATCH)
5617 tmp = gen_reg_rtx (DImode);
5618
5619 emit_insn (gen_fctiwz_<mode> (tmp, src));
5620 if (MEM_P (dest))
5621 {
5622 dest = rs6000_address_for_fpconvert (dest);
5623 emit_insn (gen_stfiwx (dest, tmp));
5624 DONE;
5625 }
5626 else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
5627 {
5628 dest = gen_lowpart (DImode, dest);
5629 emit_move_insn (dest, tmp);
5630 DONE;
5631 }
5632 else
5633 {
5634 rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
5635 emit_insn (gen_stfiwx (stack, tmp));
5636 emit_move_insn (dest, stack);
5637 DONE;
5638 }
5639 }
5640 [(set_attr "length" "12")
5641 (set_attr "type" "fp")])
5642
5643 (define_insn_and_split "fix_trunc<mode>si2_internal"
5644 [(set (match_operand:SI 0 "gpc_reg_operand" "=r,?r")
5645 (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>")))
5646 (clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d"))
5647 (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))]
5648 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5649 && !TARGET_VSX_SMALL_INTEGER"
5650 "#"
5651 ""
5652 [(pc)]
5653 "
5654 {
5655 rtx lowword;
5656 gcc_assert (MEM_P (operands[3]));
5657 lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
5658
5659 emit_insn (gen_fctiwz_<mode> (operands[2], operands[1]));
5660 emit_move_insn (operands[3], operands[2]);
5661 emit_move_insn (operands[0], lowword);
5662 DONE;
5663 }"
5664 [(set_attr "length" "16")
5665 (set_attr "type" "fp")])
5666
5667 (define_expand "fix_trunc<mode>di2"
5668 [(set (match_operand:DI 0 "gpc_reg_operand" "")
5669 (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
5670 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
5671 && TARGET_FCFID"
5672 "")
5673
5674 (define_insn "*fix_trunc<mode>di2_fctidz"
5675 [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
5676 (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
5677 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
5678 && TARGET_FCFID"
5679 "@
5680 fctidz %0,%1
5681 xscvdpsxds %x0,%x1"
5682 [(set_attr "type" "fp")])
5683
5684 (define_expand "fix_trunc<SFDF:mode><QHI:mode>2"
5685 [(parallel [(set (match_operand:<QHI:MODE> 0 "nonimmediate_operand")
5686 (fix:QHI (match_operand:SFDF 1 "gpc_reg_operand")))
5687 (clobber (match_scratch:DI 2))])]
5688 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
5689 && TARGET_VSX_SMALL_INTEGER"
5690 {
5691 if (MEM_P (operands[0]))
5692 operands[0] = rs6000_address_for_fpconvert (operands[0]);
5693 })
5694
5695 (define_insn_and_split "*fix_trunc<SFDF:mode><QHI:mode>2_internal"
5696 [(set (match_operand:<QHI:MODE> 0 "reg_or_indexed_operand" "=wIwJ,rZ")
5697 (fix:QHI
5698 (match_operand:SFDF 1 "gpc_reg_operand" "<SFDF:Fv>,<SFDF:Fv>")))
5699 (clobber (match_scratch:DI 2 "=X,wi"))]
5700 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
5701 && TARGET_VSX_SMALL_INTEGER"
5702 "#"
5703 "&& reload_completed"
5704 [(const_int 0)]
5705 {
5706 rtx dest = operands[0];
5707 rtx src = operands[1];
5708
5709 if (vsx_register_operand (dest, <QHI:MODE>mode))
5710 {
5711 rtx di_dest = gen_rtx_REG (DImode, REGNO (dest));
5712 emit_insn (gen_fix_trunc<SFDF:mode>di2 (di_dest, src));
5713 }
5714 else
5715 {
5716 rtx tmp = operands[2];
5717 rtx tmp2 = gen_rtx_REG (<QHI:MODE>mode, REGNO (tmp));
5718
5719 emit_insn (gen_fix_trunc<SFDF:mode>di2 (tmp, src));
5720 emit_move_insn (dest, tmp2);
5721 }
5722 DONE;
5723 })
5724
5725 (define_expand "fixuns_trunc<mode>si2"
5726 [(set (match_operand:SI 0 "gpc_reg_operand" "")
5727 (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))]
5728 "TARGET_HARD_FLOAT
5729 && ((TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX)
5730 || <E500_CONVERT>)"
5731 "
5732 {
5733 if (!<E500_CONVERT> && !TARGET_VSX_SMALL_INTEGER)
5734 {
5735 emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1]));
5736 DONE;
5737 }
5738 }")
5739
5740 (define_insn_and_split "fixuns_trunc<mode>si2_stfiwx"
5741 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
5742 (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
5743 (clobber (match_scratch:DI 2 "=d"))]
5744 "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
5745 && TARGET_STFIWX && can_create_pseudo_p ()
5746 && !TARGET_VSX_SMALL_INTEGER"
5747 "#"
5748 ""
5749 [(pc)]
5750 {
5751 rtx dest = operands[0];
5752 rtx src = operands[1];
5753 rtx tmp = operands[2];
5754
5755 if (GET_CODE (tmp) == SCRATCH)
5756 tmp = gen_reg_rtx (DImode);
5757
5758 emit_insn (gen_fctiwuz_<mode> (tmp, src));
5759 if (MEM_P (dest))
5760 {
5761 dest = rs6000_address_for_fpconvert (dest);
5762 emit_insn (gen_stfiwx (dest, tmp));
5763 DONE;
5764 }
5765 else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
5766 {
5767 dest = gen_lowpart (DImode, dest);
5768 emit_move_insn (dest, tmp);
5769 DONE;
5770 }
5771 else
5772 {
5773 rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
5774 emit_insn (gen_stfiwx (stack, tmp));
5775 emit_move_insn (dest, stack);
5776 DONE;
5777 }
5778 }
5779 [(set_attr "length" "12")
5780 (set_attr "type" "fp")])
5781
5782 (define_insn "fixuns_trunc<mode>di2"
5783 [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
5784 (unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
5785 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && TARGET_FCTIDUZ"
5786 "@
5787 fctiduz %0,%1
5788 xscvdpuxds %x0,%x1"
5789 [(set_attr "type" "fp")])
5790
5791 (define_expand "fixuns_trunc<SFDF:mode><QHI:mode>2"
5792 [(parallel [(set (match_operand:<QHI:MODE> 0 "nonimmediate_operand")
5793 (unsigned_fix:QHI (match_operand:SFDF 1 "gpc_reg_operand")))
5794 (clobber (match_scratch:DI 2))])]
5795 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
5796 && TARGET_VSX_SMALL_INTEGER"
5797 {
5798 if (MEM_P (operands[0]))
5799 operands[0] = rs6000_address_for_fpconvert (operands[0]);
5800 })
5801
5802 (define_insn_and_split "*fixuns_trunc<SFDF:mode><QHI:mode>2_internal"
5803 [(set (match_operand:<QHI:MODE> 0 "reg_or_indexed_operand" "=wIwJ,rZ")
5804 (unsigned_fix:QHI
5805 (match_operand:SFDF 1 "gpc_reg_operand" "<SFDF:Fv>,<SFDF:Fv>")))
5806 (clobber (match_scratch:DI 2 "=X,wi"))]
5807 "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
5808 && TARGET_VSX_SMALL_INTEGER"
5809 "#"
5810 "&& reload_completed"
5811 [(const_int 0)]
5812 {
5813 rtx dest = operands[0];
5814 rtx src = operands[1];
5815
5816 if (vsx_register_operand (dest, <QHI:MODE>mode))
5817 {
5818 rtx di_dest = gen_rtx_REG (DImode, REGNO (dest));
5819 emit_insn (gen_fixuns_trunc<SFDF:mode>di2 (di_dest, src));
5820 }
5821 else
5822 {
5823 rtx tmp = operands[2];
5824 rtx tmp2 = gen_rtx_REG (<QHI:MODE>mode, REGNO (tmp));
5825
5826 emit_insn (gen_fixuns_trunc<SFDF:mode>di2 (tmp, src));
5827 emit_move_insn (dest, tmp2);
5828 }
5829 DONE;
5830 })
5831
5832 ;; If -mvsx-small-integer, we can represent the FIX operation directly. On
5833 ;; older machines, we have to use an UNSPEC to produce a SImode and move it
5834 ;; to another location, since SImode is not allowed in vector registers.
5835 (define_insn "*fctiw<u>z_<mode>_smallint"
5836 [(set (match_operand:SI 0 "vsx_register_operand" "=d,wi")
5837 (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
5838 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5839 && TARGET_VSX_SMALL_INTEGER"
5840 "@
5841 fctiw<u>z %0,%1
5842 xscvdp<su>xws %x0,%x1"
5843 [(set_attr "type" "fp")])
5844
5845 ;; Combiner pattern to prevent moving the result of converting a floating point
5846 ;; value to 32-bit integer to GPR in order to save it.
5847 (define_insn_and_split "*fctiw<u>z_<mode>_mem"
5848 [(set (match_operand:SI 0 "memory_operand" "=Z")
5849 (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "wa")))
5850 (clobber (match_scratch:SI 2 "=wa"))]
5851 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5852 && TARGET_VSX_SMALL_INTEGER"
5853 "#"
5854 "&& reload_completed"
5855 [(set (match_dup 2)
5856 (any_fix:SI (match_dup 1)))
5857 (set (match_dup 0)
5858 (match_dup 2))])
5859
5860 ;; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
5861 ;; rather than (set (subreg:SI (reg)) (fix:SI ...))
5862 ;; because the first makes it clear that operand 0 is not live
5863 ;; before the instruction.
5864 (define_insn "fctiwz_<mode>"
5865 [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
5866 (unspec:DI [(fix:SI
5867 (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
5868 UNSPEC_FCTIWZ))]
5869 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
5870 "@
5871 fctiwz %0,%1
5872 xscvdpsxws %x0,%x1"
5873 [(set_attr "type" "fp")])
5874
5875 (define_insn "fctiwuz_<mode>"
5876 [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
5877 (unspec:DI [(unsigned_fix:SI
5878 (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
5879 UNSPEC_FCTIWUZ))]
5880 "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ"
5881 "@
5882 fctiwuz %0,%1
5883 xscvdpuxws %x0,%x1"
5884 [(set_attr "type" "fp")])
5885
5886 ;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
5887 ;; since the friz instruction does not truncate the value if the floating
5888 ;; point value is < LONG_MIN or > LONG_MAX.
5889 (define_insn "*friz"
5890 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
5891 (float:DF (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d,ws"))))]
5892 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_FPRND
5893 && flag_unsafe_math_optimizations && !flag_trapping_math && TARGET_FRIZ"
5894 "@
5895 friz %0,%1
5896 xsrdpiz %x0,%x1"
5897 [(set_attr "type" "fp")])
5898
5899 ;; Opitmize converting SF/DFmode to signed SImode and back to SF/DFmode. This
5900 ;; optimization prevents on ISA 2.06 systems and earlier having to store the
5901 ;; value from the FPR/vector unit to the stack, load the value into a GPR, sign
5902 ;; extend it, store it back on the stack from the GPR, load it back into the
5903 ;; FP/vector unit to do the rounding. If we have direct move (ISA 2.07),
5904 ;; disable using store and load to sign/zero extend the value.
5905 (define_insn_and_split "*round32<mode>2_fprs"
5906 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
5907 (float:SFDF
5908 (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))))
5909 (clobber (match_scratch:DI 2 "=d"))
5910 (clobber (match_scratch:DI 3 "=d"))]
5911 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5912 && <SI_CONVERT_FP> && TARGET_LFIWAX && TARGET_STFIWX && TARGET_FCFID
5913 && !TARGET_DIRECT_MOVE && can_create_pseudo_p ()"
5914 "#"
5915 ""
5916 [(pc)]
5917 {
5918 rtx dest = operands[0];
5919 rtx src = operands[1];
5920 rtx tmp1 = operands[2];
5921 rtx tmp2 = operands[3];
5922 rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
5923
5924 if (GET_CODE (tmp1) == SCRATCH)
5925 tmp1 = gen_reg_rtx (DImode);
5926 if (GET_CODE (tmp2) == SCRATCH)
5927 tmp2 = gen_reg_rtx (DImode);
5928
5929 emit_insn (gen_fctiwz_<mode> (tmp1, src));
5930 emit_insn (gen_stfiwx (stack, tmp1));
5931 emit_insn (gen_lfiwax (tmp2, stack));
5932 emit_insn (gen_floatdi<mode>2 (dest, tmp2));
5933 DONE;
5934 }
5935 [(set_attr "type" "fpload")
5936 (set_attr "length" "16")])
5937
5938 (define_insn_and_split "*roundu32<mode>2_fprs"
5939 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d")
5940 (unsigned_float:SFDF
5941 (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))))
5942 (clobber (match_scratch:DI 2 "=d"))
5943 (clobber (match_scratch:DI 3 "=d"))]
5944 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
5945 && TARGET_LFIWZX && TARGET_STFIWX && TARGET_FCFIDU && !TARGET_DIRECT_MOVE
5946 && can_create_pseudo_p ()"
5947 "#"
5948 ""
5949 [(pc)]
5950 {
5951 rtx dest = operands[0];
5952 rtx src = operands[1];
5953 rtx tmp1 = operands[2];
5954 rtx tmp2 = operands[3];
5955 rtx stack = rs6000_allocate_stack_temp (SImode, false, true);
5956
5957 if (GET_CODE (tmp1) == SCRATCH)
5958 tmp1 = gen_reg_rtx (DImode);
5959 if (GET_CODE (tmp2) == SCRATCH)
5960 tmp2 = gen_reg_rtx (DImode);
5961
5962 emit_insn (gen_fctiwuz_<mode> (tmp1, src));
5963 emit_insn (gen_stfiwx (stack, tmp1));
5964 emit_insn (gen_lfiwzx (tmp2, stack));
5965 emit_insn (gen_floatdi<mode>2 (dest, tmp2));
5966 DONE;
5967 }
5968 [(set_attr "type" "fpload")
5969 (set_attr "length" "16")])
5970
5971 ;; No VSX equivalent to fctid
5972 (define_insn "lrint<mode>di2"
5973 [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
5974 (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
5975 UNSPEC_FCTID))]
5976 "TARGET_<MODE>_FPR && TARGET_FPRND"
5977 "fctid %0,%1"
5978 [(set_attr "type" "fp")])
5979
5980 (define_insn "btrunc<mode>2"
5981 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
5982 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
5983 UNSPEC_FRIZ))]
5984 "TARGET_<MODE>_FPR && TARGET_FPRND"
5985 "@
5986 friz %0,%1
5987 xsrdpiz %x0,%x1"
5988 [(set_attr "type" "fp")
5989 (set_attr "fp_type" "fp_addsub_<Fs>")])
5990
5991 (define_insn "ceil<mode>2"
5992 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
5993 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
5994 UNSPEC_FRIP))]
5995 "TARGET_<MODE>_FPR && TARGET_FPRND"
5996 "@
5997 frip %0,%1
5998 xsrdpip %x0,%x1"
5999 [(set_attr "type" "fp")
6000 (set_attr "fp_type" "fp_addsub_<Fs>")])
6001
6002 (define_insn "floor<mode>2"
6003 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
6004 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
6005 UNSPEC_FRIM))]
6006 "TARGET_<MODE>_FPR && TARGET_FPRND"
6007 "@
6008 frim %0,%1
6009 xsrdpim %x0,%x1"
6010 [(set_attr "type" "fp")
6011 (set_attr "fp_type" "fp_addsub_<Fs>")])
6012
6013 ;; No VSX equivalent to frin
6014 (define_insn "round<mode>2"
6015 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
6016 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
6017 UNSPEC_FRIN))]
6018 "TARGET_<MODE>_FPR && TARGET_FPRND"
6019 "frin %0,%1"
6020 [(set_attr "type" "fp")
6021 (set_attr "fp_type" "fp_addsub_<Fs>")])
6022
6023 (define_insn "*xsrdpi<mode>2"
6024 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
6025 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Fv>")]
6026 UNSPEC_XSRDPI))]
6027 "TARGET_<MODE>_FPR && TARGET_VSX"
6028 "xsrdpi %x0,%x1"
6029 [(set_attr "type" "fp")
6030 (set_attr "fp_type" "fp_addsub_<Fs>")])
6031
6032 (define_expand "lround<mode>di2"
6033 [(set (match_dup 2)
6034 (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
6035 UNSPEC_XSRDPI))
6036 (set (match_operand:DI 0 "gpc_reg_operand" "")
6037 (unspec:DI [(match_dup 2)]
6038 UNSPEC_FCTID))]
6039 "TARGET_<MODE>_FPR && TARGET_VSX"
6040 {
6041 operands[2] = gen_reg_rtx (<MODE>mode);
6042 })
6043
6044 ; An UNSPEC is used so we don't have to support SImode in FP registers.
6045 ; The 'wu' constraint is used for the 2nd alternative to ensure stxsiwx
6046 ; is only generated for Power8 or later.
6047 (define_insn "stfiwx"
6048 [(set (match_operand:SI 0 "memory_operand" "=Z,Z")
6049 (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d,wu")]
6050 UNSPEC_STFIWX))]
6051 "TARGET_PPC_GFXOPT"
6052 "@
6053 stfiwx %1,%y0
6054 stxsiwx %x1,%y0"
6055 [(set_attr "type" "fpstore")])
6056
6057 ;; If we don't have a direct conversion to single precision, don't enable this
6058 ;; conversion for 32-bit without fast math, because we don't have the insn to
6059 ;; generate the fixup swizzle to avoid double rounding problems.
6060 (define_expand "floatsisf2"
6061 [(set (match_operand:SF 0 "gpc_reg_operand" "")
6062 (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
6063 "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT
6064 && (!TARGET_FPRS
6065 || (TARGET_FPRS
6066 && ((TARGET_FCFIDS && TARGET_LFIWAX)
6067 || (TARGET_DOUBLE_FLOAT && TARGET_FCFID
6068 && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))))"
6069 "
6070 {
6071 if (!TARGET_FPRS)
6072 {
6073 if (!REG_P (operands[1]))
6074 operands[1] = force_reg (SImode, operands[1]);
6075 }
6076 else if (TARGET_FCFIDS && TARGET_LFIWAX)
6077 {
6078 emit_insn (gen_floatsisf2_lfiwax (operands[0], operands[1]));
6079 DONE;
6080 }
6081 else if (TARGET_FCFID && TARGET_LFIWAX)
6082 {
6083 rtx dfreg = gen_reg_rtx (DFmode);
6084 emit_insn (gen_floatsidf2_lfiwax (dfreg, operands[1]));
6085 emit_insn (gen_truncdfsf2 (operands[0], dfreg));
6086 DONE;
6087 }
6088 else
6089 {
6090 rtx dreg = operands[1];
6091 if (!REG_P (dreg))
6092 dreg = force_reg (SImode, dreg);
6093 dreg = convert_to_mode (DImode, dreg, false);
6094 emit_insn (gen_floatdisf2 (operands[0], dreg));
6095 DONE;
6096 }
6097 }")
6098
6099 (define_expand "floatdidf2"
6100 [(set (match_operand:DF 0 "gpc_reg_operand" "")
6101 (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
6102 "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
6103 "")
6104
6105 (define_insn "*floatdidf2_fpr"
6106 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
6107 (float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
6108 "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
6109 "@
6110 fcfid %0,%1
6111 xscvsxddp %x0,%x1"
6112 [(set_attr "type" "fp")])
6113
6114 ; Allow the combiner to merge source memory operands to the conversion so that
6115 ; the optimizer/register allocator doesn't try to load the value too early in a
6116 ; GPR and then use store/load to move it to a FPR and suffer from a store-load
6117 ; hit. We will split after reload to avoid the trip through the GPRs
6118
6119 (define_insn_and_split "*floatdidf2_mem"
6120 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
6121 (float:DF (match_operand:DI 1 "memory_operand" "m,Z")))
6122 (clobber (match_scratch:DI 2 "=d,wi"))]
6123 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && TARGET_FCFID"
6124 "#"
6125 "&& reload_completed"
6126 [(set (match_dup 2) (match_dup 1))
6127 (set (match_dup 0) (float:DF (match_dup 2)))]
6128 ""
6129 [(set_attr "length" "8")
6130 (set_attr "type" "fpload")])
6131
6132 (define_expand "floatunsdidf2"
6133 [(set (match_operand:DF 0 "gpc_reg_operand" "")
6134 (unsigned_float:DF
6135 (match_operand:DI 1 "gpc_reg_operand" "")))]
6136 "TARGET_HARD_FLOAT && TARGET_FCFIDU"
6137 "")
6138
6139 (define_insn "*floatunsdidf2_fcfidu"
6140 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
6141 (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
6142 "TARGET_HARD_FLOAT && TARGET_FCFIDU"
6143 "@
6144 fcfidu %0,%1
6145 xscvuxddp %x0,%x1"
6146 [(set_attr "type" "fp")
6147 (set_attr "length" "4")])
6148
6149 (define_insn_and_split "*floatunsdidf2_mem"
6150 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
6151 (unsigned_float:DF (match_operand:DI 1 "memory_operand" "m,Z")))
6152 (clobber (match_scratch:DI 2 "=d,wi"))]
6153 "TARGET_HARD_FLOAT && (TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode))"
6154 "#"
6155 "&& reload_completed"
6156 [(set (match_dup 2) (match_dup 1))
6157 (set (match_dup 0) (unsigned_float:DF (match_dup 2)))]
6158 ""
6159 [(set_attr "length" "8")
6160 (set_attr "type" "fpload")])
6161
6162 (define_expand "floatdisf2"
6163 [(set (match_operand:SF 0 "gpc_reg_operand" "")
6164 (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
6165 "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6166 && (TARGET_FCFIDS || TARGET_POWERPC64 || flag_unsafe_math_optimizations)"
6167 "
6168 {
6169 if (!TARGET_FCFIDS)
6170 {
6171 rtx val = operands[1];
6172 if (!flag_unsafe_math_optimizations)
6173 {
6174 rtx label = gen_label_rtx ();
6175 val = gen_reg_rtx (DImode);
6176 emit_insn (gen_floatdisf2_internal2 (val, operands[1], label));
6177 emit_label (label);
6178 }
6179 emit_insn (gen_floatdisf2_internal1 (operands[0], val));
6180 DONE;
6181 }
6182 }")
6183
6184 (define_insn "floatdisf2_fcfids"
6185 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy")
6186 (float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
6187 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6188 && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
6189 "@
6190 fcfids %0,%1
6191 xscvsxdsp %x0,%x1"
6192 [(set_attr "type" "fp")])
6193
6194 (define_insn_and_split "*floatdisf2_mem"
6195 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy,wy")
6196 (float:SF (match_operand:DI 1 "memory_operand" "m,m,Z")))
6197 (clobber (match_scratch:DI 2 "=d,d,wi"))]
6198 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6199 && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS"
6200 "#"
6201 "&& reload_completed"
6202 [(pc)]
6203 "
6204 {
6205 emit_move_insn (operands[2], operands[1]);
6206 emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2]));
6207 DONE;
6208 }"
6209 [(set_attr "length" "8")])
6210
6211 ;; This is not IEEE compliant if rounding mode is "round to nearest".
6212 ;; If the DI->DF conversion is inexact, then it's possible to suffer
6213 ;; from double rounding.
6214 ;; Instead of creating a new cpu type for two FP operations, just use fp
6215 (define_insn_and_split "floatdisf2_internal1"
6216 [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
6217 (float:SF (match_operand:DI 1 "gpc_reg_operand" "d")))
6218 (clobber (match_scratch:DF 2 "=d"))]
6219 "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6220 && !TARGET_FCFIDS"
6221 "#"
6222 "&& reload_completed"
6223 [(set (match_dup 2)
6224 (float:DF (match_dup 1)))
6225 (set (match_dup 0)
6226 (float_truncate:SF (match_dup 2)))]
6227 ""
6228 [(set_attr "length" "8")
6229 (set_attr "type" "fp")])
6230
6231 ;; Twiddles bits to avoid double rounding.
6232 ;; Bits that might be truncated when converting to DFmode are replaced
6233 ;; by a bit that won't be lost at that stage, but is below the SFmode
6234 ;; rounding position.
6235 (define_expand "floatdisf2_internal2"
6236 [(parallel [(set (match_dup 3) (ashiftrt:DI (match_operand:DI 1 "" "")
6237 (const_int 53)))
6238 (clobber (reg:DI CA_REGNO))])
6239 (set (match_operand:DI 0 "" "") (and:DI (match_dup 1)
6240 (const_int 2047)))
6241 (set (match_dup 3) (plus:DI (match_dup 3)
6242 (const_int 1)))
6243 (set (match_dup 0) (plus:DI (match_dup 0)
6244 (const_int 2047)))
6245 (set (match_dup 4) (compare:CCUNS (match_dup 3)
6246 (const_int 2)))
6247 (set (match_dup 0) (ior:DI (match_dup 0)
6248 (match_dup 1)))
6249 (set (match_dup 0) (and:DI (match_dup 0)
6250 (const_int -2048)))
6251 (set (pc) (if_then_else (geu (match_dup 4) (const_int 0))
6252 (label_ref (match_operand:DI 2 "" ""))
6253 (pc)))
6254 (set (match_dup 0) (match_dup 1))]
6255 "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6256 && !TARGET_FCFIDS"
6257 "
6258 {
6259 operands[3] = gen_reg_rtx (DImode);
6260 operands[4] = gen_reg_rtx (CCUNSmode);
6261 }")
6262
6263 (define_expand "floatunsdisf2"
6264 [(set (match_operand:SF 0 "gpc_reg_operand" "")
6265 (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
6266 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6267 && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
6268 "")
6269
6270 (define_insn "floatunsdisf2_fcfidus"
6271 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wu")
6272 (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
6273 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6274 && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
6275 "@
6276 fcfidus %0,%1
6277 xscvuxdsp %x0,%x1"
6278 [(set_attr "type" "fp")])
6279
6280 (define_insn_and_split "*floatunsdisf2_mem"
6281 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy,wy")
6282 (unsigned_float:SF (match_operand:DI 1 "memory_operand" "m,m,Z")))
6283 (clobber (match_scratch:DI 2 "=d,d,wi"))]
6284 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
6285 && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS"
6286 "#"
6287 "&& reload_completed"
6288 [(pc)]
6289 "
6290 {
6291 emit_move_insn (operands[2], operands[1]);
6292 emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2]));
6293 DONE;
6294 }"
6295 [(set_attr "length" "8")
6296 (set_attr "type" "fpload")])
6297 \f
6298 ;; Define the TImode operations that can be done in a small number
6299 ;; of instructions. The & constraints are to prevent the register
6300 ;; allocator from allocating registers that overlap with the inputs
6301 ;; (for example, having an input in 7,8 and an output in 6,7). We
6302 ;; also allow for the output being the same as one of the inputs.
6303
6304 (define_expand "addti3"
6305 [(set (match_operand:TI 0 "gpc_reg_operand" "")
6306 (plus:TI (match_operand:TI 1 "gpc_reg_operand" "")
6307 (match_operand:TI 2 "reg_or_short_operand" "")))]
6308 "TARGET_64BIT"
6309 {
6310 rtx lo0 = gen_lowpart (DImode, operands[0]);
6311 rtx lo1 = gen_lowpart (DImode, operands[1]);
6312 rtx lo2 = gen_lowpart (DImode, operands[2]);
6313 rtx hi0 = gen_highpart (DImode, operands[0]);
6314 rtx hi1 = gen_highpart (DImode, operands[1]);
6315 rtx hi2 = gen_highpart_mode (DImode, TImode, operands[2]);
6316
6317 if (!reg_or_short_operand (lo2, DImode))
6318 lo2 = force_reg (DImode, lo2);
6319 if (!adde_operand (hi2, DImode))
6320 hi2 = force_reg (DImode, hi2);
6321
6322 emit_insn (gen_adddi3_carry (lo0, lo1, lo2));
6323 emit_insn (gen_adddi3_carry_in (hi0, hi1, hi2));
6324 DONE;
6325 })
6326
6327 (define_expand "subti3"
6328 [(set (match_operand:TI 0 "gpc_reg_operand" "")
6329 (minus:TI (match_operand:TI 1 "reg_or_short_operand" "")
6330 (match_operand:TI 2 "gpc_reg_operand" "")))]
6331 "TARGET_64BIT"
6332 {
6333 rtx lo0 = gen_lowpart (DImode, operands[0]);
6334 rtx lo1 = gen_lowpart (DImode, operands[1]);
6335 rtx lo2 = gen_lowpart (DImode, operands[2]);
6336 rtx hi0 = gen_highpart (DImode, operands[0]);
6337 rtx hi1 = gen_highpart_mode (DImode, TImode, operands[1]);
6338 rtx hi2 = gen_highpart (DImode, operands[2]);
6339
6340 if (!reg_or_short_operand (lo1, DImode))
6341 lo1 = force_reg (DImode, lo1);
6342 if (!adde_operand (hi1, DImode))
6343 hi1 = force_reg (DImode, hi1);
6344
6345 emit_insn (gen_subfdi3_carry (lo0, lo2, lo1));
6346 emit_insn (gen_subfdi3_carry_in (hi0, hi2, hi1));
6347 DONE;
6348 })
6349 \f
6350 ;; 128-bit logical operations expanders
6351
6352 (define_expand "and<mode>3"
6353 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6354 (and:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
6355 (match_operand:BOOL_128 2 "vlogical_operand" "")))]
6356 ""
6357 "")
6358
6359 (define_expand "ior<mode>3"
6360 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6361 (ior:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
6362 (match_operand:BOOL_128 2 "vlogical_operand" "")))]
6363 ""
6364 "")
6365
6366 (define_expand "xor<mode>3"
6367 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6368 (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
6369 (match_operand:BOOL_128 2 "vlogical_operand" "")))]
6370 ""
6371 "")
6372
6373 (define_expand "one_cmpl<mode>2"
6374 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6375 (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")))]
6376 ""
6377 "")
6378
6379 (define_expand "nor<mode>3"
6380 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6381 (and:BOOL_128
6382 (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" ""))
6383 (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))]
6384 ""
6385 "")
6386
6387 (define_expand "andc<mode>3"
6388 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6389 (and:BOOL_128
6390 (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))
6391 (match_operand:BOOL_128 1 "vlogical_operand" "")))]
6392 ""
6393 "")
6394
6395 ;; Power8 vector logical instructions.
6396 (define_expand "eqv<mode>3"
6397 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6398 (not:BOOL_128
6399 (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")
6400 (match_operand:BOOL_128 2 "vlogical_operand" ""))))]
6401 "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR"
6402 "")
6403
6404 ;; Rewrite nand into canonical form
6405 (define_expand "nand<mode>3"
6406 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6407 (ior:BOOL_128
6408 (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" ""))
6409 (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))]
6410 "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR"
6411 "")
6412
6413 ;; The canonical form is to have the negated element first, so we need to
6414 ;; reverse arguments.
6415 (define_expand "orc<mode>3"
6416 [(set (match_operand:BOOL_128 0 "vlogical_operand" "")
6417 (ior:BOOL_128
6418 (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))
6419 (match_operand:BOOL_128 1 "vlogical_operand" "")))]
6420 "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR"
6421 "")
6422
6423 ;; 128-bit logical operations insns and split operations
6424 (define_insn_and_split "*and<mode>3_internal"
6425 [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
6426 (and:BOOL_128
6427 (match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>")
6428 (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")))]
6429 ""
6430 {
6431 if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
6432 return "xxland %x0,%x1,%x2";
6433
6434 if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
6435 return "vand %0,%1,%2";
6436
6437 return "#";
6438 }
6439 "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
6440 [(const_int 0)]
6441 {
6442 rs6000_split_logical (operands, AND, false, false, false);
6443 DONE;
6444 }
6445 [(set (attr "type")
6446 (if_then_else
6447 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6448 (const_string "veclogical")
6449 (const_string "integer")))
6450 (set (attr "length")
6451 (if_then_else
6452 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6453 (const_string "4")
6454 (if_then_else
6455 (match_test "TARGET_POWERPC64")
6456 (const_string "8")
6457 (const_string "16"))))])
6458
6459 ;; 128-bit IOR/XOR
6460 (define_insn_and_split "*bool<mode>3_internal"
6461 [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
6462 (match_operator:BOOL_128 3 "boolean_or_operator"
6463 [(match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>")
6464 (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")]))]
6465 ""
6466 {
6467 if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
6468 return "xxl%q3 %x0,%x1,%x2";
6469
6470 if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
6471 return "v%q3 %0,%1,%2";
6472
6473 return "#";
6474 }
6475 "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
6476 [(const_int 0)]
6477 {
6478 rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, false);
6479 DONE;
6480 }
6481 [(set (attr "type")
6482 (if_then_else
6483 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6484 (const_string "veclogical")
6485 (const_string "integer")))
6486 (set (attr "length")
6487 (if_then_else
6488 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6489 (const_string "4")
6490 (if_then_else
6491 (match_test "TARGET_POWERPC64")
6492 (const_string "8")
6493 (const_string "16"))))])
6494
6495 ;; 128-bit ANDC/ORC
6496 (define_insn_and_split "*boolc<mode>3_internal1"
6497 [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
6498 (match_operator:BOOL_128 3 "boolean_operator"
6499 [(not:BOOL_128
6500 (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))
6501 (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>")]))]
6502 "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)"
6503 {
6504 if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
6505 return "xxl%q3 %x0,%x1,%x2";
6506
6507 if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
6508 return "v%q3 %0,%1,%2";
6509
6510 return "#";
6511 }
6512 "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND))
6513 && reload_completed && int_reg_operand (operands[0], <MODE>mode)"
6514 [(const_int 0)]
6515 {
6516 rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, true);
6517 DONE;
6518 }
6519 [(set (attr "type")
6520 (if_then_else
6521 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6522 (const_string "veclogical")
6523 (const_string "integer")))
6524 (set (attr "length")
6525 (if_then_else
6526 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6527 (const_string "4")
6528 (if_then_else
6529 (match_test "TARGET_POWERPC64")
6530 (const_string "8")
6531 (const_string "16"))))])
6532
6533 (define_insn_and_split "*boolc<mode>3_internal2"
6534 [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r")
6535 (match_operator:TI2 3 "boolean_operator"
6536 [(not:TI2
6537 (match_operand:TI2 2 "int_reg_operand" "r,0,r"))
6538 (match_operand:TI2 1 "int_reg_operand" "r,r,0")]))]
6539 "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
6540 "#"
6541 "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
6542 [(const_int 0)]
6543 {
6544 rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, true);
6545 DONE;
6546 }
6547 [(set_attr "type" "integer")
6548 (set (attr "length")
6549 (if_then_else
6550 (match_test "TARGET_POWERPC64")
6551 (const_string "8")
6552 (const_string "16")))])
6553
6554 ;; 128-bit NAND/NOR
6555 (define_insn_and_split "*boolcc<mode>3_internal1"
6556 [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
6557 (match_operator:BOOL_128 3 "boolean_operator"
6558 [(not:BOOL_128
6559 (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>"))
6560 (not:BOOL_128
6561 (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))]))]
6562 "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)"
6563 {
6564 if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
6565 return "xxl%q3 %x0,%x1,%x2";
6566
6567 if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
6568 return "v%q3 %0,%1,%2";
6569
6570 return "#";
6571 }
6572 "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND))
6573 && reload_completed && int_reg_operand (operands[0], <MODE>mode)"
6574 [(const_int 0)]
6575 {
6576 rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true);
6577 DONE;
6578 }
6579 [(set (attr "type")
6580 (if_then_else
6581 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6582 (const_string "veclogical")
6583 (const_string "integer")))
6584 (set (attr "length")
6585 (if_then_else
6586 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6587 (const_string "4")
6588 (if_then_else
6589 (match_test "TARGET_POWERPC64")
6590 (const_string "8")
6591 (const_string "16"))))])
6592
6593 (define_insn_and_split "*boolcc<mode>3_internal2"
6594 [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r")
6595 (match_operator:TI2 3 "boolean_operator"
6596 [(not:TI2
6597 (match_operand:TI2 1 "int_reg_operand" "r,0,r"))
6598 (not:TI2
6599 (match_operand:TI2 2 "int_reg_operand" "r,r,0"))]))]
6600 "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
6601 "#"
6602 "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)"
6603 [(const_int 0)]
6604 {
6605 rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true);
6606 DONE;
6607 }
6608 [(set_attr "type" "integer")
6609 (set (attr "length")
6610 (if_then_else
6611 (match_test "TARGET_POWERPC64")
6612 (const_string "8")
6613 (const_string "16")))])
6614
6615
6616 ;; 128-bit EQV
6617 (define_insn_and_split "*eqv<mode>3_internal1"
6618 [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
6619 (not:BOOL_128
6620 (xor:BOOL_128
6621 (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>")
6622 (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))))]
6623 "TARGET_P8_VECTOR"
6624 {
6625 if (vsx_register_operand (operands[0], <MODE>mode))
6626 return "xxleqv %x0,%x1,%x2";
6627
6628 return "#";
6629 }
6630 "TARGET_P8_VECTOR && reload_completed
6631 && int_reg_operand (operands[0], <MODE>mode)"
6632 [(const_int 0)]
6633 {
6634 rs6000_split_logical (operands, XOR, true, false, false);
6635 DONE;
6636 }
6637 [(set (attr "type")
6638 (if_then_else
6639 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6640 (const_string "veclogical")
6641 (const_string "integer")))
6642 (set (attr "length")
6643 (if_then_else
6644 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6645 (const_string "4")
6646 (if_then_else
6647 (match_test "TARGET_POWERPC64")
6648 (const_string "8")
6649 (const_string "16"))))])
6650
6651 (define_insn_and_split "*eqv<mode>3_internal2"
6652 [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r")
6653 (not:TI2
6654 (xor:TI2
6655 (match_operand:TI2 1 "int_reg_operand" "r,0,r")
6656 (match_operand:TI2 2 "int_reg_operand" "r,r,0"))))]
6657 "!TARGET_P8_VECTOR"
6658 "#"
6659 "reload_completed && !TARGET_P8_VECTOR"
6660 [(const_int 0)]
6661 {
6662 rs6000_split_logical (operands, XOR, true, false, false);
6663 DONE;
6664 }
6665 [(set_attr "type" "integer")
6666 (set (attr "length")
6667 (if_then_else
6668 (match_test "TARGET_POWERPC64")
6669 (const_string "8")
6670 (const_string "16")))])
6671
6672 ;; 128-bit one's complement
6673 (define_insn_and_split "*one_cmpl<mode>3_internal"
6674 [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>")
6675 (not:BOOL_128
6676 (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_UNARY>")))]
6677 ""
6678 {
6679 if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode))
6680 return "xxlnor %x0,%x1,%x1";
6681
6682 if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode))
6683 return "vnor %0,%1,%1";
6684
6685 return "#";
6686 }
6687 "reload_completed && int_reg_operand (operands[0], <MODE>mode)"
6688 [(const_int 0)]
6689 {
6690 rs6000_split_logical (operands, NOT, false, false, false);
6691 DONE;
6692 }
6693 [(set (attr "type")
6694 (if_then_else
6695 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6696 (const_string "veclogical")
6697 (const_string "integer")))
6698 (set (attr "length")
6699 (if_then_else
6700 (match_test "vsx_register_operand (operands[0], <MODE>mode)")
6701 (const_string "4")
6702 (if_then_else
6703 (match_test "TARGET_POWERPC64")
6704 (const_string "8")
6705 (const_string "16"))))])
6706
6707 \f
6708 ;; Now define ways of moving data around.
6709
6710 ;; Set up a register with a value from the GOT table
6711
6712 (define_expand "movsi_got"
6713 [(set (match_operand:SI 0 "gpc_reg_operand" "")
6714 (unspec:SI [(match_operand:SI 1 "got_operand" "")
6715 (match_dup 2)] UNSPEC_MOVSI_GOT))]
6716 "DEFAULT_ABI == ABI_V4 && flag_pic == 1"
6717 "
6718 {
6719 if (GET_CODE (operands[1]) == CONST)
6720 {
6721 rtx offset = const0_rtx;
6722 HOST_WIDE_INT value;
6723
6724 operands[1] = eliminate_constant_term (XEXP (operands[1], 0), &offset);
6725 value = INTVAL (offset);
6726 if (value != 0)
6727 {
6728 rtx tmp = (!can_create_pseudo_p ()
6729 ? operands[0]
6730 : gen_reg_rtx (Pmode));
6731 emit_insn (gen_movsi_got (tmp, operands[1]));
6732 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6733 DONE;
6734 }
6735 }
6736
6737 operands[2] = rs6000_got_register (operands[1]);
6738 }")
6739
6740 (define_insn "*movsi_got_internal"
6741 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
6742 (unspec:SI [(match_operand:SI 1 "got_no_const_operand" "")
6743 (match_operand:SI 2 "gpc_reg_operand" "b")]
6744 UNSPEC_MOVSI_GOT))]
6745 "DEFAULT_ABI == ABI_V4 && flag_pic == 1"
6746 "lwz %0,%a1@got(%2)"
6747 [(set_attr "type" "load")])
6748
6749 ;; Used by sched, shorten_branches and final when the GOT pseudo reg
6750 ;; didn't get allocated to a hard register.
6751 (define_split
6752 [(set (match_operand:SI 0 "gpc_reg_operand" "")
6753 (unspec:SI [(match_operand:SI 1 "got_no_const_operand" "")
6754 (match_operand:SI 2 "memory_operand" "")]
6755 UNSPEC_MOVSI_GOT))]
6756 "DEFAULT_ABI == ABI_V4
6757 && flag_pic == 1
6758 && (reload_in_progress || reload_completed)"
6759 [(set (match_dup 0) (match_dup 2))
6760 (set (match_dup 0) (unspec:SI [(match_dup 1)(match_dup 0)]
6761 UNSPEC_MOVSI_GOT))]
6762 "")
6763
6764 ;; For SI, we special-case integers that can't be loaded in one insn. We
6765 ;; do the load 16-bits at a time. We could do this by loading from memory,
6766 ;; and this is even supposed to be faster, but it is simpler not to get
6767 ;; integers in the TOC.
6768 (define_insn "movsi_low"
6769 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
6770 (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
6771 (match_operand 2 "" ""))))]
6772 "TARGET_MACHO && ! TARGET_64BIT"
6773 "lwz %0,lo16(%2)(%1)"
6774 [(set_attr "type" "load")
6775 (set_attr "length" "4")])
6776
6777 ;; MR LA LWZ LFIWZX LXSIWZX
6778 ;; STW STFIWX STXSIWX LI LIS
6779 ;; # XXLOR XXSPLTIB 0 XXSPLTIB -1 VSPLTISW
6780 ;; XXLXOR 0 XXLORC -1 P9 const MTVSRWZ MFVSRWZ
6781 ;; MF%1 MT%0 MT%0 NOP
6782 (define_insn "*movsi_internal1"
6783 [(set (match_operand:SI 0 "rs6000_nonimmediate_operand"
6784 "=r, r, r, ?*wI, ?*wH,
6785 m, ?Z, ?Z, r, r,
6786 r, ?*wIwH, ?*wJwK, ?*wJwK, ?*wu,
6787 ?*wJwK, ?*wH, ?*wK, ?*wIwH, ?r,
6788 r, *c*l, *h, *h")
6789
6790 (match_operand:SI 1 "input_operand"
6791 "r, U, m, Z, Z,
6792 r, wI, wH, I, L,
6793 n, wIwH, O, wM, wB,
6794 O, wM, wS, r, wIwH,
6795 *h, r, r, 0"))]
6796
6797 "!TARGET_SINGLE_FPU &&
6798 (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))"
6799 "@
6800 mr %0,%1
6801 la %0,%a1
6802 lwz%U1%X1 %0,%1
6803 lfiwzx %0,%y1
6804 lxsiwzx %x0,%y1
6805 stw%U0%X0 %1,%0
6806 stfiwx %1,%y0
6807 stxsiwx %x1,%y0
6808 li %0,%1
6809 lis %0,%v1
6810 #
6811 xxlor %x0,%x1,%x1
6812 xxspltib %x0,0
6813 xxspltib %x0,255
6814 vspltisw %0,%1
6815 xxlxor %x0,%x0,%x0
6816 xxlorc %x0,%x0,%x0
6817 #
6818 mtvsrwz %x0,%1
6819 mfvsrwz %0,%x1
6820 mf%1 %0
6821 mt%0 %1
6822 mt%0 %1
6823 nop"
6824 [(set_attr "type"
6825 "*, *, load, fpload, fpload,
6826 store, fpstore, fpstore, *, *,
6827 *, veclogical, vecsimple, vecsimple, vecsimple,
6828 veclogical, veclogical, vecsimple, mffgpr, mftgpr,
6829 *, *, *, *")
6830
6831 (set_attr "length"
6832 "4, 4, 4, 4, 4,
6833 4, 4, 4, 4, 4,
6834 8, 4, 4, 4, 4,
6835 4, 4, 8, 4, 4,
6836 4, 4, 4, 4")])
6837
6838 (define_insn "*movsi_internal1_single"
6839 [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*c*l,*h,*h,m,*f")
6840 (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,0,f,m"))]
6841 "TARGET_SINGLE_FPU &&
6842 (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))"
6843 "@
6844 mr %0,%1
6845 la %0,%a1
6846 lwz%U1%X1 %0,%1
6847 stw%U0%X0 %1,%0
6848 li %0,%1
6849 lis %0,%v1
6850 #
6851 mf%1 %0
6852 mt%0 %1
6853 mt%0 %1
6854 nop
6855 stfs%U0%X0 %1,%0
6856 lfs%U1%X1 %0,%1"
6857 [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*,fpstore,fpload")
6858 (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
6859
6860 ;; Like movsi, but adjust a SF value to be used in a SI context, i.e.
6861 ;; (set (reg:SI ...) (subreg:SI (reg:SF ...) 0))
6862 ;;
6863 ;; Because SF values are actually stored as DF values within the vector
6864 ;; registers, we need to convert the value to the vector SF format when
6865 ;; we need to use the bits in a union or similar cases. We only need
6866 ;; to do this transformation when the value is a vector register. Loads,
6867 ;; stores, and transfers within GPRs are assumed to be safe.
6868 ;;
6869 ;; This is a more general case of reload_gpr_from_vsxsf. That insn must have
6870 ;; no alternatives, because the call is created as part of secondary_reload,
6871 ;; and operand #2's register class is used to allocate the temporary register.
6872 ;; This function is called before reload, and it creates the temporary as
6873 ;; needed.
6874
6875 ;; MR LWZ LFIWZX LXSIWZX STW
6876 ;; STFS STXSSP STXSSPX VSX->GPR MTVSRWZ
6877 ;; VSX->VSX
6878
6879 (define_insn_and_split "movsi_from_sf"
6880 [(set (match_operand:SI 0 "rs6000_nonimmediate_operand"
6881 "=r, r, ?*wI, ?*wH, m,
6882 m, wY, Z, r, wIwH,
6883 ?wK")
6884
6885 (unspec:SI [(match_operand:SF 1 "input_operand"
6886 "r, m, Z, Z, r,
6887 f, wb, wu, wIwH, r,
6888 wK")]
6889 UNSPEC_SI_FROM_SF))
6890
6891 (clobber (match_scratch:V4SF 2
6892 "=X, X, X, X, X,
6893 X, X, X, wa, X,
6894 wa"))]
6895
6896 "TARGET_NO_SF_SUBREG
6897 && (register_operand (operands[0], SImode)
6898 || register_operand (operands[1], SFmode))"
6899 "@
6900 mr %0,%1
6901 lwz%U1%X1 %0,%1
6902 lfiwzx %0,%y1
6903 lxsiwzx %x0,%y1
6904 stw%U0%X0 %1,%0
6905 stfs%U0%X0 %1,%0
6906 stxssp %1,%0
6907 stxsspx %x1,%y0
6908 #
6909 mtvsrwz %x0,%1
6910 #"
6911 "&& reload_completed
6912 && register_operand (operands[0], SImode)
6913 && vsx_reg_sfsubreg_ok (operands[1], SFmode)"
6914 [(const_int 0)]
6915 {
6916 rtx op0 = operands[0];
6917 rtx op1 = operands[1];
6918 rtx op2 = operands[2];
6919 rtx op0_di = gen_rtx_REG (DImode, REGNO (op0));
6920
6921 emit_insn (gen_vsx_xscvdpspn_scalar (op2, op1));
6922
6923 if (int_reg_operand (op0, SImode))
6924 {
6925 emit_insn (gen_p8_mfvsrd_4_disf (op0_di, op2));
6926 emit_insn (gen_lshrdi3 (op0_di, op0_di, GEN_INT (32)));
6927 }
6928 else
6929 {
6930 rtx op1_v16qi = gen_rtx_REG (V16QImode, REGNO (op1));
6931 rtx byte_off = VECTOR_ELT_ORDER_BIG ? const0_rtx : GEN_INT (12);
6932 emit_insn (gen_vextract4b (op0_di, op1_v16qi, byte_off));
6933 }
6934
6935 DONE;
6936 }
6937 [(set_attr "type"
6938 "*, load, fpload, fpload, store,
6939 fpstore, fpstore, fpstore, mftgpr, mffgpr,
6940 veclogical")
6941
6942 (set_attr "length"
6943 "4, 4, 4, 4, 4,
6944 4, 4, 4, 12, 4,
6945 8")])
6946
6947 ;; movsi_from_sf with zero extension
6948 ;;
6949 ;; RLDICL LWZ LFIWZX LXSIWZX VSX->GPR
6950 ;; MTVSRWZ VSX->VSX
6951
6952 (define_insn_and_split "*movdi_from_sf_zero_ext"
6953 [(set (match_operand:DI 0 "gpc_reg_operand"
6954 "=r, r, ?*wI, ?*wH, r,
6955 wIwH, ?wK")
6956
6957 (zero_extend:DI
6958 (unspec:SI [(match_operand:SF 1 "input_operand"
6959 "r, m, Z, Z, wIwH,
6960 r, wK")]
6961 UNSPEC_SI_FROM_SF)))
6962
6963 (clobber (match_scratch:V4SF 2
6964 "=X, X, X, X, wa,
6965 X, wa"))]
6966
6967 "TARGET_DIRECT_MOVE_64BIT
6968 && (register_operand (operands[0], DImode)
6969 || register_operand (operands[1], SImode))"
6970 "@
6971 rldicl %0,%1,0,32
6972 lwz%U1%X1 %0,%1
6973 lfiwzx %0,%y1
6974 lxsiwzx %x0,%y1
6975 #
6976 mtvsrwz %x0,%1
6977 #"
6978 "&& reload_completed
6979 && vsx_reg_sfsubreg_ok (operands[1], SFmode)"
6980 [(const_int 0)]
6981 {
6982 rtx op0 = operands[0];
6983 rtx op1 = operands[1];
6984 rtx op2 = operands[2];
6985
6986 emit_insn (gen_vsx_xscvdpspn_scalar (op2, op1));
6987
6988 if (int_reg_operand (op0, DImode))
6989 {
6990 emit_insn (gen_p8_mfvsrd_4_disf (op0, op2));
6991 emit_insn (gen_lshrdi3 (op0, op0, GEN_INT (32)));
6992 }
6993 else
6994 {
6995 rtx op0_si = gen_rtx_REG (SImode, REGNO (op0));
6996 rtx op1_v16qi = gen_rtx_REG (V16QImode, REGNO (op1));
6997 rtx byte_off = VECTOR_ELT_ORDER_BIG ? const0_rtx : GEN_INT (12);
6998 emit_insn (gen_vextract4b (op0_si, op1_v16qi, byte_off));
6999 }
7000
7001 DONE;
7002 }
7003 [(set_attr "type"
7004 "*, load, fpload, fpload, mftgpr,
7005 mffgpr, veclogical")
7006
7007 (set_attr "length"
7008 "4, 4, 4, 4, 12,
7009 4, 8")])
7010
7011 ;; Split a load of a large constant into the appropriate two-insn
7012 ;; sequence.
7013
7014 (define_split
7015 [(set (match_operand:SI 0 "gpc_reg_operand" "")
7016 (match_operand:SI 1 "const_int_operand" ""))]
7017 "(unsigned HOST_WIDE_INT) (INTVAL (operands[1]) + 0x8000) >= 0x10000
7018 && (INTVAL (operands[1]) & 0xffff) != 0"
7019 [(set (match_dup 0)
7020 (match_dup 2))
7021 (set (match_dup 0)
7022 (ior:SI (match_dup 0)
7023 (match_dup 3)))]
7024 "
7025 {
7026 if (rs6000_emit_set_const (operands[0], operands[1]))
7027 DONE;
7028 else
7029 FAIL;
7030 }")
7031
7032 ;; Split loading -128..127 to use XXSPLITB and VEXTSW2D
7033 (define_split
7034 [(set (match_operand:DI 0 "altivec_register_operand")
7035 (match_operand:DI 1 "xxspltib_constant_split"))]
7036 "TARGET_VSX_SMALL_INTEGER && TARGET_P9_VECTOR && reload_completed"
7037 [(const_int 0)]
7038 {
7039 rtx op0 = operands[0];
7040 rtx op1 = operands[1];
7041 int r = REGNO (op0);
7042 rtx op0_v16qi = gen_rtx_REG (V16QImode, r);
7043
7044 emit_insn (gen_xxspltib_v16qi (op0_v16qi, op1));
7045 emit_insn (gen_vsx_sign_extend_qi_si (operands[0], op0_v16qi));
7046 DONE;
7047 })
7048
7049 (define_insn "*mov<mode>_internal2"
7050 [(set (match_operand:CC 2 "cc_reg_operand" "=y,x,?y")
7051 (compare:CC (match_operand:P 1 "gpc_reg_operand" "0,r,r")
7052 (const_int 0)))
7053 (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
7054 ""
7055 "@
7056 cmp<wd>i %2,%0,0
7057 mr. %0,%1
7058 #"
7059 [(set_attr "type" "cmp,logical,cmp")
7060 (set_attr "dot" "yes")
7061 (set_attr "length" "4,4,8")])
7062
7063 (define_split
7064 [(set (match_operand:CC 2 "cc_reg_not_micro_cr0_operand" "")
7065 (compare:CC (match_operand:P 1 "gpc_reg_operand" "")
7066 (const_int 0)))
7067 (set (match_operand:P 0 "gpc_reg_operand" "") (match_dup 1))]
7068 "reload_completed"
7069 [(set (match_dup 0) (match_dup 1))
7070 (set (match_dup 2)
7071 (compare:CC (match_dup 0)
7072 (const_int 0)))]
7073 "")
7074 \f
7075 (define_expand "mov<mode>"
7076 [(set (match_operand:INT 0 "general_operand" "")
7077 (match_operand:INT 1 "any_operand" ""))]
7078 ""
7079 "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
7080
7081 ;; MR LHZ/LBZ LXSI*ZX STH/STB STXSI*X LI
7082 ;; XXLOR load 0 load -1 VSPLTI* # MFVSRWZ
7083 ;; MTVSRWZ MF%1 MT%1 NOP
7084 (define_insn "*mov<mode>_internal"
7085 [(set (match_operand:QHI 0 "nonimmediate_operand"
7086 "=r, r, ?*wJwK, m, Z, r,
7087 ?*wJwK, ?*wJwK, ?*wJwK, ?*wK, ?*wK, r,
7088 ?*wJwK, r, *c*l, *h")
7089
7090 (match_operand:QHI 1 "input_operand"
7091 "r, m, Z, r, wJwK, i,
7092 wJwK, O, wM, wB, wS, ?*wJwK,
7093 r, *h, r, 0"))]
7094
7095 "gpc_reg_operand (operands[0], <MODE>mode)
7096 || gpc_reg_operand (operands[1], <MODE>mode)"
7097 "@
7098 mr %0,%1
7099 l<wd>z%U1%X1 %0,%1
7100 lxsi<wd>zx %x0,%y1
7101 st<wd>%U0%X0 %1,%0
7102 stxsi<wd>x %x1,%y0
7103 li %0,%1
7104 xxlor %x0,%x1,%x1
7105 xxspltib %x0,0
7106 xxspltib %x0,255
7107 vspltis<wd> %0,%1
7108 #
7109 mfvsrwz %0,%x1
7110 mtvsrwz %x0,%1
7111 mf%1 %0
7112 mt%0 %1
7113 nop"
7114 [(set_attr "type"
7115 "*, load, fpload, store, fpstore, *,
7116 vecsimple, vecperm, vecperm, vecperm, vecperm, mftgpr,
7117 mffgpr, mfjmpr, mtjmpr, *")
7118
7119 (set_attr "length"
7120 "4, 4, 4, 4, 4, 4,
7121 4, 4, 4, 4, 8, 4,
7122 4, 4, 4, 4")])
7123
7124 \f
7125 ;; Here is how to move condition codes around. When we store CC data in
7126 ;; an integer register or memory, we store just the high-order 4 bits.
7127 ;; This lets us not shift in the most common case of CR0.
7128 (define_expand "movcc"
7129 [(set (match_operand:CC 0 "nonimmediate_operand" "")
7130 (match_operand:CC 1 "nonimmediate_operand" ""))]
7131 ""
7132 "")
7133
7134 (define_insn "*movcc_internal1"
7135 [(set (match_operand:CC 0 "nonimmediate_operand"
7136 "=y,x,?y,y,r,r,r,r,r,*c*l,r,m")
7137 (match_operand:CC 1 "general_operand"
7138 " y,r, r,O,x,y,r,I,h, r,m,r"))]
7139 "register_operand (operands[0], CCmode)
7140 || register_operand (operands[1], CCmode)"
7141 "@
7142 mcrf %0,%1
7143 mtcrf 128,%1
7144 rlwinm %1,%1,%F0,0xffffffff\;mtcrf %R0,%1\;rlwinm %1,%1,%f0,0xffffffff
7145 crxor %0,%0,%0
7146 mfcr %0%Q1
7147 mfcr %0%Q1\;rlwinm %0,%0,%f1,0xf0000000
7148 mr %0,%1
7149 li %0,%1
7150 mf%1 %0
7151 mt%0 %1
7152 lwz%U1%X1 %0,%1
7153 stw%U0%X0 %1,%0"
7154 [(set (attr "type")
7155 (cond [(eq_attr "alternative" "0,3")
7156 (const_string "cr_logical")
7157 (eq_attr "alternative" "1,2")
7158 (const_string "mtcr")
7159 (eq_attr "alternative" "6,7")
7160 (const_string "integer")
7161 (eq_attr "alternative" "8")
7162 (const_string "mfjmpr")
7163 (eq_attr "alternative" "9")
7164 (const_string "mtjmpr")
7165 (eq_attr "alternative" "10")
7166 (const_string "load")
7167 (eq_attr "alternative" "11")
7168 (const_string "store")
7169 (match_test "TARGET_MFCRF")
7170 (const_string "mfcrf")
7171 ]
7172 (const_string "mfcr")))
7173 (set_attr "length" "4,4,12,4,4,8,4,4,4,4,4,4")])
7174 \f
7175 ;; For floating-point, we normally deal with the floating-point registers
7176 ;; unless -msoft-float is used. The sole exception is that parameter passing
7177 ;; can produce floating-point values in fixed-point registers. Unless the
7178 ;; value is a simple constant or already in memory, we deal with this by
7179 ;; allocating memory and copying the value explicitly via that memory location.
7180
7181 ;; Move 32-bit binary/decimal floating point
7182 (define_expand "mov<mode>"
7183 [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "")
7184 (match_operand:FMOVE32 1 "any_operand" ""))]
7185 "<fmove_ok>"
7186 "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
7187
7188 (define_split
7189 [(set (match_operand:FMOVE32 0 "gpc_reg_operand" "")
7190 (match_operand:FMOVE32 1 "const_double_operand" ""))]
7191 "reload_completed
7192 && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
7193 || (GET_CODE (operands[0]) == SUBREG
7194 && GET_CODE (SUBREG_REG (operands[0])) == REG
7195 && REGNO (SUBREG_REG (operands[0])) <= 31))"
7196 [(set (match_dup 2) (match_dup 3))]
7197 "
7198 {
7199 long l;
7200
7201 <real_value_to_target> (*CONST_DOUBLE_REAL_VALUE (operands[1]), l);
7202
7203 if (! TARGET_POWERPC64)
7204 operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
7205 else
7206 operands[2] = gen_lowpart (SImode, operands[0]);
7207
7208 operands[3] = gen_int_mode (l, SImode);
7209 }")
7210
7211 ;; Originally, we tried to keep movsf and movsd common, but the differences
7212 ;; addressing was making it rather difficult to hide with mode attributes. In
7213 ;; particular for SFmode, on ISA 2.07 (power8) systems, having the GPR store
7214 ;; before the VSX stores meant that the register allocator would tend to do a
7215 ;; direct move to the GPR (which involves conversion from scalar to
7216 ;; vector/memory formats) to save values in the traditional Altivec registers,
7217 ;; while SDmode had problems on power6 if the GPR store was not first due to
7218 ;; the power6 not having an integer store operation.
7219 ;;
7220 ;; LWZ LFS LXSSP LXSSPX STFS STXSSP
7221 ;; STXSSPX STW XXLXOR LI FMR XSCPSGNDP
7222 ;; MR MT<x> MF<x> NOP
7223
7224 (define_insn "movsf_hardfloat"
7225 [(set (match_operand:SF 0 "nonimmediate_operand"
7226 "=!r, f, wb, wu, m, wY,
7227 Z, m, ww, !r, f, ww,
7228 !r, *c*l, !r, *h")
7229 (match_operand:SF 1 "input_operand"
7230 "m, m, wY, Z, f, wb,
7231 wu, r, j, j, f, ww,
7232 r, r, *h, 0"))]
7233 "(register_operand (operands[0], SFmode)
7234 || register_operand (operands[1], SFmode))
7235 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
7236 && (TARGET_ALLOW_SF_SUBREG
7237 || valid_sf_si_move (operands[0], operands[1], SFmode))"
7238 "@
7239 lwz%U1%X1 %0,%1
7240 lfs%U1%X1 %0,%1
7241 lxssp %0,%1
7242 lxsspx %x0,%y1
7243 stfs%U0%X0 %1,%0
7244 stxssp %1,%0
7245 stxsspx %x1,%y0
7246 stw%U0%X0 %1,%0
7247 xxlxor %x0,%x0,%x0
7248 li %0,0
7249 fmr %0,%1
7250 xscpsgndp %x0,%x1,%x1
7251 mr %0,%1
7252 mt%0 %1
7253 mf%1 %0
7254 nop"
7255 [(set_attr "type"
7256 "load, fpload, fpload, fpload, fpstore, fpstore,
7257 fpstore, store, veclogical, integer, fpsimple, fpsimple,
7258 *, mtjmpr, mfjmpr, *")])
7259
7260 ;; LWZ LFIWZX STW STFIWX MTVSRWZ MFVSRWZ
7261 ;; FMR MR MT%0 MF%1 NOP
7262 (define_insn "movsd_hardfloat"
7263 [(set (match_operand:SD 0 "nonimmediate_operand"
7264 "=!r, wz, m, Z, ?wh, ?r,
7265 f, !r, *c*l, !r, *h")
7266 (match_operand:SD 1 "input_operand"
7267 "m, Z, r, wx, r, wh,
7268 f, r, r, *h, 0"))]
7269 "(register_operand (operands[0], SDmode)
7270 || register_operand (operands[1], SDmode))
7271 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
7272 "@
7273 lwz%U1%X1 %0,%1
7274 lfiwzx %0,%y1
7275 stw%U0%X0 %1,%0
7276 stfiwx %1,%y0
7277 mtvsrwz %x0,%1
7278 mfvsrwz %0,%x1
7279 fmr %0,%1
7280 mr %0,%1
7281 mt%0 %1
7282 mf%1 %0
7283 nop"
7284 [(set_attr "type"
7285 "load, fpload, store, fpstore, mffgpr, mftgpr,
7286 fpsimple, *, mtjmpr, mfjmpr, *")])
7287
7288 (define_insn "*mov<mode>_softfloat"
7289 [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,*h")
7290 (match_operand:FMOVE32 1 "input_operand" "r,r,h,m,r,I,L,G,Fn,0"))]
7291 "(gpc_reg_operand (operands[0], <MODE>mode)
7292 || gpc_reg_operand (operands[1], <MODE>mode))
7293 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
7294 "@
7295 mr %0,%1
7296 mt%0 %1
7297 mf%1 %0
7298 lwz%U1%X1 %0,%1
7299 stw%U0%X0 %1,%0
7300 li %0,%1
7301 lis %0,%v1
7302 #
7303 #
7304 nop"
7305 [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*")
7306 (set_attr "length" "4,4,4,4,4,4,4,4,8,4")])
7307
7308 ;; Like movsf, but adjust a SI value to be used in a SF context, i.e.
7309 ;; (set (reg:SF ...) (subreg:SF (reg:SI ...) 0))
7310 ;;
7311 ;; Because SF values are actually stored as DF values within the vector
7312 ;; registers, we need to convert the value to the vector SF format when
7313 ;; we need to use the bits in a union or similar cases. We only need
7314 ;; to do this transformation when the value is a vector register. Loads,
7315 ;; stores, and transfers within GPRs are assumed to be safe.
7316 ;;
7317 ;; This is a more general case of reload_vsx_from_gprsf. That insn must have
7318 ;; no alternatives, because the call is created as part of secondary_reload,
7319 ;; and operand #2's register class is used to allocate the temporary register.
7320 ;; This function is called before reload, and it creates the temporary as
7321 ;; needed.
7322
7323 ;; LWZ LFS LXSSP LXSSPX STW STFIWX
7324 ;; STXSIWX GPR->VSX VSX->GPR GPR->GPR
7325 (define_insn_and_split "movsf_from_si"
7326 [(set (match_operand:SF 0 "rs6000_nonimmediate_operand"
7327 "=!r, f, wb, wu, m, Z,
7328 Z, wy, ?r, !r")
7329
7330 (unspec:SF [(match_operand:SI 1 "input_operand"
7331 "m, m, wY, Z, r, f,
7332 wu, r, wy, r")]
7333 UNSPEC_SF_FROM_SI))
7334
7335 (clobber (match_scratch:DI 2
7336 "=X, X, X, X, X, X,
7337 X, r, X, X"))]
7338
7339 "TARGET_NO_SF_SUBREG
7340 && (register_operand (operands[0], SFmode)
7341 || register_operand (operands[1], SImode))"
7342 "@
7343 lwz%U1%X1 %0,%1
7344 lfs%U1%X1 %0,%1
7345 lxssp %0,%1
7346 lxsspx %x0,%y1
7347 stw%U0%X0 %1,%0
7348 stfiwx %1,%y0
7349 stxsiwx %x1,%y0
7350 #
7351 mfvsrwz %0,%x1
7352 mr %0,%1"
7353
7354 "&& reload_completed
7355 && vsx_reg_sfsubreg_ok (operands[0], SFmode)
7356 && int_reg_operand_not_pseudo (operands[1], SImode)"
7357 [(const_int 0)]
7358 {
7359 rtx op0 = operands[0];
7360 rtx op1 = operands[1];
7361 rtx op2 = operands[2];
7362 rtx op1_di = gen_rtx_REG (DImode, REGNO (op1));
7363
7364 /* Move SF value to upper 32-bits for xscvspdpn. */
7365 emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32)));
7366 emit_insn (gen_p8_mtvsrd_sf (op0, op2));
7367 emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0));
7368 DONE;
7369 }
7370 [(set_attr "length"
7371 "4, 4, 4, 4, 4, 4,
7372 4, 12, 4, 4")
7373 (set_attr "type"
7374 "load, fpload, fpload, fpload, store, fpstore,
7375 fpstore, vecfloat, mffgpr, *")])
7376
7377 \f
7378 ;; Move 64-bit binary/decimal floating point
7379 (define_expand "mov<mode>"
7380 [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "")
7381 (match_operand:FMOVE64 1 "any_operand" ""))]
7382 ""
7383 "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
7384
7385 (define_split
7386 [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "")
7387 (match_operand:FMOVE64 1 "const_int_operand" ""))]
7388 "! TARGET_POWERPC64 && reload_completed
7389 && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
7390 || (GET_CODE (operands[0]) == SUBREG
7391 && GET_CODE (SUBREG_REG (operands[0])) == REG
7392 && REGNO (SUBREG_REG (operands[0])) <= 31))"
7393 [(set (match_dup 2) (match_dup 4))
7394 (set (match_dup 3) (match_dup 1))]
7395 "
7396 {
7397 int endian = (WORDS_BIG_ENDIAN == 0);
7398 HOST_WIDE_INT value = INTVAL (operands[1]);
7399
7400 operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode);
7401 operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode);
7402 operands[4] = GEN_INT (value >> 32);
7403 operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
7404 }")
7405
7406 (define_split
7407 [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "")
7408 (match_operand:FMOVE64 1 "const_double_operand" ""))]
7409 "! TARGET_POWERPC64 && reload_completed
7410 && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
7411 || (GET_CODE (operands[0]) == SUBREG
7412 && GET_CODE (SUBREG_REG (operands[0])) == REG
7413 && REGNO (SUBREG_REG (operands[0])) <= 31))"
7414 [(set (match_dup 2) (match_dup 4))
7415 (set (match_dup 3) (match_dup 5))]
7416 "
7417 {
7418 int endian = (WORDS_BIG_ENDIAN == 0);
7419 long l[2];
7420
7421 <real_value_to_target> (*CONST_DOUBLE_REAL_VALUE (operands[1]), l);
7422
7423 operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode);
7424 operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode);
7425 operands[4] = gen_int_mode (l[endian], SImode);
7426 operands[5] = gen_int_mode (l[1 - endian], SImode);
7427 }")
7428
7429 (define_split
7430 [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "")
7431 (match_operand:FMOVE64 1 "const_double_operand" ""))]
7432 "TARGET_POWERPC64 && reload_completed
7433 && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
7434 || (GET_CODE (operands[0]) == SUBREG
7435 && GET_CODE (SUBREG_REG (operands[0])) == REG
7436 && REGNO (SUBREG_REG (operands[0])) <= 31))"
7437 [(set (match_dup 2) (match_dup 3))]
7438 "
7439 {
7440 int endian = (WORDS_BIG_ENDIAN == 0);
7441 long l[2];
7442 HOST_WIDE_INT val;
7443
7444 <real_value_to_target> (*CONST_DOUBLE_REAL_VALUE (operands[1]), l);
7445
7446 operands[2] = gen_lowpart (DImode, operands[0]);
7447 /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN. */
7448 val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32
7449 | ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
7450
7451 operands[3] = gen_int_mode (val, DImode);
7452 }")
7453
7454 ;; Don't have reload use general registers to load a constant. It is
7455 ;; less efficient than loading the constant into an FP register, since
7456 ;; it will probably be used there.
7457
7458 ;; The move constraints are ordered to prefer floating point registers before
7459 ;; general purpose registers to avoid doing a store and a load to get the value
7460 ;; into a floating point register when it is needed for a floating point
7461 ;; operation. Prefer traditional floating point registers over VSX registers,
7462 ;; since the D-form version of the memory instructions does not need a GPR for
7463 ;; reloading. ISA 3.0 (power9) adds D-form addressing for scalars to Altivec
7464 ;; registers.
7465
7466 ;; If we have FPR registers, rs6000_emit_move has moved all constants to memory,
7467 ;; except for 0.0 which can be created on VSX with an xor instruction.
7468
7469 (define_insn "*mov<mode>_hardfloat32"
7470 [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,<f64_av>,Z,<f64_p9>,wY,<f64_vsx>,<f64_vsx>,!r,Y,r,!r")
7471 (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,<f64_av>,wY,<f64_p9>,<f64_vsx>,<zero_fp>,<zero_fp>,r,Y,r"))]
7472 "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
7473 && (gpc_reg_operand (operands[0], <MODE>mode)
7474 || gpc_reg_operand (operands[1], <MODE>mode))"
7475 "@
7476 stfd%U0%X0 %1,%0
7477 lfd%U1%X1 %0,%1
7478 fmr %0,%1
7479 lxsd%U1x %x0,%y1
7480 stxsd%U0x %x1,%y0
7481 lxsd %0,%1
7482 stxsd %1,%0
7483 xxlor %x0,%x1,%x1
7484 xxlxor %x0,%x0,%x0
7485 #
7486 #
7487 #
7488 #"
7489 [(set_attr "type" "fpstore,fpload,fpsimple,fpload,fpstore,fpload,fpstore,veclogical,veclogical,two,store,load,two")
7490 (set_attr "size" "64")
7491 (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8,8,8")])
7492
7493 (define_insn "*mov<mode>_softfloat32"
7494 [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
7495 (match_operand:FMOVE64 1 "input_operand" "r,Y,r,G,H,F"))]
7496 "! TARGET_POWERPC64
7497 && ((TARGET_FPRS && TARGET_SINGLE_FLOAT)
7498 || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE
7499 || (<MODE>mode == DDmode && TARGET_E500_DOUBLE))
7500 && (gpc_reg_operand (operands[0], <MODE>mode)
7501 || gpc_reg_operand (operands[1], <MODE>mode))"
7502 "#"
7503 [(set_attr "type" "store,load,two,*,*,*")
7504 (set_attr "length" "8,8,8,8,12,16")])
7505
7506 ; ld/std require word-aligned displacements -> 'Y' constraint.
7507 ; List Y->r and r->Y before r->r for reload.
7508 (define_insn "*mov<mode>_hardfloat64"
7509 [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,<f64_p9>,wY,<f64_av>,Z,<f64_vsx>,<f64_vsx>,!r,Y,r,!r,*c*l,!r,*h,r,wg,r,<f64_dm>")
7510 (match_operand:FMOVE64 1 "input_operand" "d,m,d,wY,<f64_p9>,Z,<f64_av>,<f64_vsx>,<zero_fp>,<zero_fp>,r,Y,r,r,h,0,wg,r,<f64_dm>,r"))]
7511 "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
7512 && (gpc_reg_operand (operands[0], <MODE>mode)
7513 || gpc_reg_operand (operands[1], <MODE>mode))"
7514 "@
7515 stfd%U0%X0 %1,%0
7516 lfd%U1%X1 %0,%1
7517 fmr %0,%1
7518 lxsd %0,%1
7519 stxsd %1,%0
7520 lxsd%U1x %x0,%y1
7521 stxsd%U0x %x1,%y0
7522 xxlor %x0,%x1,%x1
7523 xxlxor %x0,%x0,%x0
7524 li %0,0
7525 std%U0%X0 %1,%0
7526 ld%U1%X1 %0,%1
7527 mr %0,%1
7528 mt%0 %1
7529 mf%1 %0
7530 nop
7531 mftgpr %0,%1
7532 mffgpr %0,%1
7533 mfvsrd %0,%x1
7534 mtvsrd %x0,%1"
7535 [(set_attr "type" "fpstore,fpload,fpsimple,fpload,fpstore,fpload,fpstore,veclogical,veclogical,integer,store,load,*,mtjmpr,mfjmpr,*,mftgpr,mffgpr,mftgpr,mffgpr")
7536 (set_attr "size" "64")
7537 (set_attr "length" "4")])
7538
7539 (define_insn "*mov<mode>_softfloat64"
7540 [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h")
7541 (match_operand:FMOVE64 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))]
7542 "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
7543 && (gpc_reg_operand (operands[0], <MODE>mode)
7544 || gpc_reg_operand (operands[1], <MODE>mode))"
7545 "@
7546 std%U0%X0 %1,%0
7547 ld%U1%X1 %0,%1
7548 mr %0,%1
7549 mt%0 %1
7550 mf%1 %0
7551 #
7552 #
7553 #
7554 nop"
7555 [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*")
7556 (set_attr "length" "4,4,4,4,4,8,12,16,4")])
7557 \f
7558 (define_expand "mov<mode>"
7559 [(set (match_operand:FMOVE128 0 "general_operand" "")
7560 (match_operand:FMOVE128 1 "any_operand" ""))]
7561 ""
7562 "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
7563
7564 ;; It's important to list Y->r and r->Y before r->r because otherwise
7565 ;; reload, given m->r, will try to pick r->r and reload it, which
7566 ;; doesn't make progress.
7567
7568 ;; We can't split little endian direct moves of TDmode, because the words are
7569 ;; not swapped like they are for TImode or TFmode. Subregs therefore are
7570 ;; problematical. Don't allow direct move for this case.
7571
7572 (define_insn_and_split "*mov<mode>_64bit_dm"
7573 [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r,r,wh")
7574 (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,<zero_fp>,r,<zero_fp>Y,r,wh,r"))]
7575 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
7576 && FLOAT128_2REG_P (<MODE>mode)
7577 && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
7578 && (gpc_reg_operand (operands[0], <MODE>mode)
7579 || gpc_reg_operand (operands[1], <MODE>mode))"
7580 "#"
7581 "&& reload_completed"
7582 [(pc)]
7583 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
7584 [(set_attr "length" "8,8,8,8,12,12,8,8,8")])
7585
7586 (define_insn_and_split "*movtd_64bit_nodm"
7587 [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
7588 (match_operand:TD 1 "input_operand" "d,m,d,r,Y,r"))]
7589 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 && !WORDS_BIG_ENDIAN
7590 && (gpc_reg_operand (operands[0], TDmode)
7591 || gpc_reg_operand (operands[1], TDmode))"
7592 "#"
7593 "&& reload_completed"
7594 [(pc)]
7595 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
7596 [(set_attr "length" "8,8,8,12,12,8")])
7597
7598 (define_insn_and_split "*mov<mode>_32bit"
7599 [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r")
7600 (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,<zero_fp>,r,<zero_fp>Y,r"))]
7601 "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
7602 && (FLOAT128_2REG_P (<MODE>mode)
7603 || int_reg_operand_not_pseudo (operands[0], <MODE>mode)
7604 || int_reg_operand_not_pseudo (operands[1], <MODE>mode))
7605 && (gpc_reg_operand (operands[0], <MODE>mode)
7606 || gpc_reg_operand (operands[1], <MODE>mode))"
7607 "#"
7608 "&& reload_completed"
7609 [(pc)]
7610 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
7611 [(set_attr "length" "8,8,8,8,20,20,16")])
7612
7613 (define_insn_and_split "*mov<mode>_softfloat"
7614 [(set (match_operand:FMOVE128 0 "rs6000_nonimmediate_operand" "=Y,r,r")
7615 (match_operand:FMOVE128 1 "input_operand" "r,YGHF,r"))]
7616 "(TARGET_SOFT_FLOAT || !TARGET_FPRS)
7617 && (gpc_reg_operand (operands[0], <MODE>mode)
7618 || gpc_reg_operand (operands[1], <MODE>mode))"
7619 "#"
7620 "&& reload_completed"
7621 [(pc)]
7622 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
7623 [(set_attr "length" "20,20,16")])
7624
7625 (define_expand "extenddf<mode>2"
7626 [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
7627 (float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand" "")))]
7628 "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)
7629 && TARGET_LONG_DOUBLE_128"
7630 {
7631 if (FLOAT128_IEEE_P (<MODE>mode))
7632 rs6000_expand_float128_convert (operands[0], operands[1], false);
7633 else if (TARGET_E500_DOUBLE)
7634 {
7635 gcc_assert (<MODE>mode == TFmode);
7636 emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
7637 }
7638 else if (TARGET_VSX)
7639 {
7640 if (<MODE>mode == TFmode)
7641 emit_insn (gen_extenddftf2_vsx (operands[0], operands[1]));
7642 else if (<MODE>mode == IFmode)
7643 emit_insn (gen_extenddfif2_vsx (operands[0], operands[1]));
7644 else
7645 gcc_unreachable ();
7646 }
7647 else
7648 {
7649 rtx zero = gen_reg_rtx (DFmode);
7650 rs6000_emit_move (zero, CONST0_RTX (DFmode), DFmode);
7651
7652 if (<MODE>mode == TFmode)
7653 emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero));
7654 else if (<MODE>mode == IFmode)
7655 emit_insn (gen_extenddfif2_fprs (operands[0], operands[1], zero));
7656 else
7657 gcc_unreachable ();
7658 }
7659 DONE;
7660 })
7661
7662 ;; Allow memory operands for the source to be created by the combiner.
7663 (define_insn_and_split "extenddf<mode>2_fprs"
7664 [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d,&d")
7665 (float_extend:IBM128
7666 (match_operand:DF 1 "nonimmediate_operand" "d,m,d")))
7667 (use (match_operand:DF 2 "nonimmediate_operand" "m,m,d"))]
7668 "!TARGET_VSX && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
7669 && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)"
7670 "#"
7671 "&& reload_completed"
7672 [(set (match_dup 3) (match_dup 1))
7673 (set (match_dup 4) (match_dup 2))]
7674 {
7675 const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
7676 const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
7677
7678 operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
7679 operands[4] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
7680 })
7681
7682 (define_insn_and_split "extenddf<mode>2_vsx"
7683 [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d")
7684 (float_extend:IBM128
7685 (match_operand:DF 1 "nonimmediate_operand" "ws,m")))]
7686 "TARGET_LONG_DOUBLE_128 && TARGET_VSX && FLOAT128_IBM_P (<MODE>mode)"
7687 "#"
7688 "&& reload_completed"
7689 [(set (match_dup 2) (match_dup 1))
7690 (set (match_dup 3) (match_dup 4))]
7691 {
7692 const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
7693 const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
7694
7695 operands[2] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
7696 operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
7697 operands[4] = CONST0_RTX (DFmode);
7698 })
7699
7700 (define_expand "extendsf<mode>2"
7701 [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
7702 (float_extend:FLOAT128 (match_operand:SF 1 "gpc_reg_operand" "")))]
7703 "TARGET_HARD_FLOAT
7704 && (TARGET_FPRS || TARGET_E500_DOUBLE)
7705 && TARGET_LONG_DOUBLE_128"
7706 {
7707 if (FLOAT128_IEEE_P (<MODE>mode))
7708 rs6000_expand_float128_convert (operands[0], operands[1], false);
7709 else
7710 {
7711 rtx tmp = gen_reg_rtx (DFmode);
7712 emit_insn (gen_extendsfdf2 (tmp, operands[1]));
7713 emit_insn (gen_extenddf<mode>2 (operands[0], tmp));
7714 }
7715 DONE;
7716 })
7717
7718 (define_expand "trunc<mode>df2"
7719 [(set (match_operand:DF 0 "gpc_reg_operand" "")
7720 (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
7721 "TARGET_HARD_FLOAT
7722 && (TARGET_FPRS || TARGET_E500_DOUBLE)
7723 && TARGET_LONG_DOUBLE_128"
7724 {
7725 if (FLOAT128_IEEE_P (<MODE>mode))
7726 {
7727 rs6000_expand_float128_convert (operands[0], operands[1], false);
7728 DONE;
7729 }
7730 })
7731
7732 (define_insn_and_split "trunc<mode>df2_internal1"
7733 [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d")
7734 (float_truncate:DF
7735 (match_operand:IBM128 1 "gpc_reg_operand" "0,d")))]
7736 "FLOAT128_IBM_P (<MODE>mode) && !TARGET_XL_COMPAT
7737 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
7738 "@
7739 #
7740 fmr %0,%1"
7741 "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
7742 [(const_int 0)]
7743 {
7744 emit_note (NOTE_INSN_DELETED);
7745 DONE;
7746 }
7747 [(set_attr "type" "fpsimple")])
7748
7749 (define_insn "trunc<mode>df2_internal2"
7750 [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
7751 (float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "d")))]
7752 "FLOAT128_IBM_P (<MODE>mode) && TARGET_XL_COMPAT && TARGET_HARD_FLOAT
7753 && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
7754 "fadd %0,%1,%L1"
7755 [(set_attr "type" "fp")
7756 (set_attr "fp_type" "fp_addsub_d")])
7757
7758 (define_expand "trunc<mode>sf2"
7759 [(set (match_operand:SF 0 "gpc_reg_operand" "")
7760 (float_truncate:SF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
7761 "TARGET_HARD_FLOAT
7762 && (TARGET_FPRS || TARGET_E500_DOUBLE)
7763 && TARGET_LONG_DOUBLE_128"
7764 {
7765 if (FLOAT128_IEEE_P (<MODE>mode))
7766 rs6000_expand_float128_convert (operands[0], operands[1], false);
7767 else if (TARGET_E500_DOUBLE)
7768 {
7769 gcc_assert (<MODE>mode == TFmode);
7770 emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
7771 }
7772 else if (<MODE>mode == TFmode)
7773 emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1]));
7774 else if (<MODE>mode == IFmode)
7775 emit_insn (gen_truncifsf2_fprs (operands[0], operands[1]));
7776 else
7777 gcc_unreachable ();
7778 DONE;
7779 })
7780
7781 (define_insn_and_split "trunc<mode>sf2_fprs"
7782 [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
7783 (float_truncate:SF (match_operand:IBM128 1 "gpc_reg_operand" "d")))
7784 (clobber (match_scratch:DF 2 "=d"))]
7785 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
7786 && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)"
7787 "#"
7788 "&& reload_completed"
7789 [(set (match_dup 2)
7790 (float_truncate:DF (match_dup 1)))
7791 (set (match_dup 0)
7792 (float_truncate:SF (match_dup 2)))]
7793 "")
7794
7795 (define_expand "floatsi<mode>2"
7796 [(parallel [(set (match_operand:FLOAT128 0 "gpc_reg_operand")
7797 (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand")))
7798 (clobber (match_scratch:DI 2))])]
7799 "TARGET_HARD_FLOAT
7800 && (TARGET_FPRS || TARGET_E500_DOUBLE)
7801 && TARGET_LONG_DOUBLE_128"
7802 {
7803 rtx op0 = operands[0];
7804 rtx op1 = operands[1];
7805
7806 if (TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode))
7807 ;
7808 else if (FLOAT128_IEEE_P (<MODE>mode))
7809 {
7810 rs6000_expand_float128_convert (op0, op1, false);
7811 DONE;
7812 }
7813 else
7814 {
7815 rtx tmp = gen_reg_rtx (DFmode);
7816 expand_float (tmp, op1, false);
7817 if (<MODE>mode == TFmode)
7818 emit_insn (gen_extenddftf2 (op0, tmp));
7819 else if (<MODE>mode == IFmode)
7820 emit_insn (gen_extenddfif2 (op0, tmp));
7821 else
7822 gcc_unreachable ();
7823 DONE;
7824 }
7825 })
7826
7827 ; fadd, but rounding towards zero.
7828 ; This is probably not the optimal code sequence.
7829 (define_insn "fix_trunc_helper<mode>"
7830 [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
7831 (unspec:DF [(match_operand:IBM128 1 "gpc_reg_operand" "d")]
7832 UNSPEC_FIX_TRUNC_TF))
7833 (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))]
7834 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
7835 && FLOAT128_IBM_P (<MODE>mode)"
7836 "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2"
7837 [(set_attr "type" "fp")
7838 (set_attr "length" "20")])
7839
7840 (define_expand "fix_trunc<mode>si2"
7841 [(set (match_operand:SI 0 "gpc_reg_operand" "")
7842 (fix:SI (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
7843 "TARGET_HARD_FLOAT
7844 && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128"
7845 {
7846 rtx op0 = operands[0];
7847 rtx op1 = operands[1];
7848
7849 if (TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode))
7850 ;
7851 else
7852 {
7853 if (FLOAT128_IEEE_P (<MODE>mode))
7854 rs6000_expand_float128_convert (op0, op1, false);
7855 else if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
7856 emit_insn (gen_spe_fix_trunctfsi2 (op0, op1));
7857 else if (<MODE>mode == TFmode)
7858 emit_insn (gen_fix_trunctfsi2_fprs (op0, op1));
7859 else if (<MODE>mode == IFmode)
7860 emit_insn (gen_fix_truncifsi2_fprs (op0, op1));
7861 else
7862 gcc_unreachable ();
7863 DONE;
7864 }
7865 })
7866
7867 (define_expand "fix_trunc<mode>si2_fprs"
7868 [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
7869 (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "")))
7870 (clobber (match_dup 2))
7871 (clobber (match_dup 3))
7872 (clobber (match_dup 4))
7873 (clobber (match_dup 5))])]
7874 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
7875 {
7876 operands[2] = gen_reg_rtx (DFmode);
7877 operands[3] = gen_reg_rtx (DFmode);
7878 operands[4] = gen_reg_rtx (DImode);
7879 operands[5] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode));
7880 })
7881
7882 (define_insn_and_split "*fix_trunc<mode>si2_internal"
7883 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
7884 (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "d")))
7885 (clobber (match_operand:DF 2 "gpc_reg_operand" "=d"))
7886 (clobber (match_operand:DF 3 "gpc_reg_operand" "=&d"))
7887 (clobber (match_operand:DI 4 "gpc_reg_operand" "=d"))
7888 (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))]
7889 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
7890 "#"
7891 ""
7892 [(pc)]
7893 {
7894 rtx lowword;
7895 emit_insn (gen_fix_trunc_helper<mode> (operands[2], operands[1],
7896 operands[3]));
7897
7898 gcc_assert (MEM_P (operands[5]));
7899 lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
7900
7901 emit_insn (gen_fctiwz_df (operands[4], operands[2]));
7902 emit_move_insn (operands[5], operands[4]);
7903 emit_move_insn (operands[0], lowword);
7904 DONE;
7905 })
7906
7907 (define_expand "fix_trunc<mode>di2"
7908 [(set (match_operand:DI 0 "gpc_reg_operand" "")
7909 (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
7910 "TARGET_FLOAT128_TYPE"
7911 {
7912 if (!TARGET_FLOAT128_HW)
7913 {
7914 rs6000_expand_float128_convert (operands[0], operands[1], false);
7915 DONE;
7916 }
7917 })
7918
7919 (define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2"
7920 [(set (match_operand:SDI 0 "gpc_reg_operand" "")
7921 (unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
7922 "TARGET_FLOAT128_TYPE"
7923 {
7924 rs6000_expand_float128_convert (operands[0], operands[1], true);
7925 DONE;
7926 })
7927
7928 (define_expand "floatdi<mode>2"
7929 [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
7930 (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
7931 "TARGET_FLOAT128_TYPE"
7932 {
7933 if (!TARGET_FLOAT128_HW)
7934 {
7935 rs6000_expand_float128_convert (operands[0], operands[1], false);
7936 DONE;
7937 }
7938 })
7939
7940 (define_expand "floatunsdi<IEEE128:mode>2"
7941 [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
7942 (unsigned_float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
7943 "TARGET_FLOAT128_TYPE"
7944 {
7945 if (!TARGET_FLOAT128_HW)
7946 {
7947 rs6000_expand_float128_convert (operands[0], operands[1], true);
7948 DONE;
7949 }
7950 })
7951
7952 (define_expand "floatuns<IEEE128:mode>2"
7953 [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
7954 (unsigned_float:IEEE128 (match_operand:SI 1 "gpc_reg_operand" "")))]
7955 "TARGET_FLOAT128_TYPE"
7956 {
7957 rtx op0 = operands[0];
7958 rtx op1 = operands[1];
7959
7960 if (TARGET_FLOAT128_HW)
7961 emit_insn (gen_floatuns_<IEEE128:mode>si2_hw (op0, op1));
7962 else
7963 rs6000_expand_float128_convert (op0, op1, true);
7964 DONE;
7965 })
7966
7967 (define_expand "neg<mode>2"
7968 [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
7969 (neg:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
7970 "FLOAT128_IEEE_P (<MODE>mode)
7971 || (FLOAT128_IBM_P (<MODE>mode)
7972 && TARGET_HARD_FLOAT
7973 && (TARGET_FPRS || TARGET_E500_DOUBLE))"
7974 "
7975 {
7976 if (FLOAT128_IEEE_P (<MODE>mode))
7977 {
7978 if (TARGET_FLOAT128_HW)
7979 {
7980 if (<MODE>mode == TFmode)
7981 emit_insn (gen_negtf2_hw (operands[0], operands[1]));
7982 else if (<MODE>mode == KFmode)
7983 emit_insn (gen_negkf2_hw (operands[0], operands[1]));
7984 else
7985 gcc_unreachable ();
7986 }
7987 else if (TARGET_FLOAT128_TYPE)
7988 {
7989 if (<MODE>mode == TFmode)
7990 emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
7991 else if (<MODE>mode == KFmode)
7992 emit_insn (gen_ieee_128bit_vsx_negkf2 (operands[0], operands[1]));
7993 else
7994 gcc_unreachable ();
7995 }
7996 else
7997 {
7998 rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
7999 rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST,
8000 <MODE>mode,
8001 operands[1], <MODE>mode);
8002
8003 if (target && !rtx_equal_p (target, operands[0]))
8004 emit_move_insn (operands[0], target);
8005 }
8006 DONE;
8007 }
8008 }")
8009
8010 (define_insn "neg<mode>2_internal"
8011 [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d")
8012 (neg:IBM128 (match_operand:IBM128 1 "gpc_reg_operand" "d")))]
8013 "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
8014 "*
8015 {
8016 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
8017 return \"fneg %L0,%L1\;fneg %0,%1\";
8018 else
8019 return \"fneg %0,%1\;fneg %L0,%L1\";
8020 }"
8021 [(set_attr "type" "fpsimple")
8022 (set_attr "length" "8")])
8023
8024 (define_expand "abs<mode>2"
8025 [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
8026 (abs:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
8027 "FLOAT128_IEEE_P (<MODE>mode)
8028 || (FLOAT128_IBM_P (<MODE>mode)
8029 && TARGET_HARD_FLOAT
8030 && (TARGET_FPRS || TARGET_E500_DOUBLE))"
8031 "
8032 {
8033 rtx label;
8034
8035 if (FLOAT128_IEEE_P (<MODE>mode))
8036 {
8037 if (TARGET_FLOAT128_HW)
8038 {
8039 if (<MODE>mode == TFmode)
8040 emit_insn (gen_abstf2_hw (operands[0], operands[1]));
8041 else if (<MODE>mode == KFmode)
8042 emit_insn (gen_abskf2_hw (operands[0], operands[1]));
8043 else
8044 FAIL;
8045 DONE;
8046 }
8047 else if (TARGET_FLOAT128_TYPE)
8048 {
8049 if (<MODE>mode == TFmode)
8050 emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
8051 else if (<MODE>mode == KFmode)
8052 emit_insn (gen_ieee_128bit_vsx_abskf2 (operands[0], operands[1]));
8053 else
8054 FAIL;
8055 DONE;
8056 }
8057 else
8058 FAIL;
8059 }
8060
8061 label = gen_label_rtx ();
8062 if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
8063 {
8064 if (flag_finite_math_only && !flag_trapping_math)
8065 emit_insn (gen_spe_abstf2_tst (operands[0], operands[1], label));
8066 else
8067 emit_insn (gen_spe_abstf2_cmp (operands[0], operands[1], label));
8068 }
8069 else if (<MODE>mode == TFmode)
8070 emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
8071 else if (<MODE>mode == TFmode)
8072 emit_insn (gen_absif2_internal (operands[0], operands[1], label));
8073 else
8074 FAIL;
8075 emit_label (label);
8076 DONE;
8077 }")
8078
8079 (define_expand "abs<mode>2_internal"
8080 [(set (match_operand:IBM128 0 "gpc_reg_operand" "")
8081 (match_operand:IBM128 1 "gpc_reg_operand" ""))
8082 (set (match_dup 3) (match_dup 5))
8083 (set (match_dup 5) (abs:DF (match_dup 5)))
8084 (set (match_dup 4) (compare:CCFP (match_dup 3) (match_dup 5)))
8085 (set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
8086 (label_ref (match_operand 2 "" ""))
8087 (pc)))
8088 (set (match_dup 6) (neg:DF (match_dup 6)))]
8089 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
8090 && TARGET_LONG_DOUBLE_128"
8091 "
8092 {
8093 const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
8094 const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
8095 operands[3] = gen_reg_rtx (DFmode);
8096 operands[4] = gen_reg_rtx (CCFPmode);
8097 operands[5] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
8098 operands[6] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
8099 }")
8100
8101 \f
8102 ;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector
8103 ;; register
8104
8105 (define_expand "ieee_128bit_negative_zero"
8106 [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
8107 "TARGET_FLOAT128_TYPE"
8108 {
8109 rtvec v = rtvec_alloc (16);
8110 int i, high;
8111
8112 for (i = 0; i < 16; i++)
8113 RTVEC_ELT (v, i) = const0_rtx;
8114
8115 high = (BYTES_BIG_ENDIAN) ? 0 : 15;
8116 RTVEC_ELT (v, high) = gen_int_mode (0x80, QImode);
8117
8118 rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v));
8119 DONE;
8120 })
8121
8122 ;; IEEE 128-bit negate
8123
8124 ;; We have 2 insns here for negate and absolute value. The first uses
8125 ;; match_scratch so that phases like combine can recognize neg/abs as generic
8126 ;; insns, and second insn after the first split pass loads up the bit to
8127 ;; twiddle the sign bit. Later GCSE passes can then combine multiple uses of
8128 ;; neg/abs to create the constant just once.
8129
8130 (define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
8131 [(set (match_operand:IEEE128 0 "register_operand" "=wa")
8132 (neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
8133 (clobber (match_scratch:V16QI 2 "=v"))]
8134 "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
8135 "#"
8136 "&& 1"
8137 [(parallel [(set (match_dup 0)
8138 (neg:IEEE128 (match_dup 1)))
8139 (use (match_dup 2))])]
8140 {
8141 if (GET_CODE (operands[2]) == SCRATCH)
8142 operands[2] = gen_reg_rtx (V16QImode);
8143
8144 operands[3] = gen_reg_rtx (V16QImode);
8145 emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
8146 }
8147 [(set_attr "length" "8")
8148 (set_attr "type" "vecsimple")])
8149
8150 (define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
8151 [(set (match_operand:IEEE128 0 "register_operand" "=wa")
8152 (neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
8153 (use (match_operand:V16QI 2 "register_operand" "v"))]
8154 "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
8155 "xxlxor %x0,%x1,%x2"
8156 [(set_attr "type" "veclogical")])
8157
8158 ;; IEEE 128-bit absolute value
8159 (define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
8160 [(set (match_operand:IEEE128 0 "register_operand" "=wa")
8161 (abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
8162 (clobber (match_scratch:V16QI 2 "=v"))]
8163 "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
8164 "#"
8165 "&& 1"
8166 [(parallel [(set (match_dup 0)
8167 (abs:IEEE128 (match_dup 1)))
8168 (use (match_dup 2))])]
8169 {
8170 if (GET_CODE (operands[2]) == SCRATCH)
8171 operands[2] = gen_reg_rtx (V16QImode);
8172
8173 operands[3] = gen_reg_rtx (V16QImode);
8174 emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
8175 }
8176 [(set_attr "length" "8")
8177 (set_attr "type" "vecsimple")])
8178
8179 (define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
8180 [(set (match_operand:IEEE128 0 "register_operand" "=wa")
8181 (abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
8182 (use (match_operand:V16QI 2 "register_operand" "v"))]
8183 "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
8184 "xxlandc %x0,%x1,%x2"
8185 [(set_attr "type" "veclogical")])
8186
8187 ;; IEEE 128-bit negative absolute value
8188 (define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
8189 [(set (match_operand:IEEE128 0 "register_operand" "=wa")
8190 (neg:IEEE128
8191 (abs:IEEE128
8192 (match_operand:IEEE128 1 "register_operand" "wa"))))
8193 (clobber (match_scratch:V16QI 2 "=v"))]
8194 "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW
8195 && FLOAT128_IEEE_P (<MODE>mode)"
8196 "#"
8197 "&& 1"
8198 [(parallel [(set (match_dup 0)
8199 (neg:IEEE128 (abs:IEEE128 (match_dup 1))))
8200 (use (match_dup 2))])]
8201 {
8202 if (GET_CODE (operands[2]) == SCRATCH)
8203 operands[2] = gen_reg_rtx (V16QImode);
8204
8205 operands[3] = gen_reg_rtx (V16QImode);
8206 emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
8207 }
8208 [(set_attr "length" "8")
8209 (set_attr "type" "vecsimple")])
8210
8211 (define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
8212 [(set (match_operand:IEEE128 0 "register_operand" "=wa")
8213 (neg:IEEE128
8214 (abs:IEEE128
8215 (match_operand:IEEE128 1 "register_operand" "wa"))))
8216 (use (match_operand:V16QI 2 "register_operand" "v"))]
8217 "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
8218 "xxlor %x0,%x1,%x2"
8219 [(set_attr "type" "veclogical")])
8220
8221 ;; Float128 conversion functions. These expand to library function calls.
8222 ;; We use expand to convert from IBM double double to IEEE 128-bit
8223 ;; and trunc for the opposite.
8224 (define_expand "extendiftf2"
8225 [(set (match_operand:TF 0 "gpc_reg_operand" "")
8226 (float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "")))]
8227 "TARGET_FLOAT128_TYPE"
8228 {
8229 rs6000_expand_float128_convert (operands[0], operands[1], false);
8230 DONE;
8231 })
8232
8233 (define_expand "extendifkf2"
8234 [(set (match_operand:KF 0 "gpc_reg_operand" "")
8235 (float_extend:KF (match_operand:IF 1 "gpc_reg_operand" "")))]
8236 "TARGET_FLOAT128_TYPE"
8237 {
8238 rs6000_expand_float128_convert (operands[0], operands[1], false);
8239 DONE;
8240 })
8241
8242 (define_expand "extendtfkf2"
8243 [(set (match_operand:KF 0 "gpc_reg_operand" "")
8244 (float_extend:KF (match_operand:TF 1 "gpc_reg_operand" "")))]
8245 "TARGET_FLOAT128_TYPE"
8246 {
8247 rs6000_expand_float128_convert (operands[0], operands[1], false);
8248 DONE;
8249 })
8250
8251 (define_expand "trunciftf2"
8252 [(set (match_operand:IF 0 "gpc_reg_operand" "")
8253 (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
8254 "TARGET_FLOAT128_TYPE"
8255 {
8256 rs6000_expand_float128_convert (operands[0], operands[1], false);
8257 DONE;
8258 })
8259
8260 (define_expand "truncifkf2"
8261 [(set (match_operand:IF 0 "gpc_reg_operand" "")
8262 (float_truncate:IF (match_operand:KF 1 "gpc_reg_operand" "")))]
8263 "TARGET_FLOAT128_TYPE"
8264 {
8265 rs6000_expand_float128_convert (operands[0], operands[1], false);
8266 DONE;
8267 })
8268
8269 (define_expand "trunckftf2"
8270 [(set (match_operand:TF 0 "gpc_reg_operand" "")
8271 (float_truncate:TF (match_operand:KF 1 "gpc_reg_operand" "")))]
8272 "TARGET_FLOAT128_TYPE"
8273 {
8274 rs6000_expand_float128_convert (operands[0], operands[1], false);
8275 DONE;
8276 })
8277
8278 (define_expand "trunctfif2"
8279 [(set (match_operand:IF 0 "gpc_reg_operand" "")
8280 (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
8281 "TARGET_FLOAT128_TYPE"
8282 {
8283 rs6000_expand_float128_convert (operands[0], operands[1], false);
8284 DONE;
8285 })
8286
8287 \f
8288 ;; Reload helper functions used by rs6000_secondary_reload. The patterns all
8289 ;; must have 3 arguments, and scratch register constraint must be a single
8290 ;; constraint.
8291
8292 ;; Reload patterns to support gpr load/store with misaligned mem.
8293 ;; and multiple gpr load/store at offset >= 0xfffc
8294 (define_expand "reload_<mode>_store"
8295 [(parallel [(match_operand 0 "memory_operand" "=m")
8296 (match_operand 1 "gpc_reg_operand" "r")
8297 (match_operand:GPR 2 "register_operand" "=&b")])]
8298 ""
8299 {
8300 rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true);
8301 DONE;
8302 })
8303
8304 (define_expand "reload_<mode>_load"
8305 [(parallel [(match_operand 0 "gpc_reg_operand" "=r")
8306 (match_operand 1 "memory_operand" "m")
8307 (match_operand:GPR 2 "register_operand" "=b")])]
8308 ""
8309 {
8310 rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false);
8311 DONE;
8312 })
8313
8314 \f
8315 ;; Reload patterns for various types using the vector registers. We may need
8316 ;; an additional base register to convert the reg+offset addressing to reg+reg
8317 ;; for vector registers and reg+reg or (reg+reg)&(-16) addressing to just an
8318 ;; index register for gpr registers.
8319 (define_expand "reload_<RELOAD:mode>_<P:mptrsize>_store"
8320 [(parallel [(match_operand:RELOAD 0 "memory_operand" "m")
8321 (match_operand:RELOAD 1 "gpc_reg_operand" "wa")
8322 (match_operand:P 2 "register_operand" "=b")])]
8323 "<P:tptrsize>"
8324 {
8325 rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true);
8326 DONE;
8327 })
8328
8329 (define_expand "reload_<RELOAD:mode>_<P:mptrsize>_load"
8330 [(parallel [(match_operand:RELOAD 0 "gpc_reg_operand" "wa")
8331 (match_operand:RELOAD 1 "memory_operand" "m")
8332 (match_operand:P 2 "register_operand" "=b")])]
8333 "<P:tptrsize>"
8334 {
8335 rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false);
8336 DONE;
8337 })
8338
8339
8340 ;; Reload sometimes tries to move the address to a GPR, and can generate
8341 ;; invalid RTL for addresses involving AND -16. Allow addresses involving
8342 ;; reg+reg, reg+small constant, or just reg, all wrapped in an AND -16.
8343
8344 (define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
8345 [(set (match_operand:P 0 "gpc_reg_operand" "=b")
8346 (and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
8347 (match_operand:P 2 "reg_or_cint_operand" "rI"))
8348 (const_int -16)))]
8349 "TARGET_ALTIVEC && (reload_in_progress || reload_completed)"
8350 "#"
8351 "&& reload_completed"
8352 [(set (match_dup 0)
8353 (plus:P (match_dup 1)
8354 (match_dup 2)))
8355 (set (match_dup 0)
8356 (and:P (match_dup 0)
8357 (const_int -16)))])
8358 \f
8359 ;; Power8 merge instructions to allow direct move to/from floating point
8360 ;; registers in 32-bit mode. We use TF mode to get two registers to move the
8361 ;; individual 32-bit parts across. Subreg doesn't work too well on the TF
8362 ;; value, since it is allocated in reload and not all of the flow information
8363 ;; is setup for it. We have two patterns to do the two moves between gprs and
8364 ;; fprs. There isn't a dependancy between the two, but we could potentially
8365 ;; schedule other instructions between the two instructions.
8366
8367 (define_insn "p8_fmrgow_<mode>"
8368 [(set (match_operand:FMOVE64X 0 "register_operand" "=d")
8369 (unspec:FMOVE64X [
8370 (match_operand:DF 1 "register_operand" "d")
8371 (match_operand:DF 2 "register_operand" "d")]
8372 UNSPEC_P8V_FMRGOW))]
8373 "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8374 "fmrgow %0,%1,%2"
8375 [(set_attr "type" "fpsimple")])
8376
8377 (define_insn "p8_mtvsrwz"
8378 [(set (match_operand:DF 0 "register_operand" "=d")
8379 (unspec:DF [(match_operand:SI 1 "register_operand" "r")]
8380 UNSPEC_P8V_MTVSRWZ))]
8381 "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8382 "mtvsrwz %x0,%1"
8383 [(set_attr "type" "mftgpr")])
8384
8385 (define_insn_and_split "reload_fpr_from_gpr<mode>"
8386 [(set (match_operand:FMOVE64X 0 "register_operand" "=d")
8387 (unspec:FMOVE64X [(match_operand:FMOVE64X 1 "register_operand" "r")]
8388 UNSPEC_P8V_RELOAD_FROM_GPR))
8389 (clobber (match_operand:IF 2 "register_operand" "=d"))]
8390 "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8391 "#"
8392 "&& reload_completed"
8393 [(const_int 0)]
8394 {
8395 rtx dest = operands[0];
8396 rtx src = operands[1];
8397 rtx tmp_hi = simplify_gen_subreg (DFmode, operands[2], IFmode, 0);
8398 rtx tmp_lo = simplify_gen_subreg (DFmode, operands[2], IFmode, 8);
8399 rtx gpr_hi_reg = gen_highpart (SImode, src);
8400 rtx gpr_lo_reg = gen_lowpart (SImode, src);
8401
8402 emit_insn (gen_p8_mtvsrwz (tmp_hi, gpr_hi_reg));
8403 emit_insn (gen_p8_mtvsrwz (tmp_lo, gpr_lo_reg));
8404 emit_insn (gen_p8_fmrgow_<mode> (dest, tmp_hi, tmp_lo));
8405 DONE;
8406 }
8407 [(set_attr "length" "12")
8408 (set_attr "type" "three")])
8409
8410 ;; Move 128 bit values from GPRs to VSX registers in 64-bit mode
8411 (define_insn "p8_mtvsrd_df"
8412 [(set (match_operand:DF 0 "register_operand" "=wa")
8413 (unspec:DF [(match_operand:DI 1 "register_operand" "r")]
8414 UNSPEC_P8V_MTVSRD))]
8415 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8416 "mtvsrd %x0,%1"
8417 [(set_attr "type" "mftgpr")])
8418
8419 (define_insn "p8_xxpermdi_<mode>"
8420 [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa")
8421 (unspec:FMOVE128_GPR [
8422 (match_operand:DF 1 "register_operand" "wa")
8423 (match_operand:DF 2 "register_operand" "wa")]
8424 UNSPEC_P8V_XXPERMDI))]
8425 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8426 "xxpermdi %x0,%x1,%x2,0"
8427 [(set_attr "type" "vecperm")])
8428
8429 (define_insn_and_split "reload_vsx_from_gpr<mode>"
8430 [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa")
8431 (unspec:FMOVE128_GPR
8432 [(match_operand:FMOVE128_GPR 1 "register_operand" "r")]
8433 UNSPEC_P8V_RELOAD_FROM_GPR))
8434 (clobber (match_operand:IF 2 "register_operand" "=wa"))]
8435 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8436 "#"
8437 "&& reload_completed"
8438 [(const_int 0)]
8439 {
8440 rtx dest = operands[0];
8441 rtx src = operands[1];
8442 /* You might think that we could use op0 as one temp and a DF clobber
8443 as op2, but you'd be wrong. Secondary reload move patterns don't
8444 check for overlap of the clobber and the destination. */
8445 rtx tmp_hi = simplify_gen_subreg (DFmode, operands[2], IFmode, 0);
8446 rtx tmp_lo = simplify_gen_subreg (DFmode, operands[2], IFmode, 8);
8447 rtx gpr_hi_reg = gen_highpart (DImode, src);
8448 rtx gpr_lo_reg = gen_lowpart (DImode, src);
8449
8450 emit_insn (gen_p8_mtvsrd_df (tmp_hi, gpr_hi_reg));
8451 emit_insn (gen_p8_mtvsrd_df (tmp_lo, gpr_lo_reg));
8452 emit_insn (gen_p8_xxpermdi_<mode> (dest, tmp_hi, tmp_lo));
8453 DONE;
8454 }
8455 [(set_attr "length" "12")
8456 (set_attr "type" "three")])
8457
8458 (define_split
8459 [(set (match_operand:FMOVE128_GPR 0 "nonimmediate_operand" "")
8460 (match_operand:FMOVE128_GPR 1 "input_operand" ""))]
8461 "reload_completed
8462 && (int_reg_operand (operands[0], <MODE>mode)
8463 || int_reg_operand (operands[1], <MODE>mode))
8464 && (!TARGET_DIRECT_MOVE_128
8465 || (!vsx_register_operand (operands[0], <MODE>mode)
8466 && !vsx_register_operand (operands[1], <MODE>mode)))"
8467 [(pc)]
8468 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
8469
8470 ;; Move SFmode to a VSX from a GPR register. Because scalar floating point
8471 ;; type is stored internally as double precision in the VSX registers, we have
8472 ;; to convert it from the vector format.
8473 (define_insn "p8_mtvsrd_sf"
8474 [(set (match_operand:SF 0 "register_operand" "=wa")
8475 (unspec:SF [(match_operand:DI 1 "register_operand" "r")]
8476 UNSPEC_P8V_MTVSRD))]
8477 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8478 "mtvsrd %x0,%1"
8479 [(set_attr "type" "mftgpr")])
8480
8481 (define_insn_and_split "reload_vsx_from_gprsf"
8482 [(set (match_operand:SF 0 "register_operand" "=wa")
8483 (unspec:SF [(match_operand:SF 1 "register_operand" "r")]
8484 UNSPEC_P8V_RELOAD_FROM_GPR))
8485 (clobber (match_operand:DI 2 "register_operand" "=r"))]
8486 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8487 "#"
8488 "&& reload_completed"
8489 [(const_int 0)]
8490 {
8491 rtx op0 = operands[0];
8492 rtx op1 = operands[1];
8493 rtx op2 = operands[2];
8494 rtx op1_di = simplify_gen_subreg (DImode, op1, SFmode, 0);
8495
8496 /* Move SF value to upper 32-bits for xscvspdpn. */
8497 emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32)));
8498 emit_insn (gen_p8_mtvsrd_sf (op0, op2));
8499 emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0));
8500 DONE;
8501 }
8502 [(set_attr "length" "8")
8503 (set_attr "type" "two")])
8504
8505 ;; Move 128 bit values from VSX registers to GPRs in 64-bit mode by doing a
8506 ;; normal 64-bit move, followed by an xxpermdi to get the bottom 64-bit value,
8507 ;; and then doing a move of that.
8508 (define_insn "p8_mfvsrd_3_<mode>"
8509 [(set (match_operand:DF 0 "register_operand" "=r")
8510 (unspec:DF [(match_operand:FMOVE128_GPR 1 "register_operand" "wa")]
8511 UNSPEC_P8V_RELOAD_FROM_VSX))]
8512 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8513 "mfvsrd %0,%x1"
8514 [(set_attr "type" "mftgpr")])
8515
8516 (define_insn_and_split "reload_gpr_from_vsx<mode>"
8517 [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=r")
8518 (unspec:FMOVE128_GPR
8519 [(match_operand:FMOVE128_GPR 1 "register_operand" "wa")]
8520 UNSPEC_P8V_RELOAD_FROM_VSX))
8521 (clobber (match_operand:FMOVE128_GPR 2 "register_operand" "=wa"))]
8522 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8523 "#"
8524 "&& reload_completed"
8525 [(const_int 0)]
8526 {
8527 rtx dest = operands[0];
8528 rtx src = operands[1];
8529 rtx tmp = operands[2];
8530 rtx gpr_hi_reg = gen_highpart (DFmode, dest);
8531 rtx gpr_lo_reg = gen_lowpart (DFmode, dest);
8532
8533 emit_insn (gen_p8_mfvsrd_3_<mode> (gpr_hi_reg, src));
8534 emit_insn (gen_vsx_xxpermdi_<mode>_be (tmp, src, src, GEN_INT (3)));
8535 emit_insn (gen_p8_mfvsrd_3_<mode> (gpr_lo_reg, tmp));
8536 DONE;
8537 }
8538 [(set_attr "length" "12")
8539 (set_attr "type" "three")])
8540
8541 ;; Move SFmode to a GPR from a VSX register. Because scalar floating point
8542 ;; type is stored internally as double precision, we have to convert it to the
8543 ;; vector format.
8544
8545 (define_insn_and_split "reload_gpr_from_vsxsf"
8546 [(set (match_operand:SF 0 "register_operand" "=r")
8547 (unspec:SF [(match_operand:SF 1 "register_operand" "wa")]
8548 UNSPEC_P8V_RELOAD_FROM_VSX))
8549 (clobber (match_operand:V4SF 2 "register_operand" "=wa"))]
8550 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8551 "#"
8552 "&& reload_completed"
8553 [(const_int 0)]
8554 {
8555 rtx op0 = operands[0];
8556 rtx op1 = operands[1];
8557 rtx op2 = operands[2];
8558 rtx diop0 = simplify_gen_subreg (DImode, op0, SFmode, 0);
8559
8560 emit_insn (gen_vsx_xscvdpspn_scalar (op2, op1));
8561 emit_insn (gen_p8_mfvsrd_4_disf (diop0, op2));
8562 emit_insn (gen_lshrdi3 (diop0, diop0, GEN_INT (32)));
8563 DONE;
8564 }
8565 [(set_attr "length" "12")
8566 (set_attr "type" "three")])
8567
8568 (define_insn "p8_mfvsrd_4_disf"
8569 [(set (match_operand:DI 0 "register_operand" "=r")
8570 (unspec:DI [(match_operand:V4SF 1 "register_operand" "wa")]
8571 UNSPEC_P8V_RELOAD_FROM_VSX))]
8572 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
8573 "mfvsrd %0,%x1"
8574 [(set_attr "type" "mftgpr")])
8575
8576 \f
8577 ;; Next come the multi-word integer load and store and the load and store
8578 ;; multiple insns.
8579
8580 ;; List r->r after r->Y, otherwise reload will try to reload a
8581 ;; non-offsettable address by using r->r which won't make progress.
8582 ;; Use of fprs is disparaged slightly otherwise reload prefers to reload
8583 ;; a gpr into a fpr instead of reloading an invalid 'Y' address
8584
8585 ;; GPR store GPR load GPR move FPR store FPR load FPR move
8586 ;; GPR const AVX store AVX store AVX load AVX load VSX move
8587 ;; P9 0 P9 -1 AVX 0/-1 VSX 0 VSX -1 P9 const
8588 ;; AVX const
8589
8590 (define_insn "*movdi_internal32"
8591 [(set (match_operand:DI 0 "rs6000_nonimmediate_operand"
8592 "=Y, r, r, ^m, ^d, ^d,
8593 r, ^wY, $Z, ^wb, $wv, ^wi,
8594 *wo, *wo, *wv, *wi, *wi, *wv,
8595 *wv")
8596
8597 (match_operand:DI 1 "input_operand"
8598 "r, Y, r, d, m, d,
8599 IJKnGHF, wb, wv, wY, Z, wi,
8600 Oj, wM, OjwM, Oj, wM, wS,
8601 wB"))]
8602
8603 "! TARGET_POWERPC64
8604 && (gpc_reg_operand (operands[0], DImode)
8605 || gpc_reg_operand (operands[1], DImode))"
8606 "@
8607 #
8608 #
8609 #
8610 stfd%U0%X0 %1,%0
8611 lfd%U1%X1 %0,%1
8612 fmr %0,%1
8613 #
8614 stxsd %1,%0
8615 stxsdx %x1,%y0
8616 lxsd %0,%1
8617 lxsdx %x0,%y1
8618 xxlor %x0,%x1,%x1
8619 xxspltib %x0,0
8620 xxspltib %x0,255
8621 vspltisw %0,%1
8622 xxlxor %x0,%x0,%x0
8623 xxlorc %x0,%x0,%x0
8624 #
8625 #"
8626 [(set_attr "type"
8627 "store, load, *, fpstore, fpload, fpsimple,
8628 *, fpstore, fpstore, fpload, fpload, veclogical,
8629 vecsimple, vecsimple, vecsimple, veclogical, veclogical, vecsimple,
8630 vecsimple")
8631 (set_attr "size" "64")])
8632
8633 (define_split
8634 [(set (match_operand:DI 0 "gpc_reg_operand" "")
8635 (match_operand:DI 1 "const_int_operand" ""))]
8636 "! TARGET_POWERPC64 && reload_completed
8637 && gpr_or_gpr_p (operands[0], operands[1])
8638 && !direct_move_p (operands[0], operands[1])"
8639 [(set (match_dup 2) (match_dup 4))
8640 (set (match_dup 3) (match_dup 1))]
8641 "
8642 {
8643 HOST_WIDE_INT value = INTVAL (operands[1]);
8644 operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
8645 DImode);
8646 operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
8647 DImode);
8648 operands[4] = GEN_INT (value >> 32);
8649 operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
8650 }")
8651
8652 (define_split
8653 [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "")
8654 (match_operand:DIFD 1 "input_operand" ""))]
8655 "reload_completed && !TARGET_POWERPC64
8656 && gpr_or_gpr_p (operands[0], operands[1])
8657 && !direct_move_p (operands[0], operands[1])"
8658 [(pc)]
8659 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
8660
8661 ;; GPR store GPR load GPR move GPR li GPR lis GPR #
8662 ;; FPR store FPR load FPR move AVX store AVX store AVX load
8663 ;; AVX load VSX move P9 0 P9 -1 AVX 0/-1 VSX 0
8664 ;; VSX -1 P9 const AVX const From SPR To SPR SPR<->SPR
8665 ;; FPR->GPR GPR->FPR VSX->GPR GPR->VSX
8666 (define_insn "*movdi_internal64"
8667 [(set (match_operand:DI 0 "nonimmediate_operand"
8668 "=Y, r, r, r, r, r,
8669 ^m, ^d, ^d, ^wY, $Z, $wb,
8670 $wv, ^wi, *wo, *wo, *wv, *wi,
8671 *wi, *wv, *wv, r, *h, *h,
8672 ?*r, ?*wg, ?*r, ?*wj")
8673
8674 (match_operand:DI 1 "input_operand"
8675 "r, Y, r, I, L, nF,
8676 d, m, d, wb, wv, wY,
8677 Z, wi, Oj, wM, OjwM, Oj,
8678 wM, wS, wB, *h, r, 0,
8679 wg, r, wj, r"))]
8680
8681 "TARGET_POWERPC64
8682 && (gpc_reg_operand (operands[0], DImode)
8683 || gpc_reg_operand (operands[1], DImode))"
8684 "@
8685 std%U0%X0 %1,%0
8686 ld%U1%X1 %0,%1
8687 mr %0,%1
8688 li %0,%1
8689 lis %0,%v1
8690 #
8691 stfd%U0%X0 %1,%0
8692 lfd%U1%X1 %0,%1
8693 fmr %0,%1
8694 stxsd %1,%0
8695 stxsdx %x1,%y0
8696 lxsd %0,%1
8697 lxsdx %x0,%y1
8698 xxlor %x0,%x1,%x1
8699 xxspltib %x0,0
8700 xxspltib %x0,255
8701 #
8702 xxlxor %x0,%x0,%x0
8703 xxlorc %x0,%x0,%x0
8704 #
8705 #
8706 mf%1 %0
8707 mt%0 %1
8708 nop
8709 mftgpr %0,%1
8710 mffgpr %0,%1
8711 mfvsrd %0,%x1
8712 mtvsrd %x0,%1"
8713 [(set_attr "type"
8714 "store, load, *, *, *, *,
8715 fpstore, fpload, fpsimple, fpstore, fpstore, fpload,
8716 fpload, veclogical, vecsimple, vecsimple, vecsimple, veclogical,
8717 veclogical, vecsimple, vecsimple, mfjmpr, mtjmpr, *,
8718 mftgpr, mffgpr, mftgpr, mffgpr")
8719
8720 (set_attr "size" "64")
8721 (set_attr "length"
8722 "4, 4, 4, 4, 4, 20,
8723 4, 4, 4, 4, 4, 4,
8724 4, 4, 4, 4, 4, 8,
8725 8, 4, 4, 4, 4, 4,
8726 4, 4, 4, 4")])
8727
8728 ; Some DImode loads are best done as a load of -1 followed by a mask
8729 ; instruction.
8730 (define_split
8731 [(set (match_operand:DI 0 "int_reg_operand_not_pseudo")
8732 (match_operand:DI 1 "const_int_operand"))]
8733 "TARGET_POWERPC64
8734 && num_insns_constant (operands[1], DImode) > 1
8735 && !IN_RANGE (INTVAL (operands[1]), -0x80000000, 0xffffffff)
8736 && rs6000_is_valid_and_mask (operands[1], DImode)"
8737 [(set (match_dup 0)
8738 (const_int -1))
8739 (set (match_dup 0)
8740 (and:DI (match_dup 0)
8741 (match_dup 1)))]
8742 "")
8743
8744 ;; Split a load of a large constant into the appropriate five-instruction
8745 ;; sequence. Handle anything in a constant number of insns.
8746 ;; When non-easy constants can go in the TOC, this should use
8747 ;; easy_fp_constant predicate.
8748 (define_split
8749 [(set (match_operand:DI 0 "int_reg_operand_not_pseudo" "")
8750 (match_operand:DI 1 "const_int_operand" ""))]
8751 "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
8752 [(set (match_dup 0) (match_dup 2))
8753 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
8754 "
8755 {
8756 if (rs6000_emit_set_const (operands[0], operands[1]))
8757 DONE;
8758 else
8759 FAIL;
8760 }")
8761
8762 (define_split
8763 [(set (match_operand:DI 0 "int_reg_operand_not_pseudo" "")
8764 (match_operand:DI 1 "const_scalar_int_operand" ""))]
8765 "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
8766 [(set (match_dup 0) (match_dup 2))
8767 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
8768 "
8769 {
8770 if (rs6000_emit_set_const (operands[0], operands[1]))
8771 DONE;
8772 else
8773 FAIL;
8774 }")
8775
8776 (define_split
8777 [(set (match_operand:DI 0 "altivec_register_operand" "")
8778 (match_operand:DI 1 "s5bit_cint_operand" ""))]
8779 "TARGET_UPPER_REGS_DI && TARGET_VSX && reload_completed"
8780 [(const_int 0)]
8781 {
8782 rtx op0 = operands[0];
8783 rtx op1 = operands[1];
8784 int r = REGNO (op0);
8785 rtx op0_v4si = gen_rtx_REG (V4SImode, r);
8786
8787 emit_insn (gen_altivec_vspltisw (op0_v4si, op1));
8788 if (op1 != const0_rtx && op1 != constm1_rtx)
8789 {
8790 rtx op0_v2di = gen_rtx_REG (V2DImode, r);
8791 emit_insn (gen_altivec_vupkhsw (op0_v2di, op0_v4si));
8792 }
8793 DONE;
8794 })
8795
8796 ;; Split integer constants that can be loaded with XXSPLTIB and a
8797 ;; sign extend operation.
8798 (define_split
8799 [(set (match_operand:INT_ISA3 0 "altivec_register_operand" "")
8800 (match_operand:INT_ISA3 1 "xxspltib_constant_split" ""))]
8801 "TARGET_UPPER_REGS_DI && TARGET_P9_VECTOR && reload_completed"
8802 [(const_int 0)]
8803 {
8804 rtx op0 = operands[0];
8805 rtx op1 = operands[1];
8806 int r = REGNO (op0);
8807 rtx op0_v16qi = gen_rtx_REG (V16QImode, r);
8808
8809 emit_insn (gen_xxspltib_v16qi (op0_v16qi, op1));
8810 if (<MODE>mode == DImode)
8811 emit_insn (gen_vsx_sign_extend_qi_di (operands[0], op0_v16qi));
8812 else if (<MODE>mode == SImode)
8813 emit_insn (gen_vsx_sign_extend_qi_si (operands[0], op0_v16qi));
8814 else if (<MODE>mode == HImode)
8815 {
8816 rtx op0_v8hi = gen_rtx_REG (V8HImode, r);
8817 emit_insn (gen_altivec_vupkhsb (op0_v8hi, op0_v16qi));
8818 }
8819 DONE;
8820 })
8821
8822 \f
8823 ;; TImode/PTImode is similar, except that we usually want to compute the
8824 ;; address into a register and use lsi/stsi (the exception is during reload).
8825
8826 (define_insn "*mov<mode>_string"
8827 [(set (match_operand:TI2 0 "reg_or_mem_operand" "=Q,Y,????r,????r,????r,r")
8828 (match_operand:TI2 1 "input_operand" "r,r,Q,Y,r,n"))]
8829 "! TARGET_POWERPC64
8830 && (<MODE>mode != TImode || VECTOR_MEM_NONE_P (TImode))
8831 && (gpc_reg_operand (operands[0], <MODE>mode)
8832 || gpc_reg_operand (operands[1], <MODE>mode))"
8833 "*
8834 {
8835 switch (which_alternative)
8836 {
8837 default:
8838 gcc_unreachable ();
8839 case 0:
8840 if (TARGET_STRING)
8841 return \"stswi %1,%P0,16\";
8842 /* FALLTHRU */
8843 case 1:
8844 return \"#\";
8845 case 2:
8846 /* If the address is not used in the output, we can use lsi. Otherwise,
8847 fall through to generating four loads. */
8848 if (TARGET_STRING
8849 && ! reg_overlap_mentioned_p (operands[0], operands[1]))
8850 return \"lswi %0,%P1,16\";
8851 /* fall through */
8852 case 3:
8853 case 4:
8854 case 5:
8855 return \"#\";
8856 }
8857 }"
8858 [(set_attr "type" "store,store,load,load,*,*")
8859 (set_attr "update" "yes")
8860 (set_attr "indexed" "yes")
8861 (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
8862 (const_string "always")
8863 (const_string "conditional")))])
8864
8865 (define_insn "*mov<mode>_ppc64"
8866 [(set (match_operand:TI2 0 "nonimmediate_operand" "=wQ,Y,r,r,r,r")
8867 (match_operand:TI2 1 "input_operand" "r,r,wQ,Y,r,n"))]
8868 "(TARGET_POWERPC64 && VECTOR_MEM_NONE_P (<MODE>mode)
8869 && (gpc_reg_operand (operands[0], <MODE>mode)
8870 || gpc_reg_operand (operands[1], <MODE>mode)))"
8871 {
8872 return rs6000_output_move_128bit (operands);
8873 }
8874 [(set_attr "type" "store,store,load,load,*,*")
8875 (set_attr "length" "8")])
8876
8877 (define_split
8878 [(set (match_operand:TI2 0 "int_reg_operand" "")
8879 (match_operand:TI2 1 "const_scalar_int_operand" ""))]
8880 "TARGET_POWERPC64
8881 && (VECTOR_MEM_NONE_P (<MODE>mode)
8882 || (reload_completed && INT_REGNO_P (REGNO (operands[0]))))"
8883 [(set (match_dup 2) (match_dup 4))
8884 (set (match_dup 3) (match_dup 5))]
8885 "
8886 {
8887 operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
8888 <MODE>mode);
8889 operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
8890 <MODE>mode);
8891 if (CONST_WIDE_INT_P (operands[1]))
8892 {
8893 operands[4] = GEN_INT (CONST_WIDE_INT_ELT (operands[1], 1));
8894 operands[5] = GEN_INT (CONST_WIDE_INT_ELT (operands[1], 0));
8895 }
8896 else if (CONST_INT_P (operands[1]))
8897 {
8898 operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
8899 operands[5] = operands[1];
8900 }
8901 else
8902 FAIL;
8903 }")
8904
8905 (define_split
8906 [(set (match_operand:TI2 0 "nonimmediate_operand" "")
8907 (match_operand:TI2 1 "input_operand" ""))]
8908 "reload_completed
8909 && gpr_or_gpr_p (operands[0], operands[1])
8910 && !direct_move_p (operands[0], operands[1])
8911 && !quad_load_store_p (operands[0], operands[1])"
8912 [(pc)]
8913 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
8914 \f
8915 (define_expand "load_multiple"
8916 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
8917 (match_operand:SI 1 "" ""))
8918 (use (match_operand:SI 2 "" ""))])]
8919 "TARGET_STRING && !TARGET_POWERPC64"
8920 "
8921 {
8922 int regno;
8923 int count;
8924 rtx op1;
8925 int i;
8926
8927 /* Support only loading a constant number of fixed-point registers from
8928 memory and only bother with this if more than two; the machine
8929 doesn't support more than eight. */
8930 if (GET_CODE (operands[2]) != CONST_INT
8931 || INTVAL (operands[2]) <= 2
8932 || INTVAL (operands[2]) > 8
8933 || GET_CODE (operands[1]) != MEM
8934 || GET_CODE (operands[0]) != REG
8935 || REGNO (operands[0]) >= 32)
8936 FAIL;
8937
8938 count = INTVAL (operands[2]);
8939 regno = REGNO (operands[0]);
8940
8941 operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
8942 op1 = replace_equiv_address (operands[1],
8943 force_reg (SImode, XEXP (operands[1], 0)));
8944
8945 for (i = 0; i < count; i++)
8946 XVECEXP (operands[3], 0, i)
8947 = gen_rtx_SET (gen_rtx_REG (SImode, regno + i),
8948 adjust_address_nv (op1, SImode, i * 4));
8949 }")
8950
8951 (define_insn "*ldmsi8"
8952 [(match_parallel 0 "load_multiple_operation"
8953 [(set (match_operand:SI 2 "gpc_reg_operand" "")
8954 (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
8955 (set (match_operand:SI 3 "gpc_reg_operand" "")
8956 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
8957 (set (match_operand:SI 4 "gpc_reg_operand" "")
8958 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
8959 (set (match_operand:SI 5 "gpc_reg_operand" "")
8960 (mem:SI (plus:SI (match_dup 1) (const_int 12))))
8961 (set (match_operand:SI 6 "gpc_reg_operand" "")
8962 (mem:SI (plus:SI (match_dup 1) (const_int 16))))
8963 (set (match_operand:SI 7 "gpc_reg_operand" "")
8964 (mem:SI (plus:SI (match_dup 1) (const_int 20))))
8965 (set (match_operand:SI 8 "gpc_reg_operand" "")
8966 (mem:SI (plus:SI (match_dup 1) (const_int 24))))
8967 (set (match_operand:SI 9 "gpc_reg_operand" "")
8968 (mem:SI (plus:SI (match_dup 1) (const_int 28))))])]
8969 "TARGET_STRING && XVECLEN (operands[0], 0) == 8"
8970 "*
8971 { return rs6000_output_load_multiple (operands); }"
8972 [(set_attr "type" "load")
8973 (set_attr "update" "yes")
8974 (set_attr "indexed" "yes")
8975 (set_attr "length" "32")])
8976
8977 (define_insn "*ldmsi7"
8978 [(match_parallel 0 "load_multiple_operation"
8979 [(set (match_operand:SI 2 "gpc_reg_operand" "")
8980 (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
8981 (set (match_operand:SI 3 "gpc_reg_operand" "")
8982 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
8983 (set (match_operand:SI 4 "gpc_reg_operand" "")
8984 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
8985 (set (match_operand:SI 5 "gpc_reg_operand" "")
8986 (mem:SI (plus:SI (match_dup 1) (const_int 12))))
8987 (set (match_operand:SI 6 "gpc_reg_operand" "")
8988 (mem:SI (plus:SI (match_dup 1) (const_int 16))))
8989 (set (match_operand:SI 7 "gpc_reg_operand" "")
8990 (mem:SI (plus:SI (match_dup 1) (const_int 20))))
8991 (set (match_operand:SI 8 "gpc_reg_operand" "")
8992 (mem:SI (plus:SI (match_dup 1) (const_int 24))))])]
8993 "TARGET_STRING && XVECLEN (operands[0], 0) == 7"
8994 "*
8995 { return rs6000_output_load_multiple (operands); }"
8996 [(set_attr "type" "load")
8997 (set_attr "update" "yes")
8998 (set_attr "indexed" "yes")
8999 (set_attr "length" "32")])
9000
9001 (define_insn "*ldmsi6"
9002 [(match_parallel 0 "load_multiple_operation"
9003 [(set (match_operand:SI 2 "gpc_reg_operand" "")
9004 (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
9005 (set (match_operand:SI 3 "gpc_reg_operand" "")
9006 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
9007 (set (match_operand:SI 4 "gpc_reg_operand" "")
9008 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
9009 (set (match_operand:SI 5 "gpc_reg_operand" "")
9010 (mem:SI (plus:SI (match_dup 1) (const_int 12))))
9011 (set (match_operand:SI 6 "gpc_reg_operand" "")
9012 (mem:SI (plus:SI (match_dup 1) (const_int 16))))
9013 (set (match_operand:SI 7 "gpc_reg_operand" "")
9014 (mem:SI (plus:SI (match_dup 1) (const_int 20))))])]
9015 "TARGET_STRING && XVECLEN (operands[0], 0) == 6"
9016 "*
9017 { return rs6000_output_load_multiple (operands); }"
9018 [(set_attr "type" "load")
9019 (set_attr "update" "yes")
9020 (set_attr "indexed" "yes")
9021 (set_attr "length" "32")])
9022
9023 (define_insn "*ldmsi5"
9024 [(match_parallel 0 "load_multiple_operation"
9025 [(set (match_operand:SI 2 "gpc_reg_operand" "")
9026 (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
9027 (set (match_operand:SI 3 "gpc_reg_operand" "")
9028 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
9029 (set (match_operand:SI 4 "gpc_reg_operand" "")
9030 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
9031 (set (match_operand:SI 5 "gpc_reg_operand" "")
9032 (mem:SI (plus:SI (match_dup 1) (const_int 12))))
9033 (set (match_operand:SI 6 "gpc_reg_operand" "")
9034 (mem:SI (plus:SI (match_dup 1) (const_int 16))))])]
9035 "TARGET_STRING && XVECLEN (operands[0], 0) == 5"
9036 "*
9037 { return rs6000_output_load_multiple (operands); }"
9038 [(set_attr "type" "load")
9039 (set_attr "update" "yes")
9040 (set_attr "indexed" "yes")
9041 (set_attr "length" "32")])
9042
9043 (define_insn "*ldmsi4"
9044 [(match_parallel 0 "load_multiple_operation"
9045 [(set (match_operand:SI 2 "gpc_reg_operand" "")
9046 (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
9047 (set (match_operand:SI 3 "gpc_reg_operand" "")
9048 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
9049 (set (match_operand:SI 4 "gpc_reg_operand" "")
9050 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
9051 (set (match_operand:SI 5 "gpc_reg_operand" "")
9052 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
9053 "TARGET_STRING && XVECLEN (operands[0], 0) == 4"
9054 "*
9055 { return rs6000_output_load_multiple (operands); }"
9056 [(set_attr "type" "load")
9057 (set_attr "update" "yes")
9058 (set_attr "indexed" "yes")
9059 (set_attr "length" "32")])
9060
9061 (define_insn "*ldmsi3"
9062 [(match_parallel 0 "load_multiple_operation"
9063 [(set (match_operand:SI 2 "gpc_reg_operand" "")
9064 (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
9065 (set (match_operand:SI 3 "gpc_reg_operand" "")
9066 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
9067 (set (match_operand:SI 4 "gpc_reg_operand" "")
9068 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
9069 "TARGET_STRING && XVECLEN (operands[0], 0) == 3"
9070 "*
9071 { return rs6000_output_load_multiple (operands); }"
9072 [(set_attr "type" "load")
9073 (set_attr "update" "yes")
9074 (set_attr "indexed" "yes")
9075 (set_attr "length" "32")])
9076
9077 (define_expand "store_multiple"
9078 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
9079 (match_operand:SI 1 "" ""))
9080 (clobber (scratch:SI))
9081 (use (match_operand:SI 2 "" ""))])]
9082 "TARGET_STRING && !TARGET_POWERPC64"
9083 "
9084 {
9085 int regno;
9086 int count;
9087 rtx to;
9088 rtx op0;
9089 int i;
9090
9091 /* Support only storing a constant number of fixed-point registers to
9092 memory and only bother with this if more than two; the machine
9093 doesn't support more than eight. */
9094 if (GET_CODE (operands[2]) != CONST_INT
9095 || INTVAL (operands[2]) <= 2
9096 || INTVAL (operands[2]) > 8
9097 || GET_CODE (operands[0]) != MEM
9098 || GET_CODE (operands[1]) != REG
9099 || REGNO (operands[1]) >= 32)
9100 FAIL;
9101
9102 count = INTVAL (operands[2]);
9103 regno = REGNO (operands[1]);
9104
9105 operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
9106 to = force_reg (SImode, XEXP (operands[0], 0));
9107 op0 = replace_equiv_address (operands[0], to);
9108
9109 XVECEXP (operands[3], 0, 0)
9110 = gen_rtx_SET (adjust_address_nv (op0, SImode, 0), operands[1]);
9111 XVECEXP (operands[3], 0, 1) = gen_rtx_CLOBBER (VOIDmode,
9112 gen_rtx_SCRATCH (SImode));
9113
9114 for (i = 1; i < count; i++)
9115 XVECEXP (operands[3], 0, i + 1)
9116 = gen_rtx_SET (adjust_address_nv (op0, SImode, i * 4),
9117 gen_rtx_REG (SImode, regno + i));
9118 }")
9119
9120 (define_insn "*stmsi8"
9121 [(match_parallel 0 "store_multiple_operation"
9122 [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
9123 (match_operand:SI 2 "gpc_reg_operand" "r"))
9124 (clobber (match_scratch:SI 3 "=X"))
9125 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
9126 (match_operand:SI 4 "gpc_reg_operand" "r"))
9127 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
9128 (match_operand:SI 5 "gpc_reg_operand" "r"))
9129 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
9130 (match_operand:SI 6 "gpc_reg_operand" "r"))
9131 (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
9132 (match_operand:SI 7 "gpc_reg_operand" "r"))
9133 (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
9134 (match_operand:SI 8 "gpc_reg_operand" "r"))
9135 (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
9136 (match_operand:SI 9 "gpc_reg_operand" "r"))
9137 (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
9138 (match_operand:SI 10 "gpc_reg_operand" "r"))])]
9139 "TARGET_STRING && XVECLEN (operands[0], 0) == 9"
9140 "stswi %2,%1,%O0"
9141 [(set_attr "type" "store")
9142 (set_attr "update" "yes")
9143 (set_attr "indexed" "yes")
9144 (set_attr "cell_micro" "always")])
9145
9146 (define_insn "*stmsi7"
9147 [(match_parallel 0 "store_multiple_operation"
9148 [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
9149 (match_operand:SI 2 "gpc_reg_operand" "r"))
9150 (clobber (match_scratch:SI 3 "=X"))
9151 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
9152 (match_operand:SI 4 "gpc_reg_operand" "r"))
9153 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
9154 (match_operand:SI 5 "gpc_reg_operand" "r"))
9155 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
9156 (match_operand:SI 6 "gpc_reg_operand" "r"))
9157 (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
9158 (match_operand:SI 7 "gpc_reg_operand" "r"))
9159 (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
9160 (match_operand:SI 8 "gpc_reg_operand" "r"))
9161 (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
9162 (match_operand:SI 9 "gpc_reg_operand" "r"))])]
9163 "TARGET_STRING && XVECLEN (operands[0], 0) == 8"
9164 "stswi %2,%1,%O0"
9165 [(set_attr "type" "store")
9166 (set_attr "update" "yes")
9167 (set_attr "indexed" "yes")
9168 (set_attr "cell_micro" "always")])
9169
9170 (define_insn "*stmsi6"
9171 [(match_parallel 0 "store_multiple_operation"
9172 [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
9173 (match_operand:SI 2 "gpc_reg_operand" "r"))
9174 (clobber (match_scratch:SI 3 "=X"))
9175 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
9176 (match_operand:SI 4 "gpc_reg_operand" "r"))
9177 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
9178 (match_operand:SI 5 "gpc_reg_operand" "r"))
9179 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
9180 (match_operand:SI 6 "gpc_reg_operand" "r"))
9181 (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
9182 (match_operand:SI 7 "gpc_reg_operand" "r"))
9183 (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
9184 (match_operand:SI 8 "gpc_reg_operand" "r"))])]
9185 "TARGET_STRING && XVECLEN (operands[0], 0) == 7"
9186 "stswi %2,%1,%O0"
9187 [(set_attr "type" "store")
9188 (set_attr "update" "yes")
9189 (set_attr "indexed" "yes")
9190 (set_attr "cell_micro" "always")])
9191
9192 (define_insn "*stmsi5"
9193 [(match_parallel 0 "store_multiple_operation"
9194 [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
9195 (match_operand:SI 2 "gpc_reg_operand" "r"))
9196 (clobber (match_scratch:SI 3 "=X"))
9197 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
9198 (match_operand:SI 4 "gpc_reg_operand" "r"))
9199 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
9200 (match_operand:SI 5 "gpc_reg_operand" "r"))
9201 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
9202 (match_operand:SI 6 "gpc_reg_operand" "r"))
9203 (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
9204 (match_operand:SI 7 "gpc_reg_operand" "r"))])]
9205 "TARGET_STRING && XVECLEN (operands[0], 0) == 6"
9206 "stswi %2,%1,%O0"
9207 [(set_attr "type" "store")
9208 (set_attr "update" "yes")
9209 (set_attr "indexed" "yes")
9210 (set_attr "cell_micro" "always")])
9211
9212 (define_insn "*stmsi4"
9213 [(match_parallel 0 "store_multiple_operation"
9214 [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
9215 (match_operand:SI 2 "gpc_reg_operand" "r"))
9216 (clobber (match_scratch:SI 3 "=X"))
9217 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
9218 (match_operand:SI 4 "gpc_reg_operand" "r"))
9219 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
9220 (match_operand:SI 5 "gpc_reg_operand" "r"))
9221 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
9222 (match_operand:SI 6 "gpc_reg_operand" "r"))])]
9223 "TARGET_STRING && XVECLEN (operands[0], 0) == 5"
9224 "stswi %2,%1,%O0"
9225 [(set_attr "type" "store")
9226 (set_attr "update" "yes")
9227 (set_attr "indexed" "yes")
9228 (set_attr "cell_micro" "always")])
9229
9230 (define_insn "*stmsi3"
9231 [(match_parallel 0 "store_multiple_operation"
9232 [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
9233 (match_operand:SI 2 "gpc_reg_operand" "r"))
9234 (clobber (match_scratch:SI 3 "=X"))
9235 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
9236 (match_operand:SI 4 "gpc_reg_operand" "r"))
9237 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
9238 (match_operand:SI 5 "gpc_reg_operand" "r"))])]
9239 "TARGET_STRING && XVECLEN (operands[0], 0) == 4"
9240 "stswi %2,%1,%O0"
9241 [(set_attr "type" "store")
9242 (set_attr "update" "yes")
9243 (set_attr "indexed" "yes")
9244 (set_attr "cell_micro" "always")])
9245 \f
9246 (define_expand "setmemsi"
9247 [(parallel [(set (match_operand:BLK 0 "" "")
9248 (match_operand 2 "const_int_operand" ""))
9249 (use (match_operand:SI 1 "" ""))
9250 (use (match_operand:SI 3 "" ""))])]
9251 ""
9252 "
9253 {
9254 /* If value to set is not zero, use the library routine. */
9255 if (operands[2] != const0_rtx)
9256 FAIL;
9257
9258 if (expand_block_clear (operands))
9259 DONE;
9260 else
9261 FAIL;
9262 }")
9263
9264 ;; String compare N insn.
9265 ;; Argument 0 is the target (result)
9266 ;; Argument 1 is the destination
9267 ;; Argument 2 is the source
9268 ;; Argument 3 is the length
9269 ;; Argument 4 is the alignment
9270
9271 (define_expand "cmpstrnsi"
9272 [(parallel [(set (match_operand:SI 0)
9273 (compare:SI (match_operand:BLK 1)
9274 (match_operand:BLK 2)))
9275 (use (match_operand:SI 3))
9276 (use (match_operand:SI 4))])]
9277 "TARGET_CMPB && (BYTES_BIG_ENDIAN || TARGET_LDBRX)"
9278 {
9279 if (optimize_insn_for_size_p ())
9280 FAIL;
9281
9282 if (expand_strn_compare (operands, 0))
9283 DONE;
9284 else
9285 FAIL;
9286 })
9287
9288 ;; String compare insn.
9289 ;; Argument 0 is the target (result)
9290 ;; Argument 1 is the destination
9291 ;; Argument 2 is the source
9292 ;; Argument 3 is the alignment
9293
9294 (define_expand "cmpstrsi"
9295 [(parallel [(set (match_operand:SI 0)
9296 (compare:SI (match_operand:BLK 1)
9297 (match_operand:BLK 2)))
9298 (use (match_operand:SI 3))])]
9299 "TARGET_CMPB && (BYTES_BIG_ENDIAN || TARGET_LDBRX)"
9300 {
9301 if (optimize_insn_for_size_p ())
9302 FAIL;
9303
9304 if (expand_strn_compare (operands, 1))
9305 DONE;
9306 else
9307 FAIL;
9308 })
9309
9310 ;; Block compare insn.
9311 ;; Argument 0 is the target (result)
9312 ;; Argument 1 is the destination
9313 ;; Argument 2 is the source
9314 ;; Argument 3 is the length
9315 ;; Argument 4 is the alignment
9316
9317 (define_expand "cmpmemsi"
9318 [(parallel [(set (match_operand:SI 0)
9319 (compare:SI (match_operand:BLK 1)
9320 (match_operand:BLK 2)))
9321 (use (match_operand:SI 3))
9322 (use (match_operand:SI 4))])]
9323 "TARGET_POPCNTD"
9324 {
9325 if (expand_block_compare (operands))
9326 DONE;
9327 else
9328 FAIL;
9329 })
9330
9331 ;; String/block move insn.
9332 ;; Argument 0 is the destination
9333 ;; Argument 1 is the source
9334 ;; Argument 2 is the length
9335 ;; Argument 3 is the alignment
9336
9337 (define_expand "movmemsi"
9338 [(parallel [(set (match_operand:BLK 0 "" "")
9339 (match_operand:BLK 1 "" ""))
9340 (use (match_operand:SI 2 "" ""))
9341 (use (match_operand:SI 3 "" ""))])]
9342 ""
9343 "
9344 {
9345 if (expand_block_move (operands))
9346 DONE;
9347 else
9348 FAIL;
9349 }")
9350
9351 ;; Move up to 32 bytes at a time. The fixed registers are needed because the
9352 ;; register allocator doesn't have a clue about allocating 8 word registers.
9353 ;; rD/rS = r5 is preferred, efficient form.
9354 (define_expand "movmemsi_8reg"
9355 [(parallel [(set (match_operand 0 "" "")
9356 (match_operand 1 "" ""))
9357 (use (match_operand 2 "" ""))
9358 (use (match_operand 3 "" ""))
9359 (clobber (reg:SI 5))
9360 (clobber (reg:SI 6))
9361 (clobber (reg:SI 7))
9362 (clobber (reg:SI 8))
9363 (clobber (reg:SI 9))
9364 (clobber (reg:SI 10))
9365 (clobber (reg:SI 11))
9366 (clobber (reg:SI 12))
9367 (clobber (match_scratch:SI 4 ""))])]
9368 "TARGET_STRING"
9369 "")
9370
9371 (define_insn ""
9372 [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
9373 (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
9374 (use (match_operand:SI 2 "immediate_operand" "i"))
9375 (use (match_operand:SI 3 "immediate_operand" "i"))
9376 (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r"))
9377 (clobber (reg:SI 6))
9378 (clobber (reg:SI 7))
9379 (clobber (reg:SI 8))
9380 (clobber (reg:SI 9))
9381 (clobber (reg:SI 10))
9382 (clobber (reg:SI 11))
9383 (clobber (reg:SI 12))
9384 (clobber (match_scratch:SI 5 "=X"))]
9385 "TARGET_STRING
9386 && ((INTVAL (operands[2]) > 24 && INTVAL (operands[2]) < 32)
9387 || INTVAL (operands[2]) == 0)
9388 && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 12)
9389 && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
9390 && REGNO (operands[4]) == 5"
9391 "lswi %4,%1,%2\;stswi %4,%0,%2"
9392 [(set_attr "type" "store")
9393 (set_attr "update" "yes")
9394 (set_attr "indexed" "yes")
9395 (set_attr "cell_micro" "always")
9396 (set_attr "length" "8")])
9397
9398 ;; Move up to 24 bytes at a time. The fixed registers are needed because the
9399 ;; register allocator doesn't have a clue about allocating 6 word registers.
9400 ;; rD/rS = r5 is preferred, efficient form.
9401 (define_expand "movmemsi_6reg"
9402 [(parallel [(set (match_operand 0 "" "")
9403 (match_operand 1 "" ""))
9404 (use (match_operand 2 "" ""))
9405 (use (match_operand 3 "" ""))
9406 (clobber (reg:SI 5))
9407 (clobber (reg:SI 6))
9408 (clobber (reg:SI 7))
9409 (clobber (reg:SI 8))
9410 (clobber (reg:SI 9))
9411 (clobber (reg:SI 10))
9412 (clobber (match_scratch:SI 4 ""))])]
9413 "TARGET_STRING"
9414 "")
9415
9416 (define_insn ""
9417 [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
9418 (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
9419 (use (match_operand:SI 2 "immediate_operand" "i"))
9420 (use (match_operand:SI 3 "immediate_operand" "i"))
9421 (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r"))
9422 (clobber (reg:SI 6))
9423 (clobber (reg:SI 7))
9424 (clobber (reg:SI 8))
9425 (clobber (reg:SI 9))
9426 (clobber (reg:SI 10))
9427 (clobber (match_scratch:SI 5 "=X"))]
9428 "TARGET_STRING
9429 && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 32
9430 && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 10)
9431 && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
9432 && REGNO (operands[4]) == 5"
9433 "lswi %4,%1,%2\;stswi %4,%0,%2"
9434 [(set_attr "type" "store")
9435 (set_attr "update" "yes")
9436 (set_attr "indexed" "yes")
9437 (set_attr "cell_micro" "always")
9438 (set_attr "length" "8")])
9439
9440 ;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill
9441 ;; problems with TImode.
9442 ;; rD/rS = r5 is preferred, efficient form.
9443 (define_expand "movmemsi_4reg"
9444 [(parallel [(set (match_operand 0 "" "")
9445 (match_operand 1 "" ""))
9446 (use (match_operand 2 "" ""))
9447 (use (match_operand 3 "" ""))
9448 (clobber (reg:SI 5))
9449 (clobber (reg:SI 6))
9450 (clobber (reg:SI 7))
9451 (clobber (reg:SI 8))
9452 (clobber (match_scratch:SI 4 ""))])]
9453 "TARGET_STRING"
9454 "")
9455
9456 (define_insn ""
9457 [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
9458 (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
9459 (use (match_operand:SI 2 "immediate_operand" "i"))
9460 (use (match_operand:SI 3 "immediate_operand" "i"))
9461 (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r"))
9462 (clobber (reg:SI 6))
9463 (clobber (reg:SI 7))
9464 (clobber (reg:SI 8))
9465 (clobber (match_scratch:SI 5 "=X"))]
9466 "TARGET_STRING
9467 && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16
9468 && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 8)
9469 && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
9470 && REGNO (operands[4]) == 5"
9471 "lswi %4,%1,%2\;stswi %4,%0,%2"
9472 [(set_attr "type" "store")
9473 (set_attr "update" "yes")
9474 (set_attr "indexed" "yes")
9475 (set_attr "cell_micro" "always")
9476 (set_attr "length" "8")])
9477
9478 ;; Move up to 8 bytes at a time.
9479 (define_expand "movmemsi_2reg"
9480 [(parallel [(set (match_operand 0 "" "")
9481 (match_operand 1 "" ""))
9482 (use (match_operand 2 "" ""))
9483 (use (match_operand 3 "" ""))
9484 (clobber (match_scratch:DI 4 ""))
9485 (clobber (match_scratch:SI 5 ""))])]
9486 "TARGET_STRING && ! TARGET_POWERPC64"
9487 "")
9488
9489 (define_insn ""
9490 [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
9491 (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
9492 (use (match_operand:SI 2 "immediate_operand" "i"))
9493 (use (match_operand:SI 3 "immediate_operand" "i"))
9494 (clobber (match_scratch:DI 4 "=&r"))
9495 (clobber (match_scratch:SI 5 "=X"))]
9496 "TARGET_STRING && ! TARGET_POWERPC64
9497 && INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
9498 "lswi %4,%1,%2\;stswi %4,%0,%2"
9499 [(set_attr "type" "store")
9500 (set_attr "update" "yes")
9501 (set_attr "indexed" "yes")
9502 (set_attr "cell_micro" "always")
9503 (set_attr "length" "8")])
9504
9505 ;; Move up to 4 bytes at a time.
9506 (define_expand "movmemsi_1reg"
9507 [(parallel [(set (match_operand 0 "" "")
9508 (match_operand 1 "" ""))
9509 (use (match_operand 2 "" ""))
9510 (use (match_operand 3 "" ""))
9511 (clobber (match_scratch:SI 4 ""))
9512 (clobber (match_scratch:SI 5 ""))])]
9513 "TARGET_STRING"
9514 "")
9515
9516 (define_insn ""
9517 [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
9518 (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
9519 (use (match_operand:SI 2 "immediate_operand" "i"))
9520 (use (match_operand:SI 3 "immediate_operand" "i"))
9521 (clobber (match_scratch:SI 4 "=&r"))
9522 (clobber (match_scratch:SI 5 "=X"))]
9523 "TARGET_STRING && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
9524 "lswi %4,%1,%2\;stswi %4,%0,%2"
9525 [(set_attr "type" "store")
9526 (set_attr "update" "yes")
9527 (set_attr "indexed" "yes")
9528 (set_attr "cell_micro" "always")
9529 (set_attr "length" "8")])
9530 \f
9531 ;; Define insns that do load or store with update. Some of these we can
9532 ;; get by using pre-decrement or pre-increment, but the hardware can also
9533 ;; do cases where the increment is not the size of the object.
9534 ;;
9535 ;; In all these cases, we use operands 0 and 1 for the register being
9536 ;; incremented because those are the operands that local-alloc will
9537 ;; tie and these are the pair most likely to be tieable (and the ones
9538 ;; that will benefit the most).
9539
9540 (define_insn "*movdi_update1"
9541 [(set (match_operand:DI 3 "gpc_reg_operand" "=r,r")
9542 (mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
9543 (match_operand:DI 2 "reg_or_aligned_short_operand" "r,I"))))
9544 (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
9545 (plus:DI (match_dup 1) (match_dup 2)))]
9546 "TARGET_POWERPC64 && TARGET_UPDATE
9547 && (!avoiding_indexed_address_p (DImode)
9548 || !gpc_reg_operand (operands[2], DImode))"
9549 "@
9550 ldux %3,%0,%2
9551 ldu %3,%2(%0)"
9552 [(set_attr "type" "load")
9553 (set_attr "update" "yes")
9554 (set_attr "indexed" "yes,no")])
9555
9556 (define_insn "movdi_<mode>_update"
9557 [(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
9558 (match_operand:P 2 "reg_or_aligned_short_operand" "r,I")))
9559 (match_operand:DI 3 "gpc_reg_operand" "r,r"))
9560 (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
9561 (plus:P (match_dup 1) (match_dup 2)))]
9562 "TARGET_POWERPC64 && TARGET_UPDATE
9563 && (!avoiding_indexed_address_p (Pmode)
9564 || !gpc_reg_operand (operands[2], Pmode)
9565 || (REG_P (operands[0])
9566 && REGNO (operands[0]) == STACK_POINTER_REGNUM))"
9567 "@
9568 stdux %3,%0,%2
9569 stdu %3,%2(%0)"
9570 [(set_attr "type" "store")
9571 (set_attr "update" "yes")
9572 (set_attr "indexed" "yes,no")])
9573
9574 ;; This pattern is only conditional on TARGET_POWERPC64, as it is
9575 ;; needed for stack allocation, even if the user passes -mno-update.
9576 (define_insn "movdi_<mode>_update_stack"
9577 [(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
9578 (match_operand:P 2 "reg_or_aligned_short_operand" "r,I")))
9579 (match_operand:DI 3 "gpc_reg_operand" "r,r"))
9580 (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
9581 (plus:P (match_dup 1) (match_dup 2)))]
9582 "TARGET_POWERPC64"
9583 "@
9584 stdux %3,%0,%2
9585 stdu %3,%2(%0)"
9586 [(set_attr "type" "store")
9587 (set_attr "update" "yes")
9588 (set_attr "indexed" "yes,no")])
9589
9590 (define_insn "*movsi_update1"
9591 [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
9592 (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9593 (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
9594 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9595 (plus:SI (match_dup 1) (match_dup 2)))]
9596 "TARGET_UPDATE
9597 && (!avoiding_indexed_address_p (SImode)
9598 || !gpc_reg_operand (operands[2], SImode))"
9599 "@
9600 lwzux %3,%0,%2
9601 lwzu %3,%2(%0)"
9602 [(set_attr "type" "load")
9603 (set_attr "update" "yes")
9604 (set_attr "indexed" "yes,no")])
9605
9606 (define_insn "*movsi_update2"
9607 [(set (match_operand:DI 3 "gpc_reg_operand" "=r")
9608 (sign_extend:DI
9609 (mem:SI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0")
9610 (match_operand:DI 2 "gpc_reg_operand" "r")))))
9611 (set (match_operand:DI 0 "gpc_reg_operand" "=b")
9612 (plus:DI (match_dup 1) (match_dup 2)))]
9613 "TARGET_POWERPC64 && rs6000_gen_cell_microcode
9614 && !avoiding_indexed_address_p (DImode)"
9615 "lwaux %3,%0,%2"
9616 [(set_attr "type" "load")
9617 (set_attr "sign_extend" "yes")
9618 (set_attr "update" "yes")
9619 (set_attr "indexed" "yes")])
9620
9621 (define_insn "movsi_update"
9622 [(set (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9623 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9624 (match_operand:SI 3 "gpc_reg_operand" "r,r"))
9625 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9626 (plus:SI (match_dup 1) (match_dup 2)))]
9627 "TARGET_UPDATE
9628 && (!avoiding_indexed_address_p (SImode)
9629 || !gpc_reg_operand (operands[2], SImode)
9630 || (REG_P (operands[0])
9631 && REGNO (operands[0]) == STACK_POINTER_REGNUM))"
9632 "@
9633 stwux %3,%0,%2
9634 stwu %3,%2(%0)"
9635 [(set_attr "type" "store")
9636 (set_attr "update" "yes")
9637 (set_attr "indexed" "yes,no")])
9638
9639 ;; This is an unconditional pattern; needed for stack allocation, even
9640 ;; if the user passes -mno-update.
9641 (define_insn "movsi_update_stack"
9642 [(set (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9643 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9644 (match_operand:SI 3 "gpc_reg_operand" "r,r"))
9645 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9646 (plus:SI (match_dup 1) (match_dup 2)))]
9647 ""
9648 "@
9649 stwux %3,%0,%2
9650 stwu %3,%2(%0)"
9651 [(set_attr "type" "store")
9652 (set_attr "update" "yes")
9653 (set_attr "indexed" "yes,no")])
9654
9655 (define_insn "*movhi_update1"
9656 [(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
9657 (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9658 (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
9659 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9660 (plus:SI (match_dup 1) (match_dup 2)))]
9661 "TARGET_UPDATE
9662 && (!avoiding_indexed_address_p (SImode)
9663 || !gpc_reg_operand (operands[2], SImode))"
9664 "@
9665 lhzux %3,%0,%2
9666 lhzu %3,%2(%0)"
9667 [(set_attr "type" "load")
9668 (set_attr "update" "yes")
9669 (set_attr "indexed" "yes,no")])
9670
9671 (define_insn "*movhi_update2"
9672 [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
9673 (zero_extend:SI
9674 (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9675 (match_operand:SI 2 "reg_or_short_operand" "r,I")))))
9676 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9677 (plus:SI (match_dup 1) (match_dup 2)))]
9678 "TARGET_UPDATE
9679 && (!avoiding_indexed_address_p (SImode)
9680 || !gpc_reg_operand (operands[2], SImode))"
9681 "@
9682 lhzux %3,%0,%2
9683 lhzu %3,%2(%0)"
9684 [(set_attr "type" "load")
9685 (set_attr "update" "yes")
9686 (set_attr "indexed" "yes,no")])
9687
9688 (define_insn "*movhi_update3"
9689 [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
9690 (sign_extend:SI
9691 (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9692 (match_operand:SI 2 "reg_or_short_operand" "r,I")))))
9693 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9694 (plus:SI (match_dup 1) (match_dup 2)))]
9695 "TARGET_UPDATE && rs6000_gen_cell_microcode
9696 && (!avoiding_indexed_address_p (SImode)
9697 || !gpc_reg_operand (operands[2], SImode))"
9698 "@
9699 lhaux %3,%0,%2
9700 lhau %3,%2(%0)"
9701 [(set_attr "type" "load")
9702 (set_attr "sign_extend" "yes")
9703 (set_attr "update" "yes")
9704 (set_attr "indexed" "yes,no")])
9705
9706 (define_insn "*movhi_update4"
9707 [(set (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9708 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9709 (match_operand:HI 3 "gpc_reg_operand" "r,r"))
9710 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9711 (plus:SI (match_dup 1) (match_dup 2)))]
9712 "TARGET_UPDATE
9713 && (!avoiding_indexed_address_p (SImode)
9714 || !gpc_reg_operand (operands[2], SImode))"
9715 "@
9716 sthux %3,%0,%2
9717 sthu %3,%2(%0)"
9718 [(set_attr "type" "store")
9719 (set_attr "update" "yes")
9720 (set_attr "indexed" "yes,no")])
9721
9722 (define_insn "*movqi_update1"
9723 [(set (match_operand:QI 3 "gpc_reg_operand" "=r,r")
9724 (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9725 (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
9726 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9727 (plus:SI (match_dup 1) (match_dup 2)))]
9728 "TARGET_UPDATE
9729 && (!avoiding_indexed_address_p (SImode)
9730 || !gpc_reg_operand (operands[2], SImode))"
9731 "@
9732 lbzux %3,%0,%2
9733 lbzu %3,%2(%0)"
9734 [(set_attr "type" "load")
9735 (set_attr "update" "yes")
9736 (set_attr "indexed" "yes,no")])
9737
9738 (define_insn "*movqi_update2"
9739 [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
9740 (zero_extend:SI
9741 (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9742 (match_operand:SI 2 "reg_or_short_operand" "r,I")))))
9743 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9744 (plus:SI (match_dup 1) (match_dup 2)))]
9745 "TARGET_UPDATE
9746 && (!avoiding_indexed_address_p (SImode)
9747 || !gpc_reg_operand (operands[2], SImode))"
9748 "@
9749 lbzux %3,%0,%2
9750 lbzu %3,%2(%0)"
9751 [(set_attr "type" "load")
9752 (set_attr "update" "yes")
9753 (set_attr "indexed" "yes,no")])
9754
9755 (define_insn "*movqi_update3"
9756 [(set (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9757 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9758 (match_operand:QI 3 "gpc_reg_operand" "r,r"))
9759 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9760 (plus:SI (match_dup 1) (match_dup 2)))]
9761 "TARGET_UPDATE
9762 && (!avoiding_indexed_address_p (SImode)
9763 || !gpc_reg_operand (operands[2], SImode))"
9764 "@
9765 stbux %3,%0,%2
9766 stbu %3,%2(%0)"
9767 [(set_attr "type" "store")
9768 (set_attr "update" "yes")
9769 (set_attr "indexed" "yes,no")])
9770
9771 (define_insn "*movsf_update1"
9772 [(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
9773 (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9774 (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
9775 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9776 (plus:SI (match_dup 1) (match_dup 2)))]
9777 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_UPDATE
9778 && (!avoiding_indexed_address_p (SImode)
9779 || !gpc_reg_operand (operands[2], SImode))"
9780 "@
9781 lfsux %3,%0,%2
9782 lfsu %3,%2(%0)"
9783 [(set_attr "type" "fpload")
9784 (set_attr "update" "yes")
9785 (set_attr "indexed" "yes,no")])
9786
9787 (define_insn "*movsf_update2"
9788 [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9789 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9790 (match_operand:SF 3 "gpc_reg_operand" "f,f"))
9791 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9792 (plus:SI (match_dup 1) (match_dup 2)))]
9793 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_UPDATE
9794 && (!avoiding_indexed_address_p (SImode)
9795 || !gpc_reg_operand (operands[2], SImode))"
9796 "@
9797 stfsux %3,%0,%2
9798 stfsu %3,%2(%0)"
9799 [(set_attr "type" "fpstore")
9800 (set_attr "update" "yes")
9801 (set_attr "indexed" "yes,no")])
9802
9803 (define_insn "*movsf_update3"
9804 [(set (match_operand:SF 3 "gpc_reg_operand" "=r,r")
9805 (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9806 (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
9807 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9808 (plus:SI (match_dup 1) (match_dup 2)))]
9809 "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE
9810 && (!avoiding_indexed_address_p (SImode)
9811 || !gpc_reg_operand (operands[2], SImode))"
9812 "@
9813 lwzux %3,%0,%2
9814 lwzu %3,%2(%0)"
9815 [(set_attr "type" "load")
9816 (set_attr "update" "yes")
9817 (set_attr "indexed" "yes,no")])
9818
9819 (define_insn "*movsf_update4"
9820 [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9821 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9822 (match_operand:SF 3 "gpc_reg_operand" "r,r"))
9823 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9824 (plus:SI (match_dup 1) (match_dup 2)))]
9825 "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE
9826 && (!avoiding_indexed_address_p (SImode)
9827 || !gpc_reg_operand (operands[2], SImode))"
9828 "@
9829 stwux %3,%0,%2
9830 stwu %3,%2(%0)"
9831 [(set_attr "type" "store")
9832 (set_attr "update" "yes")
9833 (set_attr "indexed" "yes,no")])
9834
9835 (define_insn "*movdf_update1"
9836 [(set (match_operand:DF 3 "gpc_reg_operand" "=d,d")
9837 (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9838 (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
9839 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9840 (plus:SI (match_dup 1) (match_dup 2)))]
9841 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE
9842 && (!avoiding_indexed_address_p (SImode)
9843 || !gpc_reg_operand (operands[2], SImode))"
9844 "@
9845 lfdux %3,%0,%2
9846 lfdu %3,%2(%0)"
9847 [(set_attr "type" "fpload")
9848 (set_attr "update" "yes")
9849 (set_attr "indexed" "yes,no")
9850 (set_attr "size" "64")])
9851
9852 (define_insn "*movdf_update2"
9853 [(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
9854 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
9855 (match_operand:DF 3 "gpc_reg_operand" "d,d"))
9856 (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
9857 (plus:SI (match_dup 1) (match_dup 2)))]
9858 "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE
9859 && (!avoiding_indexed_address_p (SImode)
9860 || !gpc_reg_operand (operands[2], SImode))"
9861 "@
9862 stfdux %3,%0,%2
9863 stfdu %3,%2(%0)"
9864 [(set_attr "type" "fpstore")
9865 (set_attr "update" "yes")
9866 (set_attr "indexed" "yes,no")])
9867
9868
9869 ;; After inserting conditional returns we can sometimes have
9870 ;; unnecessary register moves. Unfortunately we cannot have a
9871 ;; modeless peephole here, because some single SImode sets have early
9872 ;; clobber outputs. Although those sets expand to multi-ppc-insn
9873 ;; sequences, using get_attr_length here will smash the operands
9874 ;; array. Neither is there an early_cobbler_p predicate.
9875 ;; Disallow subregs for E500 so we don't munge frob_di_df_2.
9876 ;; Also this optimization interferes with scalars going into
9877 ;; altivec registers (the code does reloading through the FPRs).
9878 (define_peephole2
9879 [(set (match_operand:DF 0 "gpc_reg_operand" "")
9880 (match_operand:DF 1 "any_operand" ""))
9881 (set (match_operand:DF 2 "gpc_reg_operand" "")
9882 (match_dup 0))]
9883 "!(TARGET_E500_DOUBLE && GET_CODE (operands[2]) == SUBREG)
9884 && !TARGET_UPPER_REGS_DF
9885 && peep2_reg_dead_p (2, operands[0])"
9886 [(set (match_dup 2) (match_dup 1))])
9887
9888 (define_peephole2
9889 [(set (match_operand:SF 0 "gpc_reg_operand" "")
9890 (match_operand:SF 1 "any_operand" ""))
9891 (set (match_operand:SF 2 "gpc_reg_operand" "")
9892 (match_dup 0))]
9893 "!TARGET_UPPER_REGS_SF
9894 && peep2_reg_dead_p (2, operands[0])"
9895 [(set (match_dup 2) (match_dup 1))])
9896
9897 \f
9898 ;; TLS support.
9899
9900 ;; Mode attributes for different ABIs.
9901 (define_mode_iterator TLSmode [(SI "! TARGET_64BIT") (DI "TARGET_64BIT")])
9902 (define_mode_attr tls_abi_suffix [(SI "32") (DI "64")])
9903 (define_mode_attr tls_sysv_suffix [(SI "si") (DI "di")])
9904 (define_mode_attr tls_insn_suffix [(SI "wz") (DI "d")])
9905
9906 (define_insn_and_split "tls_gd_aix<TLSmode:tls_abi_suffix>"
9907 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
9908 (call (mem:TLSmode (match_operand:TLSmode 3 "symbol_ref_operand" "s"))
9909 (match_operand 4 "" "g")))
9910 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
9911 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
9912 UNSPEC_TLSGD)
9913 (clobber (reg:SI LR_REGNO))]
9914 "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
9915 {
9916 if (TARGET_CMODEL != CMODEL_SMALL)
9917 return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;"
9918 "bl %z3\;nop";
9919 else
9920 return "addi %0,%1,%2@got@tlsgd\;bl %z3\;nop";
9921 }
9922 "&& TARGET_TLS_MARKERS"
9923 [(set (match_dup 0)
9924 (unspec:TLSmode [(match_dup 1)
9925 (match_dup 2)]
9926 UNSPEC_TLSGD))
9927 (parallel [(set (match_dup 0)
9928 (call (mem:TLSmode (match_dup 3))
9929 (match_dup 4)))
9930 (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)
9931 (clobber (reg:SI LR_REGNO))])]
9932 ""
9933 [(set_attr "type" "two")
9934 (set (attr "length")
9935 (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
9936 (const_int 16)
9937 (const_int 12)))])
9938
9939 (define_insn_and_split "tls_gd_sysv<TLSmode:tls_sysv_suffix>"
9940 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
9941 (call (mem:TLSmode (match_operand:TLSmode 3 "symbol_ref_operand" "s"))
9942 (match_operand 4 "" "g")))
9943 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
9944 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
9945 UNSPEC_TLSGD)
9946 (clobber (reg:SI LR_REGNO))]
9947 "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
9948 {
9949 if (flag_pic)
9950 {
9951 if (TARGET_SECURE_PLT && flag_pic == 2)
9952 return "addi %0,%1,%2@got@tlsgd\;bl %z3+32768@plt";
9953 else
9954 return "addi %0,%1,%2@got@tlsgd\;bl %z3@plt";
9955 }
9956 else
9957 return "addi %0,%1,%2@got@tlsgd\;bl %z3";
9958 }
9959 "&& TARGET_TLS_MARKERS"
9960 [(set (match_dup 0)
9961 (unspec:TLSmode [(match_dup 1)
9962 (match_dup 2)]
9963 UNSPEC_TLSGD))
9964 (parallel [(set (match_dup 0)
9965 (call (mem:TLSmode (match_dup 3))
9966 (match_dup 4)))
9967 (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)
9968 (clobber (reg:SI LR_REGNO))])]
9969 ""
9970 [(set_attr "type" "two")
9971 (set_attr "length" "8")])
9972
9973 (define_insn_and_split "*tls_gd<TLSmode:tls_abi_suffix>"
9974 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
9975 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
9976 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
9977 UNSPEC_TLSGD))]
9978 "HAVE_AS_TLS && TARGET_TLS_MARKERS"
9979 "addi %0,%1,%2@got@tlsgd"
9980 "&& TARGET_CMODEL != CMODEL_SMALL"
9981 [(set (match_dup 3)
9982 (high:TLSmode
9983 (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))
9984 (set (match_dup 0)
9985 (lo_sum:TLSmode (match_dup 3)
9986 (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))]
9987 "
9988 {
9989 operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
9990 }"
9991 [(set (attr "length")
9992 (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
9993 (const_int 8)
9994 (const_int 4)))])
9995
9996 (define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>"
9997 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
9998 (high:TLSmode
9999 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10000 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10001 UNSPEC_TLSGD)))]
10002 "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
10003 "addis %0,%1,%2@got@tlsgd@ha"
10004 [(set_attr "length" "4")])
10005
10006 (define_insn "*tls_gd_low<TLSmode:tls_abi_suffix>"
10007 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10008 (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
10009 (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b")
10010 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10011 UNSPEC_TLSGD)))]
10012 "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
10013 "addi %0,%1,%2@got@tlsgd@l"
10014 [(set_attr "length" "4")])
10015
10016 (define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>"
10017 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10018 (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s"))
10019 (match_operand 2 "" "g")))
10020 (unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")]
10021 UNSPEC_TLSGD)
10022 (clobber (reg:SI LR_REGNO))]
10023 "HAVE_AS_TLS && TARGET_TLS_MARKERS
10024 && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
10025 "bl %z1(%3@tlsgd)\;nop"
10026 [(set_attr "type" "branch")
10027 (set_attr "length" "8")])
10028
10029 (define_insn "*tls_gd_call_sysv<TLSmode:tls_abi_suffix>"
10030 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10031 (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s"))
10032 (match_operand 2 "" "g")))
10033 (unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")]
10034 UNSPEC_TLSGD)
10035 (clobber (reg:SI LR_REGNO))]
10036 "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
10037 {
10038 if (flag_pic)
10039 {
10040 if (TARGET_SECURE_PLT && flag_pic == 2)
10041 return "bl %z1+32768(%3@tlsgd)@plt";
10042 return "bl %z1(%3@tlsgd)@plt";
10043 }
10044 return "bl %z1(%3@tlsgd)";
10045 }
10046 [(set_attr "type" "branch")
10047 (set_attr "length" "4")])
10048
10049 (define_insn_and_split "tls_ld_aix<TLSmode:tls_abi_suffix>"
10050 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10051 (call (mem:TLSmode (match_operand:TLSmode 2 "symbol_ref_operand" "s"))
10052 (match_operand 3 "" "g")))
10053 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
10054 UNSPEC_TLSLD)
10055 (clobber (reg:SI LR_REGNO))]
10056 "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
10057 {
10058 if (TARGET_CMODEL != CMODEL_SMALL)
10059 return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;"
10060 "bl %z2\;nop";
10061 else
10062 return "addi %0,%1,%&@got@tlsld\;bl %z2\;nop";
10063 }
10064 "&& TARGET_TLS_MARKERS"
10065 [(set (match_dup 0)
10066 (unspec:TLSmode [(match_dup 1)]
10067 UNSPEC_TLSLD))
10068 (parallel [(set (match_dup 0)
10069 (call (mem:TLSmode (match_dup 2))
10070 (match_dup 3)))
10071 (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
10072 (clobber (reg:SI LR_REGNO))])]
10073 ""
10074 [(set_attr "type" "two")
10075 (set (attr "length")
10076 (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
10077 (const_int 16)
10078 (const_int 12)))])
10079
10080 (define_insn_and_split "tls_ld_sysv<TLSmode:tls_sysv_suffix>"
10081 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10082 (call (mem:TLSmode (match_operand:TLSmode 2 "symbol_ref_operand" "s"))
10083 (match_operand 3 "" "g")))
10084 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
10085 UNSPEC_TLSLD)
10086 (clobber (reg:SI LR_REGNO))]
10087 "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
10088 {
10089 if (flag_pic)
10090 {
10091 if (TARGET_SECURE_PLT && flag_pic == 2)
10092 return "addi %0,%1,%&@got@tlsld\;bl %z2+32768@plt";
10093 else
10094 return "addi %0,%1,%&@got@tlsld\;bl %z2@plt";
10095 }
10096 else
10097 return "addi %0,%1,%&@got@tlsld\;bl %z2";
10098 }
10099 "&& TARGET_TLS_MARKERS"
10100 [(set (match_dup 0)
10101 (unspec:TLSmode [(match_dup 1)]
10102 UNSPEC_TLSLD))
10103 (parallel [(set (match_dup 0)
10104 (call (mem:TLSmode (match_dup 2))
10105 (match_dup 3)))
10106 (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
10107 (clobber (reg:SI LR_REGNO))])]
10108 ""
10109 [(set_attr "length" "8")])
10110
10111 (define_insn_and_split "*tls_ld<TLSmode:tls_abi_suffix>"
10112 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10113 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
10114 UNSPEC_TLSLD))]
10115 "HAVE_AS_TLS && TARGET_TLS_MARKERS"
10116 "addi %0,%1,%&@got@tlsld"
10117 "&& TARGET_CMODEL != CMODEL_SMALL"
10118 [(set (match_dup 2)
10119 (high:TLSmode
10120 (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))
10121 (set (match_dup 0)
10122 (lo_sum:TLSmode (match_dup 2)
10123 (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))]
10124 "
10125 {
10126 operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
10127 }"
10128 [(set (attr "length")
10129 (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
10130 (const_int 8)
10131 (const_int 4)))])
10132
10133 (define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>"
10134 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10135 (high:TLSmode
10136 (unspec:TLSmode [(const_int 0)
10137 (match_operand:TLSmode 1 "gpc_reg_operand" "b")]
10138 UNSPEC_TLSLD)))]
10139 "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
10140 "addis %0,%1,%&@got@tlsld@ha"
10141 [(set_attr "length" "4")])
10142
10143 (define_insn "*tls_ld_low<TLSmode:tls_abi_suffix>"
10144 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10145 (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
10146 (unspec:TLSmode [(const_int 0)
10147 (match_operand:TLSmode 2 "gpc_reg_operand" "b")]
10148 UNSPEC_TLSLD)))]
10149 "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
10150 "addi %0,%1,%&@got@tlsld@l"
10151 [(set_attr "length" "4")])
10152
10153 (define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>"
10154 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10155 (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s"))
10156 (match_operand 2 "" "g")))
10157 (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
10158 (clobber (reg:SI LR_REGNO))]
10159 "HAVE_AS_TLS && TARGET_TLS_MARKERS
10160 && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
10161 "bl %z1(%&@tlsld)\;nop"
10162 [(set_attr "type" "branch")
10163 (set_attr "length" "8")])
10164
10165 (define_insn "*tls_ld_call_sysv<TLSmode:tls_abi_suffix>"
10166 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10167 (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s"))
10168 (match_operand 2 "" "g")))
10169 (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
10170 (clobber (reg:SI LR_REGNO))]
10171 "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
10172 {
10173 if (flag_pic)
10174 {
10175 if (TARGET_SECURE_PLT && flag_pic == 2)
10176 return "bl %z1+32768(%&@tlsld)@plt";
10177 return "bl %z1(%&@tlsld)@plt";
10178 }
10179 return "bl %z1(%&@tlsld)";
10180 }
10181 [(set_attr "type" "branch")
10182 (set_attr "length" "4")])
10183
10184 (define_insn "tls_dtprel_<TLSmode:tls_abi_suffix>"
10185 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10186 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10187 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10188 UNSPEC_TLSDTPREL))]
10189 "HAVE_AS_TLS"
10190 "addi %0,%1,%2@dtprel")
10191
10192 (define_insn "tls_dtprel_ha_<TLSmode:tls_abi_suffix>"
10193 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10194 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10195 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10196 UNSPEC_TLSDTPRELHA))]
10197 "HAVE_AS_TLS"
10198 "addis %0,%1,%2@dtprel@ha")
10199
10200 (define_insn "tls_dtprel_lo_<TLSmode:tls_abi_suffix>"
10201 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10202 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10203 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10204 UNSPEC_TLSDTPRELLO))]
10205 "HAVE_AS_TLS"
10206 "addi %0,%1,%2@dtprel@l")
10207
10208 (define_insn_and_split "tls_got_dtprel_<TLSmode:tls_abi_suffix>"
10209 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10210 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10211 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10212 UNSPEC_TLSGOTDTPREL))]
10213 "HAVE_AS_TLS"
10214 "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)"
10215 "&& TARGET_CMODEL != CMODEL_SMALL"
10216 [(set (match_dup 3)
10217 (high:TLSmode
10218 (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))
10219 (set (match_dup 0)
10220 (lo_sum:TLSmode (match_dup 3)
10221 (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
10222 "
10223 {
10224 operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
10225 }"
10226 [(set (attr "length")
10227 (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
10228 (const_int 8)
10229 (const_int 4)))])
10230
10231 (define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>"
10232 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10233 (high:TLSmode
10234 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10235 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10236 UNSPEC_TLSGOTDTPREL)))]
10237 "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
10238 "addis %0,%1,%2@got@dtprel@ha"
10239 [(set_attr "length" "4")])
10240
10241 (define_insn "*tls_got_dtprel_low<TLSmode:tls_abi_suffix>"
10242 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10243 (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
10244 (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b")
10245 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10246 UNSPEC_TLSGOTDTPREL)))]
10247 "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
10248 "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)"
10249 [(set_attr "length" "4")])
10250
10251 (define_insn "tls_tprel_<TLSmode:tls_abi_suffix>"
10252 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10253 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10254 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10255 UNSPEC_TLSTPREL))]
10256 "HAVE_AS_TLS"
10257 "addi %0,%1,%2@tprel")
10258
10259 (define_insn "tls_tprel_ha_<TLSmode:tls_abi_suffix>"
10260 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10261 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10262 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10263 UNSPEC_TLSTPRELHA))]
10264 "HAVE_AS_TLS"
10265 "addis %0,%1,%2@tprel@ha")
10266
10267 (define_insn "tls_tprel_lo_<TLSmode:tls_abi_suffix>"
10268 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10269 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10270 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10271 UNSPEC_TLSTPRELLO))]
10272 "HAVE_AS_TLS"
10273 "addi %0,%1,%2@tprel@l")
10274
10275 ;; "b" output constraint here and on tls_tls input to support linker tls
10276 ;; optimization. The linker may edit the instructions emitted by a
10277 ;; tls_got_tprel/tls_tls pair to addis,addi.
10278 (define_insn_and_split "tls_got_tprel_<TLSmode:tls_abi_suffix>"
10279 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10280 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10281 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10282 UNSPEC_TLSGOTTPREL))]
10283 "HAVE_AS_TLS"
10284 "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)"
10285 "&& TARGET_CMODEL != CMODEL_SMALL"
10286 [(set (match_dup 3)
10287 (high:TLSmode
10288 (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))
10289 (set (match_dup 0)
10290 (lo_sum:TLSmode (match_dup 3)
10291 (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))]
10292 "
10293 {
10294 operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
10295 }"
10296 [(set (attr "length")
10297 (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
10298 (const_int 8)
10299 (const_int 4)))])
10300
10301 (define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>"
10302 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
10303 (high:TLSmode
10304 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10305 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10306 UNSPEC_TLSGOTTPREL)))]
10307 "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
10308 "addis %0,%1,%2@got@tprel@ha"
10309 [(set_attr "length" "4")])
10310
10311 (define_insn "*tls_got_tprel_low<TLSmode:tls_abi_suffix>"
10312 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10313 (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
10314 (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b")
10315 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10316 UNSPEC_TLSGOTTPREL)))]
10317 "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
10318 "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)"
10319 [(set_attr "length" "4")])
10320
10321 (define_insn "tls_tls_<TLSmode:tls_abi_suffix>"
10322 [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
10323 (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
10324 (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
10325 UNSPEC_TLSTLS))]
10326 "TARGET_ELF && HAVE_AS_TLS"
10327 "add %0,%1,%2@tls")
10328
10329 (define_expand "tls_get_tpointer"
10330 [(set (match_operand:SI 0 "gpc_reg_operand" "")
10331 (unspec:SI [(const_int 0)] UNSPEC_TLSTLS))]
10332 "TARGET_XCOFF && HAVE_AS_TLS"
10333 "
10334 {
10335 emit_insn (gen_tls_get_tpointer_internal ());
10336 emit_move_insn (operands[0], gen_rtx_REG (SImode, 3));
10337 DONE;
10338 }")
10339
10340 (define_insn "tls_get_tpointer_internal"
10341 [(set (reg:SI 3)
10342 (unspec:SI [(const_int 0)] UNSPEC_TLSTLS))
10343 (clobber (reg:SI LR_REGNO))]
10344 "TARGET_XCOFF && HAVE_AS_TLS"
10345 "bla __get_tpointer")
10346
10347 (define_expand "tls_get_addr<mode>"
10348 [(set (match_operand:P 0 "gpc_reg_operand" "")
10349 (unspec:P [(match_operand:P 1 "gpc_reg_operand" "")
10350 (match_operand:P 2 "gpc_reg_operand" "")] UNSPEC_TLSTLS))]
10351 "TARGET_XCOFF && HAVE_AS_TLS"
10352 "
10353 {
10354 emit_move_insn (gen_rtx_REG (Pmode, 3), operands[1]);
10355 emit_move_insn (gen_rtx_REG (Pmode, 4), operands[2]);
10356 emit_insn (gen_tls_get_addr_internal<mode> ());
10357 emit_move_insn (operands[0], gen_rtx_REG (Pmode, 3));
10358 DONE;
10359 }")
10360
10361 (define_insn "tls_get_addr_internal<mode>"
10362 [(set (reg:P 3)
10363 (unspec:P [(reg:P 3) (reg:P 4)] UNSPEC_TLSTLS))
10364 (clobber (reg:P 0))
10365 (clobber (reg:P 4))
10366 (clobber (reg:P 5))
10367 (clobber (reg:P 11))
10368 (clobber (reg:CC CR0_REGNO))
10369 (clobber (reg:P LR_REGNO))]
10370 "TARGET_XCOFF && HAVE_AS_TLS"
10371 "bla __tls_get_addr")
10372 \f
10373 ;; Next come insns related to the calling sequence.
10374 ;;
10375 ;; First, an insn to allocate new stack space for dynamic use (e.g., alloca).
10376 ;; We move the back-chain and decrement the stack pointer.
10377
10378 (define_expand "allocate_stack"
10379 [(set (match_operand 0 "gpc_reg_operand" "")
10380 (minus (reg 1) (match_operand 1 "reg_or_short_operand" "")))
10381 (set (reg 1)
10382 (minus (reg 1) (match_dup 1)))]
10383 ""
10384 "
10385 { rtx chain = gen_reg_rtx (Pmode);
10386 rtx stack_bot = gen_rtx_MEM (Pmode, stack_pointer_rtx);
10387 rtx neg_op0;
10388 rtx insn, par, set, mem;
10389
10390 emit_move_insn (chain, stack_bot);
10391
10392 /* Check stack bounds if necessary. */
10393 if (crtl->limit_stack)
10394 {
10395 rtx available;
10396 available = expand_binop (Pmode, sub_optab,
10397 stack_pointer_rtx, stack_limit_rtx,
10398 NULL_RTX, 1, OPTAB_WIDEN);
10399 emit_insn (gen_cond_trap (LTU, available, operands[1], const0_rtx));
10400 }
10401
10402 if (GET_CODE (operands[1]) != CONST_INT
10403 || INTVAL (operands[1]) < -32767
10404 || INTVAL (operands[1]) > 32768)
10405 {
10406 neg_op0 = gen_reg_rtx (Pmode);
10407 if (TARGET_32BIT)
10408 emit_insn (gen_negsi2 (neg_op0, operands[1]));
10409 else
10410 emit_insn (gen_negdi2 (neg_op0, operands[1]));
10411 }
10412 else
10413 neg_op0 = GEN_INT (- INTVAL (operands[1]));
10414
10415 insn = emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update_stack
10416 : gen_movdi_di_update_stack))
10417 (stack_pointer_rtx, stack_pointer_rtx, neg_op0,
10418 chain));
10419 /* Since we didn't use gen_frame_mem to generate the MEM, grab
10420 it now and set the alias set/attributes. The above gen_*_update
10421 calls will generate a PARALLEL with the MEM set being the first
10422 operation. */
10423 par = PATTERN (insn);
10424 gcc_assert (GET_CODE (par) == PARALLEL);
10425 set = XVECEXP (par, 0, 0);
10426 gcc_assert (GET_CODE (set) == SET);
10427 mem = SET_DEST (set);
10428 gcc_assert (MEM_P (mem));
10429 MEM_NOTRAP_P (mem) = 1;
10430 set_mem_alias_set (mem, get_frame_alias_set ());
10431
10432 emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
10433 DONE;
10434 }")
10435
10436 ;; These patterns say how to save and restore the stack pointer. We need not
10437 ;; save the stack pointer at function level since we are careful to
10438 ;; preserve the backchain. At block level, we have to restore the backchain
10439 ;; when we restore the stack pointer.
10440 ;;
10441 ;; For nonlocal gotos, we must save both the stack pointer and its
10442 ;; backchain and restore both. Note that in the nonlocal case, the
10443 ;; save area is a memory location.
10444
10445 (define_expand "save_stack_function"
10446 [(match_operand 0 "any_operand" "")
10447 (match_operand 1 "any_operand" "")]
10448 ""
10449 "DONE;")
10450
10451 (define_expand "restore_stack_function"
10452 [(match_operand 0 "any_operand" "")
10453 (match_operand 1 "any_operand" "")]
10454 ""
10455 "DONE;")
10456
10457 ;; Adjust stack pointer (op0) to a new value (op1).
10458 ;; First copy old stack backchain to new location, and ensure that the
10459 ;; scheduler won't reorder the sp assignment before the backchain write.
10460 (define_expand "restore_stack_block"
10461 [(set (match_dup 2) (match_dup 3))
10462 (set (match_dup 4) (match_dup 2))
10463 (match_dup 5)
10464 (set (match_operand 0 "register_operand" "")
10465 (match_operand 1 "register_operand" ""))]
10466 ""
10467 "
10468 {
10469 rtvec p;
10470
10471 operands[1] = force_reg (Pmode, operands[1]);
10472 operands[2] = gen_reg_rtx (Pmode);
10473 operands[3] = gen_frame_mem (Pmode, operands[0]);
10474 operands[4] = gen_frame_mem (Pmode, operands[1]);
10475 p = rtvec_alloc (1);
10476 RTVEC_ELT (p, 0) = gen_rtx_SET (gen_frame_mem (BLKmode, operands[0]),
10477 const0_rtx);
10478 operands[5] = gen_rtx_PARALLEL (VOIDmode, p);
10479 }")
10480
10481 (define_expand "save_stack_nonlocal"
10482 [(set (match_dup 3) (match_dup 4))
10483 (set (match_operand 0 "memory_operand" "") (match_dup 3))
10484 (set (match_dup 2) (match_operand 1 "register_operand" ""))]
10485 ""
10486 "
10487 {
10488 int units_per_word = (TARGET_32BIT) ? 4 : 8;
10489
10490 /* Copy the backchain to the first word, sp to the second. */
10491 operands[0] = adjust_address_nv (operands[0], Pmode, 0);
10492 operands[2] = adjust_address_nv (operands[0], Pmode, units_per_word);
10493 operands[3] = gen_reg_rtx (Pmode);
10494 operands[4] = gen_frame_mem (Pmode, operands[1]);
10495 }")
10496
10497 (define_expand "restore_stack_nonlocal"
10498 [(set (match_dup 2) (match_operand 1 "memory_operand" ""))
10499 (set (match_dup 3) (match_dup 4))
10500 (set (match_dup 5) (match_dup 2))
10501 (match_dup 6)
10502 (set (match_operand 0 "register_operand" "") (match_dup 3))]
10503 ""
10504 "
10505 {
10506 int units_per_word = (TARGET_32BIT) ? 4 : 8;
10507 rtvec p;
10508
10509 /* Restore the backchain from the first word, sp from the second. */
10510 operands[2] = gen_reg_rtx (Pmode);
10511 operands[3] = gen_reg_rtx (Pmode);
10512 operands[1] = adjust_address_nv (operands[1], Pmode, 0);
10513 operands[4] = adjust_address_nv (operands[1], Pmode, units_per_word);
10514 operands[5] = gen_frame_mem (Pmode, operands[3]);
10515 p = rtvec_alloc (1);
10516 RTVEC_ELT (p, 0) = gen_rtx_SET (gen_frame_mem (BLKmode, operands[0]),
10517 const0_rtx);
10518 operands[6] = gen_rtx_PARALLEL (VOIDmode, p);
10519 }")
10520 \f
10521 ;; TOC register handling.
10522
10523 ;; Code to initialize the TOC register...
10524
10525 (define_insn "load_toc_aix_si"
10526 [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
10527 (unspec:SI [(const_int 0)] UNSPEC_TOC))
10528 (use (reg:SI 2))])]
10529 "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_32BIT"
10530 "*
10531 {
10532 char buf[30];
10533 extern int need_toc_init;
10534 need_toc_init = 1;
10535 ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", 1);
10536 operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
10537 operands[2] = gen_rtx_REG (Pmode, 2);
10538 return \"lwz %0,%1(%2)\";
10539 }"
10540 [(set_attr "type" "load")
10541 (set_attr "update" "no")
10542 (set_attr "indexed" "no")])
10543
10544 (define_insn "load_toc_aix_di"
10545 [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
10546 (unspec:DI [(const_int 0)] UNSPEC_TOC))
10547 (use (reg:DI 2))])]
10548 "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_64BIT"
10549 "*
10550 {
10551 char buf[30];
10552 extern int need_toc_init;
10553 need_toc_init = 1;
10554 ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\",
10555 !TARGET_ELF || !TARGET_MINIMAL_TOC);
10556 if (TARGET_ELF)
10557 strcat (buf, \"@toc\");
10558 operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
10559 operands[2] = gen_rtx_REG (Pmode, 2);
10560 return \"ld %0,%1(%2)\";
10561 }"
10562 [(set_attr "type" "load")
10563 (set_attr "update" "no")
10564 (set_attr "indexed" "no")])
10565
10566 (define_insn "load_toc_v4_pic_si"
10567 [(set (reg:SI LR_REGNO)
10568 (unspec:SI [(const_int 0)] UNSPEC_TOC))]
10569 "DEFAULT_ABI == ABI_V4 && flag_pic == 1 && TARGET_32BIT"
10570 "bl _GLOBAL_OFFSET_TABLE_@local-4"
10571 [(set_attr "type" "branch")
10572 (set_attr "length" "4")])
10573
10574 (define_expand "load_toc_v4_PIC_1"
10575 [(parallel [(set (reg:SI LR_REGNO)
10576 (match_operand:SI 0 "immediate_operand" "s"))
10577 (use (unspec [(match_dup 0)] UNSPEC_TOC))])]
10578 "TARGET_ELF && DEFAULT_ABI == ABI_V4
10579 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
10580 "")
10581
10582 (define_insn "load_toc_v4_PIC_1_normal"
10583 [(set (reg:SI LR_REGNO)
10584 (match_operand:SI 0 "immediate_operand" "s"))
10585 (use (unspec [(match_dup 0)] UNSPEC_TOC))]
10586 "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4
10587 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
10588 "bcl 20,31,%0\\n%0:"
10589 [(set_attr "type" "branch")
10590 (set_attr "length" "4")
10591 (set_attr "cannot_copy" "yes")])
10592
10593 (define_insn "load_toc_v4_PIC_1_476"
10594 [(set (reg:SI LR_REGNO)
10595 (match_operand:SI 0 "immediate_operand" "s"))
10596 (use (unspec [(match_dup 0)] UNSPEC_TOC))]
10597 "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4
10598 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
10599 "*
10600 {
10601 char name[32];
10602 static char templ[32];
10603
10604 get_ppc476_thunk_name (name);
10605 sprintf (templ, \"bl %s\\n%%0:\", name);
10606 return templ;
10607 }"
10608 [(set_attr "type" "branch")
10609 (set_attr "length" "4")
10610 (set_attr "cannot_copy" "yes")])
10611
10612 (define_expand "load_toc_v4_PIC_1b"
10613 [(parallel [(set (reg:SI LR_REGNO)
10614 (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
10615 (label_ref (match_operand 1 "" ""))]
10616 UNSPEC_TOCPTR))
10617 (match_dup 1)])]
10618 "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
10619 "")
10620
10621 (define_insn "load_toc_v4_PIC_1b_normal"
10622 [(set (reg:SI LR_REGNO)
10623 (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
10624 (label_ref (match_operand 1 "" ""))]
10625 UNSPEC_TOCPTR))
10626 (match_dup 1)]
10627 "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
10628 "bcl 20,31,$+8\;.long %0-$"
10629 [(set_attr "type" "branch")
10630 (set_attr "length" "8")])
10631
10632 (define_insn "load_toc_v4_PIC_1b_476"
10633 [(set (reg:SI LR_REGNO)
10634 (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
10635 (label_ref (match_operand 1 "" ""))]
10636 UNSPEC_TOCPTR))
10637 (match_dup 1)]
10638 "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
10639 "*
10640 {
10641 char name[32];
10642 static char templ[32];
10643
10644 get_ppc476_thunk_name (name);
10645 sprintf (templ, \"bl %s\\n\\tb $+8\\n\\t.long %%0-$\", name);
10646 return templ;
10647 }"
10648 [(set_attr "type" "branch")
10649 (set_attr "length" "16")])
10650
10651 (define_insn "load_toc_v4_PIC_2"
10652 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
10653 (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
10654 (minus:SI (match_operand:SI 2 "immediate_operand" "s")
10655 (match_operand:SI 3 "immediate_operand" "s")))))]
10656 "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
10657 "lwz %0,%2-%3(%1)"
10658 [(set_attr "type" "load")])
10659
10660 (define_insn "load_toc_v4_PIC_3b"
10661 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
10662 (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
10663 (high:SI
10664 (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
10665 (match_operand:SI 3 "symbol_ref_operand" "s")))))]
10666 "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic"
10667 "addis %0,%1,%2-%3@ha")
10668
10669 (define_insn "load_toc_v4_PIC_3c"
10670 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
10671 (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
10672 (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
10673 (match_operand:SI 3 "symbol_ref_operand" "s"))))]
10674 "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic"
10675 "addi %0,%1,%2-%3@l")
10676
10677 ;; If the TOC is shared over a translation unit, as happens with all
10678 ;; the kinds of PIC that we support, we need to restore the TOC
10679 ;; pointer only when jumping over units of translation.
10680 ;; On Darwin, we need to reload the picbase.
10681
10682 (define_expand "builtin_setjmp_receiver"
10683 [(use (label_ref (match_operand 0 "" "")))]
10684 "(DEFAULT_ABI == ABI_V4 && flag_pic == 1)
10685 || (TARGET_TOC && TARGET_MINIMAL_TOC)
10686 || (DEFAULT_ABI == ABI_DARWIN && flag_pic)"
10687 "
10688 {
10689 #if TARGET_MACHO
10690 if (DEFAULT_ABI == ABI_DARWIN)
10691 {
10692 rtx picrtx = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME);
10693 rtx picreg = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
10694 rtx tmplabrtx;
10695 char tmplab[20];
10696
10697 crtl->uses_pic_offset_table = 1;
10698 ASM_GENERATE_INTERNAL_LABEL(tmplab, \"LSJR\",
10699 CODE_LABEL_NUMBER (operands[0]));
10700 tmplabrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab));
10701
10702 emit_insn (gen_load_macho_picbase (tmplabrtx));
10703 emit_move_insn (picreg, gen_rtx_REG (Pmode, LR_REGNO));
10704 emit_insn (gen_macho_correct_pic (picreg, picreg, picrtx, tmplabrtx));
10705 }
10706 else
10707 #endif
10708 rs6000_emit_load_toc_table (FALSE);
10709 DONE;
10710 }")
10711
10712 ;; Largetoc support
10713 (define_insn "*largetoc_high"
10714 [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
10715 (high:DI
10716 (unspec [(match_operand:DI 1 "" "")
10717 (match_operand:DI 2 "gpc_reg_operand" "b")]
10718 UNSPEC_TOCREL)))]
10719 "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
10720 "addis %0,%2,%1@toc@ha")
10721
10722 (define_insn "*largetoc_high_aix<mode>"
10723 [(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
10724 (high:P
10725 (unspec [(match_operand:P 1 "" "")
10726 (match_operand:P 2 "gpc_reg_operand" "b")]
10727 UNSPEC_TOCREL)))]
10728 "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
10729 "addis %0,%1@u(%2)")
10730
10731 (define_insn "*largetoc_high_plus"
10732 [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
10733 (high:DI
10734 (plus:DI
10735 (unspec [(match_operand:DI 1 "" "")
10736 (match_operand:DI 2 "gpc_reg_operand" "b")]
10737 UNSPEC_TOCREL)
10738 (match_operand:DI 3 "add_cint_operand" "n"))))]
10739 "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
10740 "addis %0,%2,%1+%3@toc@ha")
10741
10742 (define_insn "*largetoc_high_plus_aix<mode>"
10743 [(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
10744 (high:P
10745 (plus:P
10746 (unspec [(match_operand:P 1 "" "")
10747 (match_operand:P 2 "gpc_reg_operand" "b")]
10748 UNSPEC_TOCREL)
10749 (match_operand:P 3 "add_cint_operand" "n"))))]
10750 "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
10751 "addis %0,%1+%3@u(%2)")
10752
10753 (define_insn "*largetoc_low"
10754 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
10755 (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
10756 (match_operand:DI 2 "" "")))]
10757 "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
10758 "addi %0,%1,%2@l")
10759
10760 (define_insn "*largetoc_low_aix<mode>"
10761 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
10762 (lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b")
10763 (match_operand:P 2 "" "")))]
10764 "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
10765 "la %0,%2@l(%1)")
10766
10767 (define_insn_and_split "*tocref<mode>"
10768 [(set (match_operand:P 0 "gpc_reg_operand" "=b")
10769 (match_operand:P 1 "small_toc_ref" "R"))]
10770 "TARGET_TOC"
10771 "la %0,%a1"
10772 "&& TARGET_CMODEL != CMODEL_SMALL && reload_completed"
10773 [(set (match_dup 0) (high:P (match_dup 1)))
10774 (set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))])
10775
10776 ;; Elf specific ways of loading addresses for non-PIC code.
10777 ;; The output of this could be r0, but we make a very strong
10778 ;; preference for a base register because it will usually
10779 ;; be needed there.
10780 (define_insn "elf_high"
10781 [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
10782 (high:SI (match_operand 1 "" "")))]
10783 "TARGET_ELF && !TARGET_64BIT && !flag_pic"
10784 "lis %0,%1@ha")
10785
10786 (define_insn "elf_low"
10787 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
10788 (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
10789 (match_operand 2 "" "")))]
10790 "TARGET_ELF && !TARGET_64BIT && !flag_pic"
10791 "la %0,%2@l(%1)")
10792 \f
10793 ;; Call and call_value insns
10794 (define_expand "call"
10795 [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
10796 (match_operand 1 "" ""))
10797 (use (match_operand 2 "" ""))
10798 (clobber (reg:SI LR_REGNO))])]
10799 ""
10800 "
10801 {
10802 #if TARGET_MACHO
10803 if (MACHOPIC_INDIRECT)
10804 operands[0] = machopic_indirect_call_target (operands[0]);
10805 #endif
10806
10807 gcc_assert (GET_CODE (operands[0]) == MEM);
10808 gcc_assert (GET_CODE (operands[1]) == CONST_INT);
10809
10810 operands[0] = XEXP (operands[0], 0);
10811
10812 if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
10813 {
10814 rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]);
10815 DONE;
10816 }
10817
10818 if (GET_CODE (operands[0]) != SYMBOL_REF
10819 || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
10820 {
10821 if (INTVAL (operands[2]) & CALL_LONG)
10822 operands[0] = rs6000_longcall_ref (operands[0]);
10823
10824 switch (DEFAULT_ABI)
10825 {
10826 case ABI_V4:
10827 case ABI_DARWIN:
10828 operands[0] = force_reg (Pmode, operands[0]);
10829 break;
10830
10831 default:
10832 gcc_unreachable ();
10833 }
10834 }
10835 }")
10836
10837 (define_expand "call_value"
10838 [(parallel [(set (match_operand 0 "" "")
10839 (call (mem:SI (match_operand 1 "address_operand" ""))
10840 (match_operand 2 "" "")))
10841 (use (match_operand 3 "" ""))
10842 (clobber (reg:SI LR_REGNO))])]
10843 ""
10844 "
10845 {
10846 #if TARGET_MACHO
10847 if (MACHOPIC_INDIRECT)
10848 operands[1] = machopic_indirect_call_target (operands[1]);
10849 #endif
10850
10851 gcc_assert (GET_CODE (operands[1]) == MEM);
10852 gcc_assert (GET_CODE (operands[2]) == CONST_INT);
10853
10854 operands[1] = XEXP (operands[1], 0);
10855
10856 if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
10857 {
10858 rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]);
10859 DONE;
10860 }
10861
10862 if (GET_CODE (operands[1]) != SYMBOL_REF
10863 || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
10864 {
10865 if (INTVAL (operands[3]) & CALL_LONG)
10866 operands[1] = rs6000_longcall_ref (operands[1]);
10867
10868 switch (DEFAULT_ABI)
10869 {
10870 case ABI_V4:
10871 case ABI_DARWIN:
10872 operands[1] = force_reg (Pmode, operands[1]);
10873 break;
10874
10875 default:
10876 gcc_unreachable ();
10877 }
10878 }
10879 }")
10880
10881 ;; Call to function in current module. No TOC pointer reload needed.
10882 ;; Operand2 is nonzero if we are using the V.4 calling sequence and
10883 ;; either the function was not prototyped, or it was prototyped as a
10884 ;; variable argument function. It is > 0 if FP registers were passed
10885 ;; and < 0 if they were not.
10886
10887 (define_insn "*call_local32"
10888 [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
10889 (match_operand 1 "" "g,g"))
10890 (use (match_operand:SI 2 "immediate_operand" "O,n"))
10891 (clobber (reg:SI LR_REGNO))]
10892 "(INTVAL (operands[2]) & CALL_LONG) == 0"
10893 "*
10894 {
10895 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
10896 output_asm_insn (\"crxor 6,6,6\", operands);
10897
10898 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
10899 output_asm_insn (\"creqv 6,6,6\", operands);
10900
10901 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@local\" : \"bl %z0\";
10902 }"
10903 [(set_attr "type" "branch")
10904 (set_attr "length" "4,8")])
10905
10906 (define_insn "*call_local64"
10907 [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
10908 (match_operand 1 "" "g,g"))
10909 (use (match_operand:SI 2 "immediate_operand" "O,n"))
10910 (clobber (reg:SI LR_REGNO))]
10911 "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
10912 "*
10913 {
10914 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
10915 output_asm_insn (\"crxor 6,6,6\", operands);
10916
10917 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
10918 output_asm_insn (\"creqv 6,6,6\", operands);
10919
10920 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@local\" : \"bl %z0\";
10921 }"
10922 [(set_attr "type" "branch")
10923 (set_attr "length" "4,8")])
10924
10925 (define_insn "*call_value_local32"
10926 [(set (match_operand 0 "" "")
10927 (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
10928 (match_operand 2 "" "g,g")))
10929 (use (match_operand:SI 3 "immediate_operand" "O,n"))
10930 (clobber (reg:SI LR_REGNO))]
10931 "(INTVAL (operands[3]) & CALL_LONG) == 0"
10932 "*
10933 {
10934 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
10935 output_asm_insn (\"crxor 6,6,6\", operands);
10936
10937 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
10938 output_asm_insn (\"creqv 6,6,6\", operands);
10939
10940 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\";
10941 }"
10942 [(set_attr "type" "branch")
10943 (set_attr "length" "4,8")])
10944
10945
10946 (define_insn "*call_value_local64"
10947 [(set (match_operand 0 "" "")
10948 (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
10949 (match_operand 2 "" "g,g")))
10950 (use (match_operand:SI 3 "immediate_operand" "O,n"))
10951 (clobber (reg:SI LR_REGNO))]
10952 "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
10953 "*
10954 {
10955 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
10956 output_asm_insn (\"crxor 6,6,6\", operands);
10957
10958 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
10959 output_asm_insn (\"creqv 6,6,6\", operands);
10960
10961 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\";
10962 }"
10963 [(set_attr "type" "branch")
10964 (set_attr "length" "4,8")])
10965
10966
10967 ;; A function pointer under System V is just a normal pointer
10968 ;; operands[0] is the function pointer
10969 ;; operands[1] is the stack size to clean up
10970 ;; operands[2] is the value FUNCTION_ARG returns for the VOID argument
10971 ;; which indicates how to set cr1
10972
10973 (define_insn "*call_indirect_nonlocal_sysv<mode>"
10974 [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l,c,*l"))
10975 (match_operand 1 "" "g,g,g,g"))
10976 (use (match_operand:SI 2 "immediate_operand" "O,O,n,n"))
10977 (clobber (reg:SI LR_REGNO))]
10978 "DEFAULT_ABI == ABI_V4
10979 || DEFAULT_ABI == ABI_DARWIN"
10980 {
10981 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
10982 output_asm_insn ("crxor 6,6,6", operands);
10983
10984 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
10985 output_asm_insn ("creqv 6,6,6", operands);
10986
10987 return "b%T0l";
10988 }
10989 [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
10990 (set_attr "length" "4,4,8,8")])
10991
10992 (define_insn_and_split "*call_nonlocal_sysv<mode>"
10993 [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
10994 (match_operand 1 "" "g,g"))
10995 (use (match_operand:SI 2 "immediate_operand" "O,n"))
10996 (clobber (reg:SI LR_REGNO))]
10997 "(DEFAULT_ABI == ABI_DARWIN
10998 || (DEFAULT_ABI == ABI_V4
10999 && (INTVAL (operands[2]) & CALL_LONG) == 0))"
11000 {
11001 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
11002 output_asm_insn ("crxor 6,6,6", operands);
11003
11004 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
11005 output_asm_insn ("creqv 6,6,6", operands);
11006
11007 #if TARGET_MACHO
11008 return output_call(insn, operands, 0, 2);
11009 #else
11010 if (DEFAULT_ABI == ABI_V4 && flag_pic)
11011 {
11012 gcc_assert (!TARGET_SECURE_PLT);
11013 return "bl %z0@plt";
11014 }
11015 else
11016 return "bl %z0";
11017 #endif
11018 }
11019 "DEFAULT_ABI == ABI_V4
11020 && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[0])
11021 && (INTVAL (operands[2]) & CALL_LONG) == 0"
11022 [(parallel [(call (mem:SI (match_dup 0))
11023 (match_dup 1))
11024 (use (match_dup 2))
11025 (use (match_dup 3))
11026 (clobber (reg:SI LR_REGNO))])]
11027 {
11028 operands[3] = pic_offset_table_rtx;
11029 }
11030 [(set_attr "type" "branch,branch")
11031 (set_attr "length" "4,8")])
11032
11033 (define_insn "*call_nonlocal_sysv_secure<mode>"
11034 [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
11035 (match_operand 1 "" "g,g"))
11036 (use (match_operand:SI 2 "immediate_operand" "O,n"))
11037 (use (match_operand:SI 3 "register_operand" "r,r"))
11038 (clobber (reg:SI LR_REGNO))]
11039 "(DEFAULT_ABI == ABI_V4
11040 && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[0])
11041 && (INTVAL (operands[2]) & CALL_LONG) == 0)"
11042 {
11043 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
11044 output_asm_insn ("crxor 6,6,6", operands);
11045
11046 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
11047 output_asm_insn ("creqv 6,6,6", operands);
11048
11049 if (flag_pic == 2)
11050 /* The magic 32768 offset here and in the other sysv call insns
11051 corresponds to the offset of r30 in .got2, as given by LCTOC1.
11052 See sysv4.h:toc_section. */
11053 return "bl %z0+32768@plt";
11054 else
11055 return "bl %z0@plt";
11056 }
11057 [(set_attr "type" "branch,branch")
11058 (set_attr "length" "4,8")])
11059
11060 (define_insn "*call_value_indirect_nonlocal_sysv<mode>"
11061 [(set (match_operand 0 "" "")
11062 (call (mem:SI (match_operand:P 1 "register_operand" "c,*l,c,*l"))
11063 (match_operand 2 "" "g,g,g,g")))
11064 (use (match_operand:SI 3 "immediate_operand" "O,O,n,n"))
11065 (clobber (reg:SI LR_REGNO))]
11066 "DEFAULT_ABI == ABI_V4
11067 || DEFAULT_ABI == ABI_DARWIN"
11068 {
11069 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
11070 output_asm_insn ("crxor 6,6,6", operands);
11071
11072 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
11073 output_asm_insn ("creqv 6,6,6", operands);
11074
11075 return "b%T1l";
11076 }
11077 [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
11078 (set_attr "length" "4,4,8,8")])
11079
11080 (define_insn_and_split "*call_value_nonlocal_sysv<mode>"
11081 [(set (match_operand 0 "" "")
11082 (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s"))
11083 (match_operand 2 "" "g,g")))
11084 (use (match_operand:SI 3 "immediate_operand" "O,n"))
11085 (clobber (reg:SI LR_REGNO))]
11086 "(DEFAULT_ABI == ABI_DARWIN
11087 || (DEFAULT_ABI == ABI_V4
11088 && (INTVAL (operands[3]) & CALL_LONG) == 0))"
11089 {
11090 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
11091 output_asm_insn ("crxor 6,6,6", operands);
11092
11093 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
11094 output_asm_insn ("creqv 6,6,6", operands);
11095
11096 #if TARGET_MACHO
11097 return output_call(insn, operands, 1, 3);
11098 #else
11099 if (DEFAULT_ABI == ABI_V4 && flag_pic)
11100 {
11101 gcc_assert (!TARGET_SECURE_PLT);
11102 return "bl %z1@plt";
11103 }
11104 else
11105 return "bl %z1";
11106 #endif
11107 }
11108 "DEFAULT_ABI == ABI_V4
11109 && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[1])
11110 && (INTVAL (operands[3]) & CALL_LONG) == 0"
11111 [(parallel [(set (match_dup 0)
11112 (call (mem:SI (match_dup 1))
11113 (match_dup 2)))
11114 (use (match_dup 3))
11115 (use (match_dup 4))
11116 (clobber (reg:SI LR_REGNO))])]
11117 {
11118 operands[4] = pic_offset_table_rtx;
11119 }
11120 [(set_attr "type" "branch,branch")
11121 (set_attr "length" "4,8")])
11122
11123 (define_insn "*call_value_nonlocal_sysv_secure<mode>"
11124 [(set (match_operand 0 "" "")
11125 (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s"))
11126 (match_operand 2 "" "g,g")))
11127 (use (match_operand:SI 3 "immediate_operand" "O,n"))
11128 (use (match_operand:SI 4 "register_operand" "r,r"))
11129 (clobber (reg:SI LR_REGNO))]
11130 "(DEFAULT_ABI == ABI_V4
11131 && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[1])
11132 && (INTVAL (operands[3]) & CALL_LONG) == 0)"
11133 {
11134 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
11135 output_asm_insn ("crxor 6,6,6", operands);
11136
11137 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
11138 output_asm_insn ("creqv 6,6,6", operands);
11139
11140 if (flag_pic == 2)
11141 return "bl %z1+32768@plt";
11142 else
11143 return "bl %z1@plt";
11144 }
11145 [(set_attr "type" "branch,branch")
11146 (set_attr "length" "4,8")])
11147
11148
11149 ;; Call to AIX abi function in the same module.
11150
11151 (define_insn "*call_local_aix<mode>"
11152 [(call (mem:SI (match_operand:P 0 "current_file_function_operand" "s"))
11153 (match_operand 1 "" "g"))
11154 (clobber (reg:P LR_REGNO))]
11155 "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
11156 "bl %z0"
11157 [(set_attr "type" "branch")
11158 (set_attr "length" "4")])
11159
11160 (define_insn "*call_value_local_aix<mode>"
11161 [(set (match_operand 0 "" "")
11162 (call (mem:SI (match_operand:P 1 "current_file_function_operand" "s"))
11163 (match_operand 2 "" "g")))
11164 (clobber (reg:P LR_REGNO))]
11165 "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
11166 "bl %z1"
11167 [(set_attr "type" "branch")
11168 (set_attr "length" "4")])
11169
11170 ;; Call to AIX abi function which may be in another module.
11171 ;; Restore the TOC pointer (r2) after the call.
11172
11173 (define_insn "*call_nonlocal_aix<mode>"
11174 [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s"))
11175 (match_operand 1 "" "g"))
11176 (clobber (reg:P LR_REGNO))]
11177 "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
11178 "bl %z0\;nop"
11179 [(set_attr "type" "branch")
11180 (set_attr "length" "8")])
11181
11182 (define_insn "*call_value_nonlocal_aix<mode>"
11183 [(set (match_operand 0 "" "")
11184 (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
11185 (match_operand 2 "" "g")))
11186 (clobber (reg:P LR_REGNO))]
11187 "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
11188 "bl %z1\;nop"
11189 [(set_attr "type" "branch")
11190 (set_attr "length" "8")])
11191
11192 ;; Call to indirect functions with the AIX abi using a 3 word descriptor.
11193 ;; Operand0 is the addresss of the function to call
11194 ;; Operand2 is the location in the function descriptor to load r2 from
11195 ;; Operand3 is the offset of the stack location holding the current TOC pointer
11196
11197 (define_insn "*call_indirect_aix<mode>"
11198 [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
11199 (match_operand 1 "" "g,g"))
11200 (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
11201 (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
11202 (clobber (reg:P LR_REGNO))]
11203 "DEFAULT_ABI == ABI_AIX"
11204 "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3(1)"
11205 [(set_attr "type" "jmpreg")
11206 (set_attr "length" "12")])
11207
11208 (define_insn "*call_value_indirect_aix<mode>"
11209 [(set (match_operand 0 "" "")
11210 (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
11211 (match_operand 2 "" "g,g")))
11212 (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
11213 (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
11214 (clobber (reg:P LR_REGNO))]
11215 "DEFAULT_ABI == ABI_AIX"
11216 "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4(1)"
11217 [(set_attr "type" "jmpreg")
11218 (set_attr "length" "12")])
11219
11220 ;; Call to indirect functions with the ELFv2 ABI.
11221 ;; Operand0 is the addresss of the function to call
11222 ;; Operand2 is the offset of the stack location holding the current TOC pointer
11223
11224 (define_insn "*call_indirect_elfv2<mode>"
11225 [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
11226 (match_operand 1 "" "g,g"))
11227 (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
11228 (clobber (reg:P LR_REGNO))]
11229 "DEFAULT_ABI == ABI_ELFv2"
11230 "b%T0l\;<ptrload> 2,%2(1)"
11231 [(set_attr "type" "jmpreg")
11232 (set_attr "length" "8")])
11233
11234 (define_insn "*call_value_indirect_elfv2<mode>"
11235 [(set (match_operand 0 "" "")
11236 (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
11237 (match_operand 2 "" "g,g")))
11238 (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
11239 (clobber (reg:P LR_REGNO))]
11240 "DEFAULT_ABI == ABI_ELFv2"
11241 "b%T1l\;<ptrload> 2,%3(1)"
11242 [(set_attr "type" "jmpreg")
11243 (set_attr "length" "8")])
11244
11245
11246 ;; Call subroutine returning any type.
11247 (define_expand "untyped_call"
11248 [(parallel [(call (match_operand 0 "" "")
11249 (const_int 0))
11250 (match_operand 1 "" "")
11251 (match_operand 2 "" "")])]
11252 ""
11253 "
11254 {
11255 int i;
11256
11257 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
11258
11259 for (i = 0; i < XVECLEN (operands[2], 0); i++)
11260 {
11261 rtx set = XVECEXP (operands[2], 0, i);
11262 emit_move_insn (SET_DEST (set), SET_SRC (set));
11263 }
11264
11265 /* The optimizer does not know that the call sets the function value
11266 registers we stored in the result block. We avoid problems by
11267 claiming that all hard registers are used and clobbered at this
11268 point. */
11269 emit_insn (gen_blockage ());
11270
11271 DONE;
11272 }")
11273
11274 ;; sibling call patterns
11275 (define_expand "sibcall"
11276 [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
11277 (match_operand 1 "" ""))
11278 (use (match_operand 2 "" ""))
11279 (simple_return)])]
11280 ""
11281 "
11282 {
11283 #if TARGET_MACHO
11284 if (MACHOPIC_INDIRECT)
11285 operands[0] = machopic_indirect_call_target (operands[0]);
11286 #endif
11287
11288 gcc_assert (GET_CODE (operands[0]) == MEM);
11289 gcc_assert (GET_CODE (operands[1]) == CONST_INT);
11290
11291 operands[0] = XEXP (operands[0], 0);
11292
11293 if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
11294 {
11295 rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]);
11296 DONE;
11297 }
11298 }")
11299
11300 (define_expand "sibcall_value"
11301 [(parallel [(set (match_operand 0 "register_operand" "")
11302 (call (mem:SI (match_operand 1 "address_operand" ""))
11303 (match_operand 2 "" "")))
11304 (use (match_operand 3 "" ""))
11305 (simple_return)])]
11306 ""
11307 "
11308 {
11309 #if TARGET_MACHO
11310 if (MACHOPIC_INDIRECT)
11311 operands[1] = machopic_indirect_call_target (operands[1]);
11312 #endif
11313
11314 gcc_assert (GET_CODE (operands[1]) == MEM);
11315 gcc_assert (GET_CODE (operands[2]) == CONST_INT);
11316
11317 operands[1] = XEXP (operands[1], 0);
11318
11319 if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
11320 {
11321 rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]);
11322 DONE;
11323 }
11324 }")
11325
11326 (define_insn "*sibcall_local32"
11327 [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
11328 (match_operand 1 "" "g,g"))
11329 (use (match_operand:SI 2 "immediate_operand" "O,n"))
11330 (simple_return)]
11331 "(INTVAL (operands[2]) & CALL_LONG) == 0"
11332 "*
11333 {
11334 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
11335 output_asm_insn (\"crxor 6,6,6\", operands);
11336
11337 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
11338 output_asm_insn (\"creqv 6,6,6\", operands);
11339
11340 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\";
11341 }"
11342 [(set_attr "type" "branch")
11343 (set_attr "length" "4,8")])
11344
11345 (define_insn "*sibcall_local64"
11346 [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
11347 (match_operand 1 "" "g,g"))
11348 (use (match_operand:SI 2 "immediate_operand" "O,n"))
11349 (simple_return)]
11350 "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
11351 "*
11352 {
11353 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
11354 output_asm_insn (\"crxor 6,6,6\", operands);
11355
11356 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
11357 output_asm_insn (\"creqv 6,6,6\", operands);
11358
11359 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\";
11360 }"
11361 [(set_attr "type" "branch")
11362 (set_attr "length" "4,8")])
11363
11364 (define_insn "*sibcall_value_local32"
11365 [(set (match_operand 0 "" "")
11366 (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
11367 (match_operand 2 "" "g,g")))
11368 (use (match_operand:SI 3 "immediate_operand" "O,n"))
11369 (simple_return)]
11370 "(INTVAL (operands[3]) & CALL_LONG) == 0"
11371 "*
11372 {
11373 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
11374 output_asm_insn (\"crxor 6,6,6\", operands);
11375
11376 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
11377 output_asm_insn (\"creqv 6,6,6\", operands);
11378
11379 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\";
11380 }"
11381 [(set_attr "type" "branch")
11382 (set_attr "length" "4,8")])
11383
11384 (define_insn "*sibcall_value_local64"
11385 [(set (match_operand 0 "" "")
11386 (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
11387 (match_operand 2 "" "g,g")))
11388 (use (match_operand:SI 3 "immediate_operand" "O,n"))
11389 (simple_return)]
11390 "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
11391 "*
11392 {
11393 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
11394 output_asm_insn (\"crxor 6,6,6\", operands);
11395
11396 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
11397 output_asm_insn (\"creqv 6,6,6\", operands);
11398
11399 return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\";
11400 }"
11401 [(set_attr "type" "branch")
11402 (set_attr "length" "4,8")])
11403
11404 (define_insn "*sibcall_nonlocal_sysv<mode>"
11405 [(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
11406 (match_operand 1 "" ""))
11407 (use (match_operand 2 "immediate_operand" "O,n,O,n"))
11408 (simple_return)]
11409 "(DEFAULT_ABI == ABI_DARWIN
11410 || DEFAULT_ABI == ABI_V4)
11411 && (INTVAL (operands[2]) & CALL_LONG) == 0"
11412 "*
11413 {
11414 if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
11415 output_asm_insn (\"crxor 6,6,6\", operands);
11416
11417 else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
11418 output_asm_insn (\"creqv 6,6,6\", operands);
11419
11420 if (which_alternative >= 2)
11421 return \"b%T0\";
11422 else if (DEFAULT_ABI == ABI_V4 && flag_pic)
11423 {
11424 gcc_assert (!TARGET_SECURE_PLT);
11425 return \"b %z0@plt\";
11426 }
11427 else
11428 return \"b %z0\";
11429 }"
11430 [(set_attr "type" "branch")
11431 (set_attr "length" "4,8,4,8")])
11432
11433 (define_insn "*sibcall_value_nonlocal_sysv<mode>"
11434 [(set (match_operand 0 "" "")
11435 (call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
11436 (match_operand 2 "" "")))
11437 (use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
11438 (simple_return)]
11439 "(DEFAULT_ABI == ABI_DARWIN
11440 || DEFAULT_ABI == ABI_V4)
11441 && (INTVAL (operands[3]) & CALL_LONG) == 0"
11442 "*
11443 {
11444 if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
11445 output_asm_insn (\"crxor 6,6,6\", operands);
11446
11447 else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
11448 output_asm_insn (\"creqv 6,6,6\", operands);
11449
11450 if (which_alternative >= 2)
11451 return \"b%T1\";
11452 else if (DEFAULT_ABI == ABI_V4 && flag_pic)
11453 {
11454 gcc_assert (!TARGET_SECURE_PLT);
11455 return \"b %z1@plt\";
11456 }
11457 else
11458 return \"b %z1\";
11459 }"
11460 [(set_attr "type" "branch")
11461 (set_attr "length" "4,8,4,8")])
11462
11463 ;; AIX ABI sibling call patterns.
11464
11465 (define_insn "*sibcall_aix<mode>"
11466 [(call (mem:SI (match_operand:P 0 "call_operand" "s,c"))
11467 (match_operand 1 "" "g,g"))
11468 (simple_return)]
11469 "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
11470 "@
11471 b %z0
11472 b%T0"
11473 [(set_attr "type" "branch")
11474 (set_attr "length" "4")])
11475
11476 (define_insn "*sibcall_value_aix<mode>"
11477 [(set (match_operand 0 "" "")
11478 (call (mem:SI (match_operand:P 1 "call_operand" "s,c"))
11479 (match_operand 2 "" "g,g")))
11480 (simple_return)]
11481 "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
11482 "@
11483 b %z1
11484 b%T1"
11485 [(set_attr "type" "branch")
11486 (set_attr "length" "4")])
11487
11488 (define_expand "sibcall_epilogue"
11489 [(use (const_int 0))]
11490 ""
11491 {
11492 if (!TARGET_SCHED_PROLOG)
11493 emit_insn (gen_blockage ());
11494 rs6000_emit_epilogue (TRUE);
11495 DONE;
11496 })
11497
11498 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
11499 ;; all of memory. This blocks insns from being moved across this point.
11500
11501 (define_insn "blockage"
11502 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCK)]
11503 ""
11504 "")
11505
11506 (define_expand "probe_stack_address"
11507 [(use (match_operand 0 "address_operand"))]
11508 ""
11509 {
11510 operands[0] = gen_rtx_MEM (Pmode, operands[0]);
11511 MEM_VOLATILE_P (operands[0]) = 1;
11512
11513 if (TARGET_64BIT)
11514 emit_insn (gen_probe_stack_di (operands[0]));
11515 else
11516 emit_insn (gen_probe_stack_si (operands[0]));
11517 DONE;
11518 })
11519
11520 (define_insn "probe_stack_<mode>"
11521 [(set (match_operand:P 0 "memory_operand" "=m")
11522 (unspec:P [(const_int 0)] UNSPEC_PROBE_STACK))]
11523 ""
11524 {
11525 operands[1] = gen_rtx_REG (Pmode, 0);
11526 return "st<wd>%U0%X0 %1,%0";
11527 }
11528 [(set_attr "type" "store")
11529 (set (attr "update")
11530 (if_then_else (match_operand 0 "update_address_mem")
11531 (const_string "yes")
11532 (const_string "no")))
11533 (set (attr "indexed")
11534 (if_then_else (match_operand 0 "indexed_address_mem")
11535 (const_string "yes")
11536 (const_string "no")))
11537 (set_attr "length" "4")])
11538
11539 (define_insn "probe_stack_range<P:mode>"
11540 [(set (match_operand:P 0 "register_operand" "=r")
11541 (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
11542 (match_operand:P 2 "register_operand" "r")]
11543 UNSPECV_PROBE_STACK_RANGE))]
11544 ""
11545 "* return output_probe_stack_range (operands[0], operands[2]);"
11546 [(set_attr "type" "three")])
11547 \f
11548 ;; Compare insns are next. Note that the RS/6000 has two types of compares,
11549 ;; signed & unsigned, and one type of branch.
11550 ;;
11551 ;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
11552 ;; insns, and branches.
11553
11554 (define_expand "cbranch<mode>4"
11555 [(use (match_operator 0 "rs6000_cbranch_operator"
11556 [(match_operand:GPR 1 "gpc_reg_operand" "")
11557 (match_operand:GPR 2 "reg_or_short_operand" "")]))
11558 (use (match_operand 3 ""))]
11559 ""
11560 "
11561 {
11562 /* Take care of the possibility that operands[2] might be negative but
11563 this might be a logical operation. That insn doesn't exist. */
11564 if (GET_CODE (operands[2]) == CONST_INT
11565 && INTVAL (operands[2]) < 0)
11566 {
11567 operands[2] = force_reg (<MODE>mode, operands[2]);
11568 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
11569 GET_MODE (operands[0]),
11570 operands[1], operands[2]);
11571 }
11572
11573 rs6000_emit_cbranch (<MODE>mode, operands);
11574 DONE;
11575 }")
11576
11577 (define_expand "cbranch<mode>4"
11578 [(use (match_operator 0 "rs6000_cbranch_operator"
11579 [(match_operand:FP 1 "gpc_reg_operand" "")
11580 (match_operand:FP 2 "gpc_reg_operand" "")]))
11581 (use (match_operand 3 ""))]
11582 ""
11583 "
11584 {
11585 rs6000_emit_cbranch (<MODE>mode, operands);
11586 DONE;
11587 }")
11588
11589 (define_expand "cstore<mode>4_signed"
11590 [(use (match_operator 1 "signed_comparison_operator"
11591 [(match_operand:P 2 "gpc_reg_operand")
11592 (match_operand:P 3 "gpc_reg_operand")]))
11593 (clobber (match_operand:P 0 "gpc_reg_operand"))]
11594 ""
11595 {
11596 enum rtx_code cond_code = GET_CODE (operands[1]);
11597
11598 rtx op0 = operands[0];
11599 rtx op1 = operands[2];
11600 rtx op2 = operands[3];
11601
11602 if (cond_code == GE || cond_code == LT)
11603 {
11604 cond_code = swap_condition (cond_code);
11605 std::swap (op1, op2);
11606 }
11607
11608 rtx tmp1 = gen_reg_rtx (<MODE>mode);
11609 rtx tmp2 = gen_reg_rtx (<MODE>mode);
11610 rtx tmp3 = gen_reg_rtx (<MODE>mode);
11611
11612 int sh = GET_MODE_BITSIZE (<MODE>mode) - 1;
11613 emit_insn (gen_lshr<mode>3 (tmp1, op1, GEN_INT (sh)));
11614 emit_insn (gen_ashr<mode>3 (tmp2, op2, GEN_INT (sh)));
11615
11616 emit_insn (gen_subf<mode>3_carry (tmp3, op1, op2));
11617
11618 if (cond_code == LE)
11619 emit_insn (gen_add<mode>3_carry_in (op0, tmp1, tmp2));
11620 else
11621 {
11622 rtx tmp4 = gen_reg_rtx (<MODE>mode);
11623 emit_insn (gen_add<mode>3_carry_in (tmp4, tmp1, tmp2));
11624 emit_insn (gen_xor<mode>3 (op0, tmp4, const1_rtx));
11625 }
11626
11627 DONE;
11628 })
11629
11630 (define_expand "cstore<mode>4_unsigned"
11631 [(use (match_operator 1 "unsigned_comparison_operator"
11632 [(match_operand:P 2 "gpc_reg_operand")
11633 (match_operand:P 3 "reg_or_short_operand")]))
11634 (clobber (match_operand:P 0 "gpc_reg_operand"))]
11635 ""
11636 {
11637 enum rtx_code cond_code = GET_CODE (operands[1]);
11638
11639 rtx op0 = operands[0];
11640 rtx op1 = operands[2];
11641 rtx op2 = operands[3];
11642
11643 if (cond_code == GEU || cond_code == LTU)
11644 {
11645 cond_code = swap_condition (cond_code);
11646 std::swap (op1, op2);
11647 }
11648
11649 if (!gpc_reg_operand (op1, <MODE>mode))
11650 op1 = force_reg (<MODE>mode, op1);
11651 if (!reg_or_short_operand (op2, <MODE>mode))
11652 op2 = force_reg (<MODE>mode, op2);
11653
11654 rtx tmp = gen_reg_rtx (<MODE>mode);
11655 rtx tmp2 = gen_reg_rtx (<MODE>mode);
11656
11657 emit_insn (gen_subf<mode>3_carry (tmp, op1, op2));
11658 emit_insn (gen_subf<mode>3_carry_in_xx (tmp2));
11659
11660 if (cond_code == LEU)
11661 emit_insn (gen_add<mode>3 (op0, tmp2, const1_rtx));
11662 else
11663 emit_insn (gen_neg<mode>2 (op0, tmp2));
11664
11665 DONE;
11666 })
11667
11668 (define_expand "cstore_si_as_di"
11669 [(use (match_operator 1 "unsigned_comparison_operator"
11670 [(match_operand:SI 2 "gpc_reg_operand")
11671 (match_operand:SI 3 "reg_or_short_operand")]))
11672 (clobber (match_operand:SI 0 "gpc_reg_operand"))]
11673 ""
11674 {
11675 int uns_flag = unsigned_comparison_operator (operands[1], VOIDmode) ? 1 : 0;
11676 enum rtx_code cond_code = signed_condition (GET_CODE (operands[1]));
11677
11678 operands[2] = force_reg (SImode, operands[2]);
11679 operands[3] = force_reg (SImode, operands[3]);
11680 rtx op1 = gen_reg_rtx (DImode);
11681 rtx op2 = gen_reg_rtx (DImode);
11682 convert_move (op1, operands[2], uns_flag);
11683 convert_move (op2, operands[3], uns_flag);
11684
11685 if (cond_code == GT || cond_code == LE)
11686 {
11687 cond_code = swap_condition (cond_code);
11688 std::swap (op1, op2);
11689 }
11690
11691 rtx tmp = gen_reg_rtx (DImode);
11692 rtx tmp2 = gen_reg_rtx (DImode);
11693 emit_insn (gen_subdi3 (tmp, op1, op2));
11694 emit_insn (gen_lshrdi3 (tmp2, tmp, GEN_INT (63)));
11695
11696 rtx tmp3;
11697 switch (cond_code)
11698 {
11699 default:
11700 gcc_unreachable ();
11701 case LT:
11702 tmp3 = tmp2;
11703 break;
11704 case GE:
11705 tmp3 = gen_reg_rtx (DImode);
11706 emit_insn (gen_xordi3 (tmp3, tmp2, const1_rtx));
11707 break;
11708 }
11709
11710 convert_move (operands[0], tmp3, 1);
11711
11712 DONE;
11713 })
11714
11715 (define_expand "cstore<mode>4_signed_imm"
11716 [(use (match_operator 1 "signed_comparison_operator"
11717 [(match_operand:GPR 2 "gpc_reg_operand")
11718 (match_operand:GPR 3 "immediate_operand")]))
11719 (clobber (match_operand:GPR 0 "gpc_reg_operand"))]
11720 ""
11721 {
11722 bool invert = false;
11723
11724 enum rtx_code cond_code = GET_CODE (operands[1]);
11725
11726 rtx op0 = operands[0];
11727 rtx op1 = operands[2];
11728 HOST_WIDE_INT val = INTVAL (operands[3]);
11729
11730 if (cond_code == GE || cond_code == GT)
11731 {
11732 cond_code = reverse_condition (cond_code);
11733 invert = true;
11734 }
11735
11736 if (cond_code == LE)
11737 val++;
11738
11739 rtx tmp = gen_reg_rtx (<MODE>mode);
11740 emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (-val)));
11741 rtx x = gen_reg_rtx (<MODE>mode);
11742 if (val < 0)
11743 emit_insn (gen_and<mode>3 (x, op1, tmp));
11744 else
11745 emit_insn (gen_ior<mode>3 (x, op1, tmp));
11746
11747 if (invert)
11748 {
11749 rtx tmp = gen_reg_rtx (<MODE>mode);
11750 emit_insn (gen_one_cmpl<mode>2 (tmp, x));
11751 x = tmp;
11752 }
11753
11754 int sh = GET_MODE_BITSIZE (<MODE>mode) - 1;
11755 emit_insn (gen_lshr<mode>3 (op0, x, GEN_INT (sh)));
11756
11757 DONE;
11758 })
11759
11760 (define_expand "cstore<mode>4_unsigned_imm"
11761 [(use (match_operator 1 "unsigned_comparison_operator"
11762 [(match_operand:GPR 2 "gpc_reg_operand")
11763 (match_operand:GPR 3 "immediate_operand")]))
11764 (clobber (match_operand:GPR 0 "gpc_reg_operand"))]
11765 ""
11766 {
11767 bool invert = false;
11768
11769 enum rtx_code cond_code = GET_CODE (operands[1]);
11770
11771 rtx op0 = operands[0];
11772 rtx op1 = operands[2];
11773 HOST_WIDE_INT val = INTVAL (operands[3]);
11774
11775 if (cond_code == GEU || cond_code == GTU)
11776 {
11777 cond_code = reverse_condition (cond_code);
11778 invert = true;
11779 }
11780
11781 if (cond_code == LEU)
11782 val++;
11783
11784 rtx tmp = gen_reg_rtx (<MODE>mode);
11785 rtx tmp2 = gen_reg_rtx (<MODE>mode);
11786 emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (-val)));
11787 emit_insn (gen_one_cmpl<mode>2 (tmp2, op1));
11788 rtx x = gen_reg_rtx (<MODE>mode);
11789 if (val < 0)
11790 emit_insn (gen_ior<mode>3 (x, tmp, tmp2));
11791 else
11792 emit_insn (gen_and<mode>3 (x, tmp, tmp2));
11793
11794 if (invert)
11795 {
11796 rtx tmp = gen_reg_rtx (<MODE>mode);
11797 emit_insn (gen_one_cmpl<mode>2 (tmp, x));
11798 x = tmp;
11799 }
11800
11801 int sh = GET_MODE_BITSIZE (<MODE>mode) - 1;
11802 emit_insn (gen_lshr<mode>3 (op0, x, GEN_INT (sh)));
11803
11804 DONE;
11805 })
11806
11807 (define_expand "cstore<mode>4"
11808 [(use (match_operator 1 "rs6000_cbranch_operator"
11809 [(match_operand:GPR 2 "gpc_reg_operand")
11810 (match_operand:GPR 3 "reg_or_short_operand")]))
11811 (clobber (match_operand:GPR 0 "gpc_reg_operand"))]
11812 ""
11813 {
11814 /* Use ISEL if the user asked for it. */
11815 if (TARGET_ISEL)
11816 rs6000_emit_sISEL (<MODE>mode, operands);
11817
11818 /* Expanding EQ and NE directly to some machine instructions does not help
11819 but does hurt combine. So don't. */
11820 else if (GET_CODE (operands[1]) == EQ)
11821 emit_insn (gen_eq<mode>3 (operands[0], operands[2], operands[3]));
11822 else if (<MODE>mode == Pmode
11823 && GET_CODE (operands[1]) == NE)
11824 emit_insn (gen_ne<mode>3 (operands[0], operands[2], operands[3]));
11825 else if (GET_CODE (operands[1]) == NE)
11826 {
11827 rtx tmp = gen_reg_rtx (<MODE>mode);
11828 emit_insn (gen_eq<mode>3 (tmp, operands[2], operands[3]));
11829 emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx));
11830 }
11831
11832 /* Expanding the unsigned comparisons however helps a lot: all the neg_ltu
11833 etc. combinations magically work out just right. */
11834 else if (<MODE>mode == Pmode
11835 && unsigned_comparison_operator (operands[1], VOIDmode))
11836 emit_insn (gen_cstore<mode>4_unsigned (operands[0], operands[1],
11837 operands[2], operands[3]));
11838
11839 /* For comparisons smaller than Pmode we can cheaply do things in Pmode. */
11840 else if (<MODE>mode == SImode && Pmode == DImode)
11841 emit_insn (gen_cstore_si_as_di (operands[0], operands[1],
11842 operands[2], operands[3]));
11843
11844 /* For signed comparisons against a constant, we can do some simple
11845 bit-twiddling. */
11846 else if (signed_comparison_operator (operands[1], VOIDmode)
11847 && CONST_INT_P (operands[3]))
11848 emit_insn (gen_cstore<mode>4_signed_imm (operands[0], operands[1],
11849 operands[2], operands[3]));
11850
11851 /* And similarly for unsigned comparisons. */
11852 else if (unsigned_comparison_operator (operands[1], VOIDmode)
11853 && CONST_INT_P (operands[3]))
11854 emit_insn (gen_cstore<mode>4_unsigned_imm (operands[0], operands[1],
11855 operands[2], operands[3]));
11856
11857 /* We also do not want to use mfcr for signed comparisons. */
11858 else if (<MODE>mode == Pmode
11859 && signed_comparison_operator (operands[1], VOIDmode))
11860 emit_insn (gen_cstore<mode>4_signed (operands[0], operands[1],
11861 operands[2], operands[3]));
11862
11863 /* Everything else, use the mfcr brute force. */
11864 else
11865 rs6000_emit_sCOND (<MODE>mode, operands);
11866
11867 DONE;
11868 })
11869
11870 (define_expand "cstore<mode>4"
11871 [(use (match_operator 1 "rs6000_cbranch_operator"
11872 [(match_operand:FP 2 "gpc_reg_operand")
11873 (match_operand:FP 3 "gpc_reg_operand")]))
11874 (clobber (match_operand:SI 0 "gpc_reg_operand"))]
11875 ""
11876 {
11877 rs6000_emit_sCOND (<MODE>mode, operands);
11878 DONE;
11879 })
11880
11881
11882 (define_expand "stack_protect_set"
11883 [(match_operand 0 "memory_operand")
11884 (match_operand 1 "memory_operand")]
11885 ""
11886 {
11887 if (rs6000_stack_protector_guard == SSP_TLS)
11888 {
11889 rtx reg = gen_rtx_REG (Pmode, rs6000_stack_protector_guard_reg);
11890 rtx offset = GEN_INT (rs6000_stack_protector_guard_offset);
11891 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
11892 operands[1] = gen_rtx_MEM (Pmode, addr);
11893 }
11894
11895 if (TARGET_64BIT)
11896 emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
11897 else
11898 emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
11899
11900 DONE;
11901 })
11902
11903 (define_insn "stack_protect_setsi"
11904 [(set (match_operand:SI 0 "memory_operand" "=m")
11905 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
11906 (set (match_scratch:SI 2 "=&r") (const_int 0))]
11907 "TARGET_32BIT"
11908 "lwz%U1%X1 %2,%1\;stw%U0%X0 %2,%0\;li %2,0"
11909 [(set_attr "type" "three")
11910 (set_attr "length" "12")])
11911
11912 (define_insn "stack_protect_setdi"
11913 [(set (match_operand:DI 0 "memory_operand" "=Y")
11914 (unspec:DI [(match_operand:DI 1 "memory_operand" "Y")] UNSPEC_SP_SET))
11915 (set (match_scratch:DI 2 "=&r") (const_int 0))]
11916 "TARGET_64BIT"
11917 "ld%U1%X1 %2,%1\;std%U0%X0 %2,%0\;li %2,0"
11918 [(set_attr "type" "three")
11919 (set_attr "length" "12")])
11920
11921 (define_expand "stack_protect_test"
11922 [(match_operand 0 "memory_operand")
11923 (match_operand 1 "memory_operand")
11924 (match_operand 2 "")]
11925 ""
11926 {
11927 rtx guard = operands[1];
11928
11929 if (rs6000_stack_protector_guard == SSP_TLS)
11930 {
11931 rtx reg = gen_rtx_REG (Pmode, rs6000_stack_protector_guard_reg);
11932 rtx offset = GEN_INT (rs6000_stack_protector_guard_offset);
11933 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
11934 guard = gen_rtx_MEM (Pmode, addr);
11935 }
11936
11937 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, guard), UNSPEC_SP_TEST);
11938 rtx test = gen_rtx_EQ (VOIDmode, operands[0], operands[1]);
11939 rtx jump = gen_cbranchsi4 (test, operands[0], operands[1], operands[2]);
11940 emit_jump_insn (jump);
11941
11942 DONE;
11943 })
11944
11945 (define_insn "stack_protect_testsi"
11946 [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
11947 (unspec:CCEQ [(match_operand:SI 1 "memory_operand" "m,m")
11948 (match_operand:SI 2 "memory_operand" "m,m")]
11949 UNSPEC_SP_TEST))
11950 (set (match_scratch:SI 4 "=r,r") (const_int 0))
11951 (clobber (match_scratch:SI 3 "=&r,&r"))]
11952 "TARGET_32BIT"
11953 "@
11954 lwz%U1%X1 %3,%1\;lwz%U2%X2 %4,%2\;xor. %3,%3,%4\;li %4,0
11955 lwz%U1%X1 %3,%1\;lwz%U2%X2 %4,%2\;cmplw %0,%3,%4\;li %3,0\;li %4,0"
11956 [(set_attr "length" "16,20")])
11957
11958 (define_insn "stack_protect_testdi"
11959 [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
11960 (unspec:CCEQ [(match_operand:DI 1 "memory_operand" "Y,Y")
11961 (match_operand:DI 2 "memory_operand" "Y,Y")]
11962 UNSPEC_SP_TEST))
11963 (set (match_scratch:DI 4 "=r,r") (const_int 0))
11964 (clobber (match_scratch:DI 3 "=&r,&r"))]
11965 "TARGET_64BIT"
11966 "@
11967 ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;xor. %3,%3,%4\;li %4,0
11968 ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;cmpld %0,%3,%4\;li %3,0\;li %4,0"
11969 [(set_attr "length" "16,20")])
11970
11971 \f
11972 ;; Here are the actual compare insns.
11973 (define_insn "*cmp<mode>_signed"
11974 [(set (match_operand:CC 0 "cc_reg_operand" "=y")
11975 (compare:CC (match_operand:GPR 1 "gpc_reg_operand" "r")
11976 (match_operand:GPR 2 "reg_or_short_operand" "rI")))]
11977 ""
11978 "cmp<wd>%I2 %0,%1,%2"
11979 [(set_attr "type" "cmp")])
11980
11981 (define_insn "*cmp<mode>_unsigned"
11982 [(set (match_operand:CCUNS 0 "cc_reg_operand" "=y")
11983 (compare:CCUNS (match_operand:GPR 1 "gpc_reg_operand" "r")
11984 (match_operand:GPR 2 "reg_or_u_short_operand" "rK")))]
11985 ""
11986 "cmpl<wd>%I2 %0,%1,%2"
11987 [(set_attr "type" "cmp")])
11988
11989 ;; If we are comparing a register for equality with a large constant,
11990 ;; we can do this with an XOR followed by a compare. But this is profitable
11991 ;; only if the large constant is only used for the comparison (and in this
11992 ;; case we already have a register to reuse as scratch).
11993 ;;
11994 ;; For 64-bit registers, we could only do so if the constant's bit 15 is clear:
11995 ;; otherwise we'd need to XOR with FFFFFFFF????0000 which is not available.
11996
11997 (define_peephole2
11998 [(set (match_operand:SI 0 "register_operand")
11999 (match_operand:SI 1 "logical_const_operand" ""))
12000 (set (match_dup 0) (match_operator:SI 3 "boolean_or_operator"
12001 [(match_dup 0)
12002 (match_operand:SI 2 "logical_const_operand" "")]))
12003 (set (match_operand:CC 4 "cc_reg_operand" "")
12004 (compare:CC (match_operand:SI 5 "gpc_reg_operand" "")
12005 (match_dup 0)))
12006 (set (pc)
12007 (if_then_else (match_operator 6 "equality_operator"
12008 [(match_dup 4) (const_int 0)])
12009 (match_operand 7 "" "")
12010 (match_operand 8 "" "")))]
12011 "peep2_reg_dead_p (3, operands[0])
12012 && peep2_reg_dead_p (4, operands[4])
12013 && REGNO (operands[0]) != REGNO (operands[5])"
12014 [(set (match_dup 0) (xor:SI (match_dup 5) (match_dup 9)))
12015 (set (match_dup 4) (compare:CC (match_dup 0) (match_dup 10)))
12016 (set (pc) (if_then_else (match_dup 6) (match_dup 7) (match_dup 8)))]
12017
12018 {
12019 /* Get the constant we are comparing against, and see what it looks like
12020 when sign-extended from 16 to 32 bits. Then see what constant we could
12021 XOR with SEXTC to get the sign-extended value. */
12022 rtx cnst = simplify_const_binary_operation (GET_CODE (operands[3]),
12023 SImode,
12024 operands[1], operands[2]);
12025 HOST_WIDE_INT c = INTVAL (cnst);
12026 HOST_WIDE_INT sextc = ((c & 0xffff) ^ 0x8000) - 0x8000;
12027 HOST_WIDE_INT xorv = c ^ sextc;
12028
12029 operands[9] = GEN_INT (xorv);
12030 operands[10] = GEN_INT (sextc);
12031 })
12032
12033 ;; The following two insns don't exist as single insns, but if we provide
12034 ;; them, we can swap an add and compare, which will enable us to overlap more
12035 ;; of the required delay between a compare and branch. We generate code for
12036 ;; them by splitting.
12037
12038 (define_insn ""
12039 [(set (match_operand:CC 3 "cc_reg_operand" "=y")
12040 (compare:CC (match_operand:SI 1 "gpc_reg_operand" "r")
12041 (match_operand:SI 2 "short_cint_operand" "i")))
12042 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
12043 (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "i")))]
12044 ""
12045 "#"
12046 [(set_attr "length" "8")])
12047
12048 (define_insn ""
12049 [(set (match_operand:CCUNS 3 "cc_reg_operand" "=y")
12050 (compare:CCUNS (match_operand:SI 1 "gpc_reg_operand" "r")
12051 (match_operand:SI 2 "u_short_cint_operand" "i")))
12052 (set (match_operand:SI 0 "gpc_reg_operand" "=r")
12053 (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "i")))]
12054 ""
12055 "#"
12056 [(set_attr "length" "8")])
12057
12058 (define_split
12059 [(set (match_operand:CC 3 "cc_reg_operand" "")
12060 (compare:CC (match_operand:SI 1 "gpc_reg_operand" "")
12061 (match_operand:SI 2 "short_cint_operand" "")))
12062 (set (match_operand:SI 0 "gpc_reg_operand" "")
12063 (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "")))]
12064 ""
12065 [(set (match_dup 3) (compare:CC (match_dup 1) (match_dup 2)))
12066 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
12067
12068 (define_split
12069 [(set (match_operand:CCUNS 3 "cc_reg_operand" "")
12070 (compare:CCUNS (match_operand:SI 1 "gpc_reg_operand" "")
12071 (match_operand:SI 2 "u_short_cint_operand" "")))
12072 (set (match_operand:SI 0 "gpc_reg_operand" "")
12073 (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "")))]
12074 ""
12075 [(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2)))
12076 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
12077
12078 ;; Only need to compare second words if first words equal
12079 (define_insn "*cmp<mode>_internal1"
12080 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
12081 (compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
12082 (match_operand:IBM128 2 "gpc_reg_operand" "d")))]
12083 "!TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode)
12084 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
12085 "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
12086 [(set_attr "type" "fpcompare")
12087 (set_attr "length" "12")])
12088
12089 (define_insn_and_split "*cmp<mode>_internal2"
12090 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
12091 (compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
12092 (match_operand:IBM128 2 "gpc_reg_operand" "d")))
12093 (clobber (match_scratch:DF 3 "=d"))
12094 (clobber (match_scratch:DF 4 "=d"))
12095 (clobber (match_scratch:DF 5 "=d"))
12096 (clobber (match_scratch:DF 6 "=d"))
12097 (clobber (match_scratch:DF 7 "=d"))
12098 (clobber (match_scratch:DF 8 "=d"))
12099 (clobber (match_scratch:DF 9 "=d"))
12100 (clobber (match_scratch:DF 10 "=d"))
12101 (clobber (match_scratch:GPR 11 "=b"))]
12102 "TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode)
12103 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
12104 "#"
12105 "&& reload_completed"
12106 [(set (match_dup 3) (match_dup 14))
12107 (set (match_dup 4) (match_dup 15))
12108 (set (match_dup 9) (abs:DF (match_dup 5)))
12109 (set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 3)))
12110 (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
12111 (label_ref (match_dup 12))
12112 (pc)))
12113 (set (match_dup 0) (compare:CCFP (match_dup 5) (match_dup 7)))
12114 (set (pc) (label_ref (match_dup 13)))
12115 (match_dup 12)
12116 (set (match_dup 10) (minus:DF (match_dup 5) (match_dup 7)))
12117 (set (match_dup 9) (minus:DF (match_dup 6) (match_dup 8)))
12118 (set (match_dup 9) (plus:DF (match_dup 10) (match_dup 9)))
12119 (set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 4)))
12120 (match_dup 13)]
12121 {
12122 REAL_VALUE_TYPE rv;
12123 const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
12124 const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
12125
12126 operands[5] = simplify_gen_subreg (DFmode, operands[1], <MODE>mode, hi_word);
12127 operands[6] = simplify_gen_subreg (DFmode, operands[1], <MODE>mode, lo_word);
12128 operands[7] = simplify_gen_subreg (DFmode, operands[2], <MODE>mode, hi_word);
12129 operands[8] = simplify_gen_subreg (DFmode, operands[2], <MODE>mode, lo_word);
12130 operands[12] = gen_label_rtx ();
12131 operands[13] = gen_label_rtx ();
12132 real_inf (&rv);
12133 operands[14] = force_const_mem (DFmode,
12134 const_double_from_real_value (rv, DFmode));
12135 operands[15] = force_const_mem (DFmode,
12136 const_double_from_real_value (dconst0,
12137 DFmode));
12138 if (TARGET_TOC)
12139 {
12140 rtx tocref;
12141 tocref = create_TOC_reference (XEXP (operands[14], 0), operands[11]);
12142 operands[14] = gen_const_mem (DFmode, tocref);
12143 tocref = create_TOC_reference (XEXP (operands[15], 0), operands[11]);
12144 operands[15] = gen_const_mem (DFmode, tocref);
12145 set_mem_alias_set (operands[14], get_TOC_alias_set ());
12146 set_mem_alias_set (operands[15], get_TOC_alias_set ());
12147 }
12148 })
12149 \f
12150 ;; Now we have the scc insns. We can do some combinations because of the
12151 ;; way the machine works.
12152 ;;
12153 ;; Note that this is probably faster if we can put an insn between the
12154 ;; mfcr and rlinm, but this is tricky. Let's leave it for now. In most
12155 ;; cases the insns below which don't use an intermediate CR field will
12156 ;; be used instead.
12157 (define_insn ""
12158 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
12159 (match_operator:SI 1 "scc_comparison_operator"
12160 [(match_operand 2 "cc_reg_operand" "y")
12161 (const_int 0)]))]
12162 ""
12163 "mfcr %0%Q2\;rlwinm %0,%0,%J1,1"
12164 [(set (attr "type")
12165 (cond [(match_test "TARGET_MFCRF")
12166 (const_string "mfcrf")
12167 ]
12168 (const_string "mfcr")))
12169 (set_attr "length" "8")])
12170
12171 ;; Same as above, but get the GT bit.
12172 (define_insn "move_from_CR_gt_bit"
12173 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
12174 (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))]
12175 "TARGET_HARD_FLOAT && !TARGET_FPRS"
12176 "mfcr %0\;rlwinm %0,%0,%D1,31,31"
12177 [(set_attr "type" "mfcr")
12178 (set_attr "length" "8")])
12179
12180 ;; Same as above, but get the OV/ORDERED bit.
12181 (define_insn "move_from_CR_ov_bit"
12182 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
12183 (unspec:SI [(match_operand:CC 1 "cc_reg_operand" "y")]
12184 UNSPEC_MV_CR_OV))]
12185 "TARGET_ISEL"
12186 "mfcr %0\;rlwinm %0,%0,%t1,1"
12187 [(set_attr "type" "mfcr")
12188 (set_attr "length" "8")])
12189
12190 (define_insn ""
12191 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
12192 (match_operator:DI 1 "scc_comparison_operator"
12193 [(match_operand 2 "cc_reg_operand" "y")
12194 (const_int 0)]))]
12195 "TARGET_POWERPC64"
12196 "mfcr %0%Q2\;rlwinm %0,%0,%J1,1"
12197 [(set (attr "type")
12198 (cond [(match_test "TARGET_MFCRF")
12199 (const_string "mfcrf")
12200 ]
12201 (const_string "mfcr")))
12202 (set_attr "length" "8")])
12203
12204 (define_insn ""
12205 [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
12206 (compare:CC (match_operator:SI 1 "scc_comparison_operator"
12207 [(match_operand 2 "cc_reg_operand" "y,y")
12208 (const_int 0)])
12209 (const_int 0)))
12210 (set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
12211 (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
12212 "TARGET_32BIT"
12213 "@
12214 mfcr %3%Q2\;rlwinm. %3,%3,%J1,1
12215 #"
12216 [(set_attr "type" "shift")
12217 (set_attr "dot" "yes")
12218 (set_attr "length" "8,16")])
12219
12220 (define_split
12221 [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
12222 (compare:CC (match_operator:SI 1 "scc_comparison_operator"
12223 [(match_operand 2 "cc_reg_operand" "")
12224 (const_int 0)])
12225 (const_int 0)))
12226 (set (match_operand:SI 3 "gpc_reg_operand" "")
12227 (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
12228 "TARGET_32BIT && reload_completed"
12229 [(set (match_dup 3)
12230 (match_op_dup 1 [(match_dup 2) (const_int 0)]))
12231 (set (match_dup 0)
12232 (compare:CC (match_dup 3)
12233 (const_int 0)))]
12234 "")
12235
12236 (define_insn ""
12237 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
12238 (ashift:SI (match_operator:SI 1 "scc_comparison_operator"
12239 [(match_operand 2 "cc_reg_operand" "y")
12240 (const_int 0)])
12241 (match_operand:SI 3 "const_int_operand" "n")))]
12242 ""
12243 "*
12244 {
12245 int is_bit = ccr_bit (operands[1], 1);
12246 int put_bit = 31 - (INTVAL (operands[3]) & 31);
12247 int count;
12248
12249 if (is_bit >= put_bit)
12250 count = is_bit - put_bit;
12251 else
12252 count = 32 - (put_bit - is_bit);
12253
12254 operands[4] = GEN_INT (count);
12255 operands[5] = GEN_INT (put_bit);
12256
12257 return \"mfcr %0%Q2\;rlwinm %0,%0,%4,%5,%5\";
12258 }"
12259 [(set (attr "type")
12260 (cond [(match_test "TARGET_MFCRF")
12261 (const_string "mfcrf")
12262 ]
12263 (const_string "mfcr")))
12264 (set_attr "length" "8")])
12265
12266 (define_insn ""
12267 [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
12268 (compare:CC
12269 (ashift:SI (match_operator:SI 1 "scc_comparison_operator"
12270 [(match_operand 2 "cc_reg_operand" "y,y")
12271 (const_int 0)])
12272 (match_operand:SI 3 "const_int_operand" "n,n"))
12273 (const_int 0)))
12274 (set (match_operand:SI 4 "gpc_reg_operand" "=r,r")
12275 (ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])
12276 (match_dup 3)))]
12277 ""
12278 "*
12279 {
12280 int is_bit = ccr_bit (operands[1], 1);
12281 int put_bit = 31 - (INTVAL (operands[3]) & 31);
12282 int count;
12283
12284 /* Force split for non-cc0 compare. */
12285 if (which_alternative == 1)
12286 return \"#\";
12287
12288 if (is_bit >= put_bit)
12289 count = is_bit - put_bit;
12290 else
12291 count = 32 - (put_bit - is_bit);
12292
12293 operands[5] = GEN_INT (count);
12294 operands[6] = GEN_INT (put_bit);
12295
12296 return \"mfcr %4%Q2\;rlwinm. %4,%4,%5,%6,%6\";
12297 }"
12298 [(set_attr "type" "shift")
12299 (set_attr "dot" "yes")
12300 (set_attr "length" "8,16")])
12301
12302 (define_split
12303 [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
12304 (compare:CC
12305 (ashift:SI (match_operator:SI 1 "scc_comparison_operator"
12306 [(match_operand 2 "cc_reg_operand" "")
12307 (const_int 0)])
12308 (match_operand:SI 3 "const_int_operand" ""))
12309 (const_int 0)))
12310 (set (match_operand:SI 4 "gpc_reg_operand" "")
12311 (ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])
12312 (match_dup 3)))]
12313 "reload_completed"
12314 [(set (match_dup 4)
12315 (ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])
12316 (match_dup 3)))
12317 (set (match_dup 0)
12318 (compare:CC (match_dup 4)
12319 (const_int 0)))]
12320 "")
12321
12322
12323 (define_mode_attr scc_eq_op2 [(SI "rKLI")
12324 (DI "rKJI")])
12325
12326 (define_insn_and_split "eq<mode>3"
12327 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
12328 (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
12329 (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
12330 (clobber (match_scratch:GPR 3 "=r"))
12331 (clobber (match_scratch:GPR 4 "=r"))]
12332 ""
12333 "#"
12334 ""
12335 [(set (match_dup 4)
12336 (clz:GPR (match_dup 3)))
12337 (set (match_dup 0)
12338 (lshiftrt:GPR (match_dup 4)
12339 (match_dup 5)))]
12340 {
12341 operands[3] = rs6000_emit_eqne (<MODE>mode,
12342 operands[1], operands[2], operands[3]);
12343
12344 if (GET_CODE (operands[4]) == SCRATCH)
12345 operands[4] = gen_reg_rtx (<MODE>mode);
12346
12347 operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
12348 }
12349 [(set (attr "length")
12350 (if_then_else (match_test "operands[2] == const0_rtx")
12351 (const_string "8")
12352 (const_string "12")))])
12353
12354 (define_insn_and_split "ne<mode>3"
12355 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12356 (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
12357 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>")))
12358 (clobber (match_scratch:P 3 "=r"))
12359 (clobber (match_scratch:P 4 "=r"))
12360 (clobber (reg:P CA_REGNO))]
12361 "!TARGET_ISEL"
12362 "#"
12363 ""
12364 [(parallel [(set (match_dup 4)
12365 (plus:P (match_dup 3)
12366 (const_int -1)))
12367 (set (reg:P CA_REGNO)
12368 (ne:P (match_dup 3)
12369 (const_int 0)))])
12370 (parallel [(set (match_dup 0)
12371 (plus:P (plus:P (not:P (match_dup 4))
12372 (reg:P CA_REGNO))
12373 (match_dup 3)))
12374 (clobber (reg:P CA_REGNO))])]
12375 {
12376 operands[3] = rs6000_emit_eqne (<MODE>mode,
12377 operands[1], operands[2], operands[3]);
12378
12379 if (GET_CODE (operands[4]) == SCRATCH)
12380 operands[4] = gen_reg_rtx (<MODE>mode);
12381 }
12382 [(set (attr "length")
12383 (if_then_else (match_test "operands[2] == const0_rtx")
12384 (const_string "8")
12385 (const_string "12")))])
12386
12387 (define_insn_and_split "*neg_eq_<mode>"
12388 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12389 (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
12390 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
12391 (clobber (match_scratch:P 3 "=r"))
12392 (clobber (match_scratch:P 4 "=r"))
12393 (clobber (reg:P CA_REGNO))]
12394 ""
12395 "#"
12396 ""
12397 [(parallel [(set (match_dup 4)
12398 (plus:P (match_dup 3)
12399 (const_int -1)))
12400 (set (reg:P CA_REGNO)
12401 (ne:P (match_dup 3)
12402 (const_int 0)))])
12403 (parallel [(set (match_dup 0)
12404 (plus:P (reg:P CA_REGNO)
12405 (const_int -1)))
12406 (clobber (reg:P CA_REGNO))])]
12407 {
12408 operands[3] = rs6000_emit_eqne (<MODE>mode,
12409 operands[1], operands[2], operands[3]);
12410
12411 if (GET_CODE (operands[4]) == SCRATCH)
12412 operands[4] = gen_reg_rtx (<MODE>mode);
12413 }
12414 [(set (attr "length")
12415 (if_then_else (match_test "operands[2] == const0_rtx")
12416 (const_string "8")
12417 (const_string "12")))])
12418
12419 (define_insn_and_split "*neg_ne_<mode>"
12420 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12421 (neg:P (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
12422 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
12423 (clobber (match_scratch:P 3 "=r"))
12424 (clobber (match_scratch:P 4 "=r"))
12425 (clobber (reg:P CA_REGNO))]
12426 ""
12427 "#"
12428 ""
12429 [(parallel [(set (match_dup 4)
12430 (neg:P (match_dup 3)))
12431 (set (reg:P CA_REGNO)
12432 (eq:P (match_dup 3)
12433 (const_int 0)))])
12434 (parallel [(set (match_dup 0)
12435 (plus:P (reg:P CA_REGNO)
12436 (const_int -1)))
12437 (clobber (reg:P CA_REGNO))])]
12438 {
12439 operands[3] = rs6000_emit_eqne (<MODE>mode,
12440 operands[1], operands[2], operands[3]);
12441
12442 if (GET_CODE (operands[4]) == SCRATCH)
12443 operands[4] = gen_reg_rtx (<MODE>mode);
12444 }
12445 [(set (attr "length")
12446 (if_then_else (match_test "operands[2] == const0_rtx")
12447 (const_string "8")
12448 (const_string "12")))])
12449
12450 (define_insn_and_split "*plus_eq_<mode>"
12451 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12452 (plus:P (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
12453 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
12454 (match_operand:P 3 "gpc_reg_operand" "r")))
12455 (clobber (match_scratch:P 4 "=r"))
12456 (clobber (match_scratch:P 5 "=r"))
12457 (clobber (reg:P CA_REGNO))]
12458 ""
12459 "#"
12460 ""
12461 [(parallel [(set (match_dup 5)
12462 (neg:P (match_dup 4)))
12463 (set (reg:P CA_REGNO)
12464 (eq:P (match_dup 4)
12465 (const_int 0)))])
12466 (parallel [(set (match_dup 0)
12467 (plus:P (match_dup 3)
12468 (reg:P CA_REGNO)))
12469 (clobber (reg:P CA_REGNO))])]
12470 {
12471 operands[4] = rs6000_emit_eqne (<MODE>mode,
12472 operands[1], operands[2], operands[4]);
12473
12474 if (GET_CODE (operands[5]) == SCRATCH)
12475 operands[5] = gen_reg_rtx (<MODE>mode);
12476 }
12477 [(set (attr "length")
12478 (if_then_else (match_test "operands[2] == const0_rtx")
12479 (const_string "8")
12480 (const_string "12")))])
12481
12482 (define_insn_and_split "*plus_ne_<mode>"
12483 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12484 (plus:P (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
12485 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
12486 (match_operand:P 3 "gpc_reg_operand" "r")))
12487 (clobber (match_scratch:P 4 "=r"))
12488 (clobber (match_scratch:P 5 "=r"))
12489 (clobber (reg:P CA_REGNO))]
12490 ""
12491 "#"
12492 ""
12493 [(parallel [(set (match_dup 5)
12494 (plus:P (match_dup 4)
12495 (const_int -1)))
12496 (set (reg:P CA_REGNO)
12497 (ne:P (match_dup 4)
12498 (const_int 0)))])
12499 (parallel [(set (match_dup 0)
12500 (plus:P (match_dup 3)
12501 (reg:P CA_REGNO)))
12502 (clobber (reg:P CA_REGNO))])]
12503 {
12504 operands[4] = rs6000_emit_eqne (<MODE>mode,
12505 operands[1], operands[2], operands[4]);
12506
12507 if (GET_CODE (operands[5]) == SCRATCH)
12508 operands[5] = gen_reg_rtx (<MODE>mode);
12509 }
12510 [(set (attr "length")
12511 (if_then_else (match_test "operands[2] == const0_rtx")
12512 (const_string "8")
12513 (const_string "12")))])
12514
12515 (define_insn_and_split "*minus_eq_<mode>"
12516 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12517 (minus:P (match_operand:P 3 "gpc_reg_operand" "r")
12518 (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
12519 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
12520 (clobber (match_scratch:P 4 "=r"))
12521 (clobber (match_scratch:P 5 "=r"))
12522 (clobber (reg:P CA_REGNO))]
12523 ""
12524 "#"
12525 ""
12526 [(parallel [(set (match_dup 5)
12527 (plus:P (match_dup 4)
12528 (const_int -1)))
12529 (set (reg:P CA_REGNO)
12530 (ne:P (match_dup 4)
12531 (const_int 0)))])
12532 (parallel [(set (match_dup 0)
12533 (plus:P (plus:P (match_dup 3)
12534 (reg:P CA_REGNO))
12535 (const_int -1)))
12536 (clobber (reg:P CA_REGNO))])]
12537 {
12538 operands[4] = rs6000_emit_eqne (<MODE>mode,
12539 operands[1], operands[2], operands[4]);
12540
12541 if (GET_CODE (operands[5]) == SCRATCH)
12542 operands[5] = gen_reg_rtx (<MODE>mode);
12543 }
12544 [(set (attr "length")
12545 (if_then_else (match_test "operands[2] == const0_rtx")
12546 (const_string "8")
12547 (const_string "12")))])
12548
12549 (define_insn_and_split "*minus_ne_<mode>"
12550 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
12551 (minus:P (match_operand:P 3 "gpc_reg_operand" "r")
12552 (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
12553 (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
12554 (clobber (match_scratch:P 4 "=r"))
12555 (clobber (match_scratch:P 5 "=r"))
12556 (clobber (reg:P CA_REGNO))]
12557 ""
12558 "#"
12559 ""
12560 [(parallel [(set (match_dup 5)
12561 (neg:P (match_dup 4)))
12562 (set (reg:P CA_REGNO)
12563 (eq:P (match_dup 4)
12564 (const_int 0)))])
12565 (parallel [(set (match_dup 0)
12566 (plus:P (plus:P (match_dup 3)
12567 (reg:P CA_REGNO))
12568 (const_int -1)))
12569 (clobber (reg:P CA_REGNO))])]
12570 {
12571 operands[4] = rs6000_emit_eqne (<MODE>mode,
12572 operands[1], operands[2], operands[4]);
12573
12574 if (GET_CODE (operands[5]) == SCRATCH)
12575 operands[5] = gen_reg_rtx (<MODE>mode);
12576 }
12577 [(set (attr "length")
12578 (if_then_else (match_test "operands[2] == const0_rtx")
12579 (const_string "8")
12580 (const_string "12")))])
12581
12582 (define_insn_and_split "*eqsi3_ext<mode>"
12583 [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r")
12584 (eq:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r")
12585 (match_operand:SI 2 "scc_eq_operand" "rKLI")))
12586 (clobber (match_scratch:SI 3 "=r"))
12587 (clobber (match_scratch:SI 4 "=r"))]
12588 ""
12589 "#"
12590 ""
12591 [(set (match_dup 4)
12592 (clz:SI (match_dup 3)))
12593 (set (match_dup 0)
12594 (zero_extend:EXTSI
12595 (lshiftrt:SI (match_dup 4)
12596 (const_int 5))))]
12597 {
12598 operands[3] = rs6000_emit_eqne (SImode,
12599 operands[1], operands[2], operands[3]);
12600
12601 if (GET_CODE (operands[4]) == SCRATCH)
12602 operands[4] = gen_reg_rtx (SImode);
12603 }
12604 [(set (attr "length")
12605 (if_then_else (match_test "operands[2] == const0_rtx")
12606 (const_string "8")
12607 (const_string "12")))])
12608
12609 (define_insn_and_split "*nesi3_ext<mode>"
12610 [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r")
12611 (ne:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r")
12612 (match_operand:SI 2 "scc_eq_operand" "rKLI")))
12613 (clobber (match_scratch:SI 3 "=r"))
12614 (clobber (match_scratch:SI 4 "=r"))
12615 (clobber (match_scratch:EXTSI 5 "=r"))]
12616 ""
12617 "#"
12618 ""
12619 [(set (match_dup 4)
12620 (clz:SI (match_dup 3)))
12621 (set (match_dup 5)
12622 (zero_extend:EXTSI
12623 (lshiftrt:SI (match_dup 4)
12624 (const_int 5))))
12625 (set (match_dup 0)
12626 (xor:EXTSI (match_dup 5)
12627 (const_int 1)))]
12628 {
12629 operands[3] = rs6000_emit_eqne (SImode,
12630 operands[1], operands[2], operands[3]);
12631
12632 if (GET_CODE (operands[4]) == SCRATCH)
12633 operands[4] = gen_reg_rtx (SImode);
12634 if (GET_CODE (operands[5]) == SCRATCH)
12635 operands[5] = gen_reg_rtx (<MODE>mode);
12636 }
12637 [(set (attr "length")
12638 (if_then_else (match_test "operands[2] == const0_rtx")
12639 (const_string "12")
12640 (const_string "16")))])
12641 \f
12642 ;; Define both directions of branch and return. If we need a reload
12643 ;; register, we'd rather use CR0 since it is much easier to copy a
12644 ;; register CC value to there.
12645
12646 (define_insn ""
12647 [(set (pc)
12648 (if_then_else (match_operator 1 "branch_comparison_operator"
12649 [(match_operand 2
12650 "cc_reg_operand" "y")
12651 (const_int 0)])
12652 (label_ref (match_operand 0 "" ""))
12653 (pc)))]
12654 ""
12655 "*
12656 {
12657 return output_cbranch (operands[1], \"%l0\", 0, insn);
12658 }"
12659 [(set_attr "type" "branch")])
12660
12661 (define_insn ""
12662 [(set (pc)
12663 (if_then_else (match_operator 0 "branch_comparison_operator"
12664 [(match_operand 1
12665 "cc_reg_operand" "y")
12666 (const_int 0)])
12667 (any_return)
12668 (pc)))]
12669 "<return_pred>"
12670 "*
12671 {
12672 return output_cbranch (operands[0], NULL, 0, insn);
12673 }"
12674 [(set_attr "type" "jmpreg")
12675 (set_attr "length" "4")])
12676
12677 (define_insn ""
12678 [(set (pc)
12679 (if_then_else (match_operator 1 "branch_comparison_operator"
12680 [(match_operand 2
12681 "cc_reg_operand" "y")
12682 (const_int 0)])
12683 (pc)
12684 (label_ref (match_operand 0 "" ""))))]
12685 ""
12686 "*
12687 {
12688 return output_cbranch (operands[1], \"%l0\", 1, insn);
12689 }"
12690 [(set_attr "type" "branch")])
12691
12692 (define_insn ""
12693 [(set (pc)
12694 (if_then_else (match_operator 0 "branch_comparison_operator"
12695 [(match_operand 1
12696 "cc_reg_operand" "y")
12697 (const_int 0)])
12698 (pc)
12699 (any_return)))]
12700 "<return_pred>"
12701 "*
12702 {
12703 return output_cbranch (operands[0], NULL, 1, insn);
12704 }"
12705 [(set_attr "type" "jmpreg")
12706 (set_attr "length" "4")])
12707
12708 ;; Logic on condition register values.
12709
12710 ; This pattern matches things like
12711 ; (set (reg:CCEQ 68) (compare:CCEQ (ior:SI (gt:SI (reg:CCFP 68) (const_int 0))
12712 ; (eq:SI (reg:CCFP 68) (const_int 0)))
12713 ; (const_int 1)))
12714 ; which are generated by the branch logic.
12715 ; Prefer destructive operations where BT = BB (for crXX BT,BA,BB)
12716
12717 (define_insn "*cceq_ior_compare"
12718 [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
12719 (compare:CCEQ (match_operator:SI 1 "boolean_operator"
12720 [(match_operator:SI 2
12721 "branch_positive_comparison_operator"
12722 [(match_operand 3
12723 "cc_reg_operand" "y,y")
12724 (const_int 0)])
12725 (match_operator:SI 4
12726 "branch_positive_comparison_operator"
12727 [(match_operand 5
12728 "cc_reg_operand" "0,y")
12729 (const_int 0)])])
12730 (const_int 1)))]
12731 ""
12732 "cr%q1 %E0,%j2,%j4"
12733 [(set_attr "type" "cr_logical,delayed_cr")])
12734
12735 ; Why is the constant -1 here, but 1 in the previous pattern?
12736 ; Because ~1 has all but the low bit set.
12737 (define_insn ""
12738 [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
12739 (compare:CCEQ (match_operator:SI 1 "boolean_or_operator"
12740 [(not:SI (match_operator:SI 2
12741 "branch_positive_comparison_operator"
12742 [(match_operand 3
12743 "cc_reg_operand" "y,y")
12744 (const_int 0)]))
12745 (match_operator:SI 4
12746 "branch_positive_comparison_operator"
12747 [(match_operand 5
12748 "cc_reg_operand" "0,y")
12749 (const_int 0)])])
12750 (const_int -1)))]
12751 ""
12752 "cr%q1 %E0,%j2,%j4"
12753 [(set_attr "type" "cr_logical,delayed_cr")])
12754
12755 (define_insn "*cceq_rev_compare"
12756 [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
12757 (compare:CCEQ (match_operator:SI 1
12758 "branch_positive_comparison_operator"
12759 [(match_operand 2
12760 "cc_reg_operand" "0,y")
12761 (const_int 0)])
12762 (const_int 0)))]
12763 ""
12764 "crnot %E0,%j1"
12765 [(set_attr "type" "cr_logical,delayed_cr")])
12766
12767 ;; If we are comparing the result of two comparisons, this can be done
12768 ;; using creqv or crxor.
12769
12770 (define_insn_and_split ""
12771 [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y")
12772 (compare:CCEQ (match_operator 1 "branch_comparison_operator"
12773 [(match_operand 2 "cc_reg_operand" "y")
12774 (const_int 0)])
12775 (match_operator 3 "branch_comparison_operator"
12776 [(match_operand 4 "cc_reg_operand" "y")
12777 (const_int 0)])))]
12778 ""
12779 "#"
12780 ""
12781 [(set (match_dup 0) (compare:CCEQ (xor:SI (match_dup 1) (match_dup 3))
12782 (match_dup 5)))]
12783 "
12784 {
12785 int positive_1, positive_2;
12786
12787 positive_1 = branch_positive_comparison_operator (operands[1],
12788 GET_MODE (operands[1]));
12789 positive_2 = branch_positive_comparison_operator (operands[3],
12790 GET_MODE (operands[3]));
12791
12792 if (! positive_1)
12793 operands[1] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE (operands[2]),
12794 GET_CODE (operands[1])),
12795 SImode,
12796 operands[2], const0_rtx);
12797 else if (GET_MODE (operands[1]) != SImode)
12798 operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode,
12799 operands[2], const0_rtx);
12800
12801 if (! positive_2)
12802 operands[3] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE (operands[4]),
12803 GET_CODE (operands[3])),
12804 SImode,
12805 operands[4], const0_rtx);
12806 else if (GET_MODE (operands[3]) != SImode)
12807 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
12808 operands[4], const0_rtx);
12809
12810 if (positive_1 == positive_2)
12811 {
12812 operands[1] = gen_rtx_NOT (SImode, operands[1]);
12813 operands[5] = constm1_rtx;
12814 }
12815 else
12816 {
12817 operands[5] = const1_rtx;
12818 }
12819 }")
12820
12821 ;; Unconditional branch and return.
12822
12823 (define_insn "jump"
12824 [(set (pc)
12825 (label_ref (match_operand 0 "" "")))]
12826 ""
12827 "b %l0"
12828 [(set_attr "type" "branch")])
12829
12830 (define_insn "<return_str>return"
12831 [(any_return)]
12832 "<return_pred>"
12833 "blr"
12834 [(set_attr "type" "jmpreg")])
12835
12836 (define_expand "indirect_jump"
12837 [(set (pc) (match_operand 0 "register_operand" ""))])
12838
12839 (define_insn "*indirect_jump<mode>"
12840 [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
12841 ""
12842 "@
12843 bctr
12844 blr"
12845 [(set_attr "type" "jmpreg")])
12846
12847 ;; Table jump for switch statements:
12848 (define_expand "tablejump"
12849 [(use (match_operand 0 "" ""))
12850 (use (label_ref (match_operand 1 "" "")))]
12851 ""
12852 "
12853 {
12854 if (TARGET_32BIT)
12855 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
12856 else
12857 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
12858 DONE;
12859 }")
12860
12861 (define_expand "tablejumpsi"
12862 [(set (match_dup 3)
12863 (plus:SI (match_operand:SI 0 "" "")
12864 (match_dup 2)))
12865 (parallel [(set (pc) (match_dup 3))
12866 (use (label_ref (match_operand 1 "" "")))])]
12867 "TARGET_32BIT"
12868 "
12869 { operands[0] = force_reg (SImode, operands[0]);
12870 operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
12871 operands[3] = gen_reg_rtx (SImode);
12872 }")
12873
12874 (define_expand "tablejumpdi"
12875 [(set (match_dup 4)
12876 (sign_extend:DI (match_operand:SI 0 "lwa_operand" "")))
12877 (set (match_dup 3)
12878 (plus:DI (match_dup 4)
12879 (match_dup 2)))
12880 (parallel [(set (pc) (match_dup 3))
12881 (use (label_ref (match_operand 1 "" "")))])]
12882 "TARGET_64BIT"
12883 "
12884 { operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
12885 operands[3] = gen_reg_rtx (DImode);
12886 operands[4] = gen_reg_rtx (DImode);
12887 }")
12888
12889 (define_insn "*tablejump<mode>_internal1"
12890 [(set (pc)
12891 (match_operand:P 0 "register_operand" "c,*l"))
12892 (use (label_ref (match_operand 1 "" "")))]
12893 ""
12894 "@
12895 bctr
12896 blr"
12897 [(set_attr "type" "jmpreg")])
12898
12899 (define_insn "nop"
12900 [(unspec [(const_int 0)] UNSPEC_NOP)]
12901 ""
12902 "nop")
12903
12904 (define_insn "group_ending_nop"
12905 [(unspec [(const_int 0)] UNSPEC_GRP_END_NOP)]
12906 ""
12907 "*
12908 {
12909 if (rs6000_cpu_attr == CPU_POWER6)
12910 return \"ori 1,1,0\";
12911 return \"ori 2,2,0\";
12912 }")
12913 \f
12914 ;; Define the subtract-one-and-jump insns, starting with the template
12915 ;; so loop.c knows what to generate.
12916
12917 (define_expand "doloop_end"
12918 [(use (match_operand 0 "" "")) ; loop pseudo
12919 (use (match_operand 1 "" ""))] ; label
12920 ""
12921 "
12922 {
12923 if (TARGET_64BIT)
12924 {
12925 if (GET_MODE (operands[0]) != DImode)
12926 FAIL;
12927 emit_jump_insn (gen_ctrdi (operands[0], operands[1]));
12928 }
12929 else
12930 {
12931 if (GET_MODE (operands[0]) != SImode)
12932 FAIL;
12933 emit_jump_insn (gen_ctrsi (operands[0], operands[1]));
12934 }
12935 DONE;
12936 }")
12937
12938 (define_expand "ctr<mode>"
12939 [(parallel [(set (pc)
12940 (if_then_else (ne (match_operand:P 0 "register_operand" "")
12941 (const_int 1))
12942 (label_ref (match_operand 1 "" ""))
12943 (pc)))
12944 (set (match_dup 0)
12945 (plus:P (match_dup 0)
12946 (const_int -1)))
12947 (clobber (match_scratch:CC 2 ""))
12948 (clobber (match_scratch:P 3 ""))])]
12949 ""
12950 "")
12951
12952 ;; We need to be able to do this for any operand, including MEM, or we
12953 ;; will cause reload to blow up since we don't allow output reloads on
12954 ;; JUMP_INSNs.
12955 ;; For the length attribute to be calculated correctly, the
12956 ;; label MUST be operand 0.
12957 ;; rs6000_legitimate_combined_insn prevents combine creating any of
12958 ;; the ctr<mode> insns.
12959
12960 (define_insn "ctr<mode>_internal1"
12961 [(set (pc)
12962 (if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
12963 (const_int 1))
12964 (label_ref (match_operand 0 "" ""))
12965 (pc)))
12966 (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
12967 (plus:P (match_dup 1)
12968 (const_int -1)))
12969 (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
12970 (clobber (match_scratch:P 4 "=X,X,&r,r"))]
12971 ""
12972 "*
12973 {
12974 if (which_alternative != 0)
12975 return \"#\";
12976 else if (get_attr_length (insn) == 4)
12977 return \"bdnz %l0\";
12978 else
12979 return \"bdz $+8\;b %l0\";
12980 }"
12981 [(set_attr "type" "branch")
12982 (set_attr "length" "*,16,20,20")])
12983
12984 (define_insn "ctr<mode>_internal2"
12985 [(set (pc)
12986 (if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
12987 (const_int 1))
12988 (pc)
12989 (label_ref (match_operand 0 "" ""))))
12990 (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
12991 (plus:P (match_dup 1)
12992 (const_int -1)))
12993 (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
12994 (clobber (match_scratch:P 4 "=X,X,&r,r"))]
12995 ""
12996 "*
12997 {
12998 if (which_alternative != 0)
12999 return \"#\";
13000 else if (get_attr_length (insn) == 4)
13001 return \"bdz %l0\";
13002 else
13003 return \"bdnz $+8\;b %l0\";
13004 }"
13005 [(set_attr "type" "branch")
13006 (set_attr "length" "*,16,20,20")])
13007
13008 ;; Similar but use EQ
13009
13010 (define_insn "ctr<mode>_internal3"
13011 [(set (pc)
13012 (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
13013 (const_int 1))
13014 (label_ref (match_operand 0 "" ""))
13015 (pc)))
13016 (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
13017 (plus:P (match_dup 1)
13018 (const_int -1)))
13019 (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
13020 (clobber (match_scratch:P 4 "=X,X,&r,r"))]
13021 ""
13022 "*
13023 {
13024 if (which_alternative != 0)
13025 return \"#\";
13026 else if (get_attr_length (insn) == 4)
13027 return \"bdz %l0\";
13028 else
13029 return \"bdnz $+8\;b %l0\";
13030 }"
13031 [(set_attr "type" "branch")
13032 (set_attr "length" "*,16,20,20")])
13033
13034 (define_insn "ctr<mode>_internal4"
13035 [(set (pc)
13036 (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
13037 (const_int 1))
13038 (pc)
13039 (label_ref (match_operand 0 "" ""))))
13040 (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
13041 (plus:P (match_dup 1)
13042 (const_int -1)))
13043 (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
13044 (clobber (match_scratch:P 4 "=X,X,&r,r"))]
13045 ""
13046 "*
13047 {
13048 if (which_alternative != 0)
13049 return \"#\";
13050 else if (get_attr_length (insn) == 4)
13051 return \"bdnz %l0\";
13052 else
13053 return \"bdz $+8\;b %l0\";
13054 }"
13055 [(set_attr "type" "branch")
13056 (set_attr "length" "*,16,20,20")])
13057
13058 ;; Now the splitters if we could not allocate the CTR register
13059
13060 (define_split
13061 [(set (pc)
13062 (if_then_else (match_operator 2 "comparison_operator"
13063 [(match_operand:P 1 "gpc_reg_operand" "")
13064 (const_int 1)])
13065 (match_operand 5 "" "")
13066 (match_operand 6 "" "")))
13067 (set (match_operand:P 0 "int_reg_operand" "")
13068 (plus:P (match_dup 1) (const_int -1)))
13069 (clobber (match_scratch:CC 3 ""))
13070 (clobber (match_scratch:P 4 ""))]
13071 "reload_completed"
13072 [(set (match_dup 3)
13073 (compare:CC (match_dup 1)
13074 (const_int 1)))
13075 (set (match_dup 0)
13076 (plus:P (match_dup 1)
13077 (const_int -1)))
13078 (set (pc) (if_then_else (match_dup 7)
13079 (match_dup 5)
13080 (match_dup 6)))]
13081 "
13082 { operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode,
13083 operands[3], const0_rtx); }")
13084
13085 (define_split
13086 [(set (pc)
13087 (if_then_else (match_operator 2 "comparison_operator"
13088 [(match_operand:P 1 "gpc_reg_operand" "")
13089 (const_int 1)])
13090 (match_operand 5 "" "")
13091 (match_operand 6 "" "")))
13092 (set (match_operand:P 0 "nonimmediate_operand" "")
13093 (plus:P (match_dup 1) (const_int -1)))
13094 (clobber (match_scratch:CC 3 ""))
13095 (clobber (match_scratch:P 4 ""))]
13096 "reload_completed && ! gpc_reg_operand (operands[0], SImode)"
13097 [(set (match_dup 3)
13098 (compare:CC (match_dup 1)
13099 (const_int 1)))
13100 (set (match_dup 4)
13101 (plus:P (match_dup 1)
13102 (const_int -1)))
13103 (set (match_dup 0)
13104 (match_dup 4))
13105 (set (pc) (if_then_else (match_dup 7)
13106 (match_dup 5)
13107 (match_dup 6)))]
13108 "
13109 { operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode,
13110 operands[3], const0_rtx); }")
13111 \f
13112 (define_insn "trap"
13113 [(trap_if (const_int 1) (const_int 0))]
13114 ""
13115 "trap"
13116 [(set_attr "type" "trap")])
13117
13118 (define_expand "ctrap<mode>4"
13119 [(trap_if (match_operator 0 "ordered_comparison_operator"
13120 [(match_operand:GPR 1 "register_operand")
13121 (match_operand:GPR 2 "reg_or_short_operand")])
13122 (match_operand 3 "zero_constant" ""))]
13123 ""
13124 "")
13125
13126 (define_insn ""
13127 [(trap_if (match_operator 0 "ordered_comparison_operator"
13128 [(match_operand:GPR 1 "register_operand" "r")
13129 (match_operand:GPR 2 "reg_or_short_operand" "rI")])
13130 (const_int 0))]
13131 ""
13132 "t<wd>%V0%I2 %1,%2"
13133 [(set_attr "type" "trap")])
13134 \f
13135 ;; Insns related to generating the function prologue and epilogue.
13136
13137 (define_expand "prologue"
13138 [(use (const_int 0))]
13139 ""
13140 {
13141 rs6000_emit_prologue ();
13142 if (!TARGET_SCHED_PROLOG)
13143 emit_insn (gen_blockage ());
13144 DONE;
13145 })
13146
13147 (define_insn "*movesi_from_cr_one"
13148 [(match_parallel 0 "mfcr_operation"
13149 [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
13150 (unspec:SI [(match_operand:CC 2 "cc_reg_operand" "y")
13151 (match_operand 3 "immediate_operand" "n")]
13152 UNSPEC_MOVESI_FROM_CR))])]
13153 "TARGET_MFCRF"
13154 "*
13155 {
13156 int mask = 0;
13157 int i;
13158 for (i = 0; i < XVECLEN (operands[0], 0); i++)
13159 {
13160 mask = INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1));
13161 operands[4] = GEN_INT (mask);
13162 output_asm_insn (\"mfcr %1,%4\", operands);
13163 }
13164 return \"\";
13165 }"
13166 [(set_attr "type" "mfcrf")])
13167
13168 (define_insn "movesi_from_cr"
13169 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
13170 (unspec:SI [(reg:CC CR0_REGNO) (reg:CC CR1_REGNO)
13171 (reg:CC CR2_REGNO) (reg:CC CR3_REGNO)
13172 (reg:CC CR4_REGNO) (reg:CC CR5_REGNO)
13173 (reg:CC CR6_REGNO) (reg:CC CR7_REGNO)]
13174 UNSPEC_MOVESI_FROM_CR))]
13175 ""
13176 "mfcr %0"
13177 [(set_attr "type" "mfcr")])
13178
13179 (define_insn "*crsave"
13180 [(match_parallel 0 "crsave_operation"
13181 [(set (match_operand:SI 1 "memory_operand" "=m")
13182 (match_operand:SI 2 "gpc_reg_operand" "r"))])]
13183 ""
13184 "stw %2,%1"
13185 [(set_attr "type" "store")])
13186
13187 (define_insn "*stmw"
13188 [(match_parallel 0 "stmw_operation"
13189 [(set (match_operand:SI 1 "memory_operand" "=m")
13190 (match_operand:SI 2 "gpc_reg_operand" "r"))])]
13191 "TARGET_MULTIPLE"
13192 "stmw %2,%1"
13193 [(set_attr "type" "store")
13194 (set_attr "update" "yes")
13195 (set_attr "indexed" "yes")])
13196
13197 ; The following comment applies to:
13198 ; save_gpregs_*
13199 ; save_fpregs_*
13200 ; restore_gpregs*
13201 ; return_and_restore_gpregs*
13202 ; return_and_restore_fpregs*
13203 ; return_and_restore_fpregs_aix*
13204 ;
13205 ; The out-of-line save / restore functions expects one input argument.
13206 ; Since those are not standard call_insn's, we must avoid using
13207 ; MATCH_OPERAND for that argument. That way the register rename
13208 ; optimization will not try to rename this register.
13209 ; Each pattern is repeated for each possible register number used in
13210 ; various ABIs (r11, r1, and for some functions r12)
13211
13212 (define_insn "*save_gpregs_<mode>_r11"
13213 [(match_parallel 0 "any_parallel_operand"
13214 [(clobber (reg:P LR_REGNO))
13215 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13216 (use (reg:P 11))
13217 (set (match_operand:P 2 "memory_operand" "=m")
13218 (match_operand:P 3 "gpc_reg_operand" "r"))])]
13219 ""
13220 "bl %1"
13221 [(set_attr "type" "branch")
13222 (set_attr "length" "4")])
13223
13224 (define_insn "*save_gpregs_<mode>_r12"
13225 [(match_parallel 0 "any_parallel_operand"
13226 [(clobber (reg:P LR_REGNO))
13227 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13228 (use (reg:P 12))
13229 (set (match_operand:P 2 "memory_operand" "=m")
13230 (match_operand:P 3 "gpc_reg_operand" "r"))])]
13231 ""
13232 "bl %1"
13233 [(set_attr "type" "branch")
13234 (set_attr "length" "4")])
13235
13236 (define_insn "*save_gpregs_<mode>_r1"
13237 [(match_parallel 0 "any_parallel_operand"
13238 [(clobber (reg:P LR_REGNO))
13239 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13240 (use (reg:P 1))
13241 (set (match_operand:P 2 "memory_operand" "=m")
13242 (match_operand:P 3 "gpc_reg_operand" "r"))])]
13243 ""
13244 "bl %1"
13245 [(set_attr "type" "branch")
13246 (set_attr "length" "4")])
13247
13248 (define_insn "*save_fpregs_<mode>_r11"
13249 [(match_parallel 0 "any_parallel_operand"
13250 [(clobber (reg:P LR_REGNO))
13251 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13252 (use (reg:P 11))
13253 (set (match_operand:DF 2 "memory_operand" "=m")
13254 (match_operand:DF 3 "gpc_reg_operand" "d"))])]
13255 ""
13256 "bl %1"
13257 [(set_attr "type" "branch")
13258 (set_attr "length" "4")])
13259
13260 (define_insn "*save_fpregs_<mode>_r12"
13261 [(match_parallel 0 "any_parallel_operand"
13262 [(clobber (reg:P LR_REGNO))
13263 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13264 (use (reg:P 12))
13265 (set (match_operand:DF 2 "memory_operand" "=m")
13266 (match_operand:DF 3 "gpc_reg_operand" "d"))])]
13267 ""
13268 "bl %1"
13269 [(set_attr "type" "branch")
13270 (set_attr "length" "4")])
13271
13272 (define_insn "*save_fpregs_<mode>_r1"
13273 [(match_parallel 0 "any_parallel_operand"
13274 [(clobber (reg:P LR_REGNO))
13275 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13276 (use (reg:P 1))
13277 (set (match_operand:DF 2 "memory_operand" "=m")
13278 (match_operand:DF 3 "gpc_reg_operand" "d"))])]
13279 ""
13280 "bl %1"
13281 [(set_attr "type" "branch")
13282 (set_attr "length" "4")])
13283
13284 ; This is to explain that changes to the stack pointer should
13285 ; not be moved over loads from or stores to stack memory.
13286 (define_insn "stack_tie"
13287 [(match_parallel 0 "tie_operand"
13288 [(set (mem:BLK (reg 1)) (const_int 0))])]
13289 ""
13290 ""
13291 [(set_attr "length" "0")])
13292
13293 ; Some 32-bit ABIs do not have a red zone, so the stack deallocation has to
13294 ; stay behind all restores from the stack, it cannot be reordered to before
13295 ; one. See PR77687. This insn is an add or mr, and a stack_tie on the
13296 ; operands of that.
13297 (define_insn "stack_restore_tie"
13298 [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
13299 (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
13300 (match_operand:SI 2 "reg_or_cint_operand" "O,rI")))
13301 (set (mem:BLK (match_dup 0)) (const_int 0))
13302 (set (mem:BLK (match_dup 1)) (const_int 0))]
13303 "TARGET_32BIT"
13304 "@
13305 mr %0,%1
13306 add%I2 %0,%1,%2"
13307 [(set_attr "type" "*,add")])
13308
13309 (define_expand "epilogue"
13310 [(use (const_int 0))]
13311 ""
13312 {
13313 if (!TARGET_SCHED_PROLOG)
13314 emit_insn (gen_blockage ());
13315 rs6000_emit_epilogue (FALSE);
13316 DONE;
13317 })
13318
13319 ; On some processors, doing the mtcrf one CC register at a time is
13320 ; faster (like on the 604e). On others, doing them all at once is
13321 ; faster; for instance, on the 601 and 750.
13322
13323 (define_expand "movsi_to_cr_one"
13324 [(set (match_operand:CC 0 "cc_reg_operand" "")
13325 (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "")
13326 (match_dup 2)] UNSPEC_MOVESI_TO_CR))]
13327 ""
13328 "operands[2] = GEN_INT (1 << (75 - REGNO (operands[0])));")
13329
13330 (define_insn "*movsi_to_cr"
13331 [(match_parallel 0 "mtcrf_operation"
13332 [(set (match_operand:CC 1 "cc_reg_operand" "=y")
13333 (unspec:CC [(match_operand:SI 2 "gpc_reg_operand" "r")
13334 (match_operand 3 "immediate_operand" "n")]
13335 UNSPEC_MOVESI_TO_CR))])]
13336 ""
13337 "*
13338 {
13339 int mask = 0;
13340 int i;
13341 for (i = 0; i < XVECLEN (operands[0], 0); i++)
13342 mask |= INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1));
13343 operands[4] = GEN_INT (mask);
13344 return \"mtcrf %4,%2\";
13345 }"
13346 [(set_attr "type" "mtcr")])
13347
13348 (define_insn "*mtcrfsi"
13349 [(set (match_operand:CC 0 "cc_reg_operand" "=y")
13350 (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
13351 (match_operand 2 "immediate_operand" "n")]
13352 UNSPEC_MOVESI_TO_CR))]
13353 "GET_CODE (operands[0]) == REG
13354 && CR_REGNO_P (REGNO (operands[0]))
13355 && GET_CODE (operands[2]) == CONST_INT
13356 && INTVAL (operands[2]) == 1 << (75 - REGNO (operands[0]))"
13357 "mtcrf %R0,%1"
13358 [(set_attr "type" "mtcr")])
13359
13360 ; The load-multiple instructions have similar properties.
13361 ; Note that "load_multiple" is a name known to the machine-independent
13362 ; code that actually corresponds to the PowerPC load-string.
13363
13364 (define_insn "*lmw"
13365 [(match_parallel 0 "lmw_operation"
13366 [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
13367 (match_operand:SI 2 "memory_operand" "m"))])]
13368 "TARGET_MULTIPLE"
13369 "lmw %1,%2"
13370 [(set_attr "type" "load")
13371 (set_attr "update" "yes")
13372 (set_attr "indexed" "yes")
13373 (set_attr "cell_micro" "always")])
13374
13375 ; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
13376 ; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible...
13377
13378 ; The following comment applies to:
13379 ; save_gpregs_*
13380 ; save_fpregs_*
13381 ; restore_gpregs*
13382 ; return_and_restore_gpregs*
13383 ; return_and_restore_fpregs*
13384 ; return_and_restore_fpregs_aix*
13385 ;
13386 ; The out-of-line save / restore functions expects one input argument.
13387 ; Since those are not standard call_insn's, we must avoid using
13388 ; MATCH_OPERAND for that argument. That way the register rename
13389 ; optimization will not try to rename this register.
13390 ; Each pattern is repeated for each possible register number used in
13391 ; various ABIs (r11, r1, and for some functions r12)
13392
13393 (define_insn "*restore_gpregs_<mode>_r11"
13394 [(match_parallel 0 "any_parallel_operand"
13395 [(clobber (reg:P LR_REGNO))
13396 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13397 (use (reg:P 11))
13398 (set (match_operand:P 2 "gpc_reg_operand" "=r")
13399 (match_operand:P 3 "memory_operand" "m"))])]
13400 ""
13401 "bl %1"
13402 [(set_attr "type" "branch")
13403 (set_attr "length" "4")])
13404
13405 (define_insn "*restore_gpregs_<mode>_r12"
13406 [(match_parallel 0 "any_parallel_operand"
13407 [(clobber (reg:P LR_REGNO))
13408 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13409 (use (reg:P 12))
13410 (set (match_operand:P 2 "gpc_reg_operand" "=r")
13411 (match_operand:P 3 "memory_operand" "m"))])]
13412 ""
13413 "bl %1"
13414 [(set_attr "type" "branch")
13415 (set_attr "length" "4")])
13416
13417 (define_insn "*restore_gpregs_<mode>_r1"
13418 [(match_parallel 0 "any_parallel_operand"
13419 [(clobber (reg:P LR_REGNO))
13420 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13421 (use (reg:P 1))
13422 (set (match_operand:P 2 "gpc_reg_operand" "=r")
13423 (match_operand:P 3 "memory_operand" "m"))])]
13424 ""
13425 "bl %1"
13426 [(set_attr "type" "branch")
13427 (set_attr "length" "4")])
13428
13429 (define_insn "*return_and_restore_gpregs_<mode>_r11"
13430 [(match_parallel 0 "any_parallel_operand"
13431 [(return)
13432 (clobber (reg:P LR_REGNO))
13433 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13434 (use (reg:P 11))
13435 (set (match_operand:P 2 "gpc_reg_operand" "=r")
13436 (match_operand:P 3 "memory_operand" "m"))])]
13437 ""
13438 "b %1"
13439 [(set_attr "type" "branch")
13440 (set_attr "length" "4")])
13441
13442 (define_insn "*return_and_restore_gpregs_<mode>_r12"
13443 [(match_parallel 0 "any_parallel_operand"
13444 [(return)
13445 (clobber (reg:P LR_REGNO))
13446 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13447 (use (reg:P 12))
13448 (set (match_operand:P 2 "gpc_reg_operand" "=r")
13449 (match_operand:P 3 "memory_operand" "m"))])]
13450 ""
13451 "b %1"
13452 [(set_attr "type" "branch")
13453 (set_attr "length" "4")])
13454
13455 (define_insn "*return_and_restore_gpregs_<mode>_r1"
13456 [(match_parallel 0 "any_parallel_operand"
13457 [(return)
13458 (clobber (reg:P LR_REGNO))
13459 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13460 (use (reg:P 1))
13461 (set (match_operand:P 2 "gpc_reg_operand" "=r")
13462 (match_operand:P 3 "memory_operand" "m"))])]
13463 ""
13464 "b %1"
13465 [(set_attr "type" "branch")
13466 (set_attr "length" "4")])
13467
13468 (define_insn "*return_and_restore_fpregs_<mode>_r11"
13469 [(match_parallel 0 "any_parallel_operand"
13470 [(return)
13471 (clobber (reg:P LR_REGNO))
13472 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13473 (use (reg:P 11))
13474 (set (match_operand:DF 2 "gpc_reg_operand" "=d")
13475 (match_operand:DF 3 "memory_operand" "m"))])]
13476 ""
13477 "b %1"
13478 [(set_attr "type" "branch")
13479 (set_attr "length" "4")])
13480
13481 (define_insn "*return_and_restore_fpregs_<mode>_r12"
13482 [(match_parallel 0 "any_parallel_operand"
13483 [(return)
13484 (clobber (reg:P LR_REGNO))
13485 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13486 (use (reg:P 12))
13487 (set (match_operand:DF 2 "gpc_reg_operand" "=d")
13488 (match_operand:DF 3 "memory_operand" "m"))])]
13489 ""
13490 "b %1"
13491 [(set_attr "type" "branch")
13492 (set_attr "length" "4")])
13493
13494 (define_insn "*return_and_restore_fpregs_<mode>_r1"
13495 [(match_parallel 0 "any_parallel_operand"
13496 [(return)
13497 (clobber (reg:P LR_REGNO))
13498 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13499 (use (reg:P 1))
13500 (set (match_operand:DF 2 "gpc_reg_operand" "=d")
13501 (match_operand:DF 3 "memory_operand" "m"))])]
13502 ""
13503 "b %1"
13504 [(set_attr "type" "branch")
13505 (set_attr "length" "4")])
13506
13507 (define_insn "*return_and_restore_fpregs_aix_<mode>_r11"
13508 [(match_parallel 0 "any_parallel_operand"
13509 [(return)
13510 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13511 (use (reg:P 11))
13512 (set (match_operand:DF 2 "gpc_reg_operand" "=d")
13513 (match_operand:DF 3 "memory_operand" "m"))])]
13514 ""
13515 "b %1"
13516 [(set_attr "type" "branch")
13517 (set_attr "length" "4")])
13518
13519 (define_insn "*return_and_restore_fpregs_aix_<mode>_r1"
13520 [(match_parallel 0 "any_parallel_operand"
13521 [(return)
13522 (use (match_operand:P 1 "symbol_ref_operand" "s"))
13523 (use (reg:P 1))
13524 (set (match_operand:DF 2 "gpc_reg_operand" "=d")
13525 (match_operand:DF 3 "memory_operand" "m"))])]
13526 ""
13527 "b %1"
13528 [(set_attr "type" "branch")
13529 (set_attr "length" "4")])
13530
13531 ; This is used in compiling the unwind routines.
13532 (define_expand "eh_return"
13533 [(use (match_operand 0 "general_operand" ""))]
13534 ""
13535 "
13536 {
13537 if (TARGET_32BIT)
13538 emit_insn (gen_eh_set_lr_si (operands[0]));
13539 else
13540 emit_insn (gen_eh_set_lr_di (operands[0]));
13541 DONE;
13542 }")
13543
13544 ; We can't expand this before we know where the link register is stored.
13545 (define_insn "eh_set_lr_<mode>"
13546 [(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
13547 UNSPECV_EH_RR)
13548 (clobber (match_scratch:P 1 "=&b"))]
13549 ""
13550 "#")
13551
13552 (define_split
13553 [(unspec_volatile [(match_operand 0 "register_operand" "")] UNSPECV_EH_RR)
13554 (clobber (match_scratch 1 ""))]
13555 "reload_completed"
13556 [(const_int 0)]
13557 "
13558 {
13559 rs6000_emit_eh_reg_restore (operands[0], operands[1]);
13560 DONE;
13561 }")
13562
13563 (define_insn "prefetch"
13564 [(prefetch (match_operand 0 "indexed_or_indirect_address" "a")
13565 (match_operand:SI 1 "const_int_operand" "n")
13566 (match_operand:SI 2 "const_int_operand" "n"))]
13567 ""
13568 "*
13569 {
13570 if (GET_CODE (operands[0]) == REG)
13571 return INTVAL (operands[1]) ? \"dcbtst 0,%0\" : \"dcbt 0,%0\";
13572 return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\";
13573 }"
13574 [(set_attr "type" "load")])
13575 \f
13576 ;; Handle -fsplit-stack.
13577
13578 (define_expand "split_stack_prologue"
13579 [(const_int 0)]
13580 ""
13581 {
13582 rs6000_expand_split_stack_prologue ();
13583 DONE;
13584 })
13585
13586 (define_expand "load_split_stack_limit"
13587 [(set (match_operand 0)
13588 (unspec [(const_int 0)] UNSPEC_STACK_CHECK))]
13589 ""
13590 {
13591 emit_insn (gen_rtx_SET (operands[0],
13592 gen_rtx_UNSPEC (Pmode,
13593 gen_rtvec (1, const0_rtx),
13594 UNSPEC_STACK_CHECK)));
13595 DONE;
13596 })
13597
13598 (define_insn "load_split_stack_limit_di"
13599 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
13600 (unspec:DI [(const_int 0)] UNSPEC_STACK_CHECK))]
13601 "TARGET_64BIT"
13602 "ld %0,-0x7040(13)"
13603 [(set_attr "type" "load")
13604 (set_attr "update" "no")
13605 (set_attr "indexed" "no")])
13606
13607 (define_insn "load_split_stack_limit_si"
13608 [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
13609 (unspec:SI [(const_int 0)] UNSPEC_STACK_CHECK))]
13610 "!TARGET_64BIT"
13611 "lwz %0,-0x7020(2)"
13612 [(set_attr "type" "load")
13613 (set_attr "update" "no")
13614 (set_attr "indexed" "no")])
13615
13616 ;; A return instruction which the middle-end doesn't see.
13617 ;; Use r0 to stop regrename twiddling with lr restore insns emitted
13618 ;; after the call to __morestack.
13619 (define_insn "split_stack_return"
13620 [(unspec_volatile [(use (reg:SI 0))] UNSPECV_SPLIT_STACK_RETURN)]
13621 ""
13622 "blr"
13623 [(set_attr "type" "jmpreg")])
13624
13625 ;; If there are operand 0 bytes available on the stack, jump to
13626 ;; operand 1.
13627 (define_expand "split_stack_space_check"
13628 [(set (match_dup 2)
13629 (unspec [(const_int 0)] UNSPEC_STACK_CHECK))
13630 (set (match_dup 3)
13631 (minus (reg STACK_POINTER_REGNUM)
13632 (match_operand 0)))
13633 (set (match_dup 4) (compare:CCUNS (match_dup 3) (match_dup 2)))
13634 (set (pc) (if_then_else
13635 (geu (match_dup 4) (const_int 0))
13636 (label_ref (match_operand 1))
13637 (pc)))]
13638 ""
13639 {
13640 rs6000_split_stack_space_check (operands[0], operands[1]);
13641 DONE;
13642 })
13643 \f
13644 (define_insn "bpermd_<mode>"
13645 [(set (match_operand:P 0 "gpc_reg_operand" "=r")
13646 (unspec:P [(match_operand:P 1 "gpc_reg_operand" "r")
13647 (match_operand:P 2 "gpc_reg_operand" "r")] UNSPEC_BPERM))]
13648 "TARGET_POPCNTD"
13649 "bpermd %0,%1,%2"
13650 [(set_attr "type" "popcnt")])
13651
13652 \f
13653 ;; Builtin fma support. Handle
13654 ;; Note that the conditions for expansion are in the FMA_F iterator.
13655
13656 (define_expand "fma<mode>4"
13657 [(set (match_operand:FMA_F 0 "gpc_reg_operand" "")
13658 (fma:FMA_F
13659 (match_operand:FMA_F 1 "gpc_reg_operand" "")
13660 (match_operand:FMA_F 2 "gpc_reg_operand" "")
13661 (match_operand:FMA_F 3 "gpc_reg_operand" "")))]
13662 ""
13663 "")
13664
13665 (define_insn "*fma<mode>4_fpr"
13666 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
13667 (fma:SFDF
13668 (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>,<Fv2>")
13669 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
13670 (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>")))]
13671 "TARGET_<MODE>_FPR"
13672 "@
13673 fmadd<Ftrad> %0,%1,%2,%3
13674 xsmadda<Fvsx> %x0,%x1,%x2
13675 xsmaddm<Fvsx> %x0,%x1,%x3"
13676 [(set_attr "type" "fp")
13677 (set_attr "fp_type" "fp_maddsub_<Fs>")])
13678
13679 ; Altivec only has fma and nfms.
13680 (define_expand "fms<mode>4"
13681 [(set (match_operand:FMA_F 0 "gpc_reg_operand" "")
13682 (fma:FMA_F
13683 (match_operand:FMA_F 1 "gpc_reg_operand" "")
13684 (match_operand:FMA_F 2 "gpc_reg_operand" "")
13685 (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand" ""))))]
13686 "!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
13687 "")
13688
13689 (define_insn "*fms<mode>4_fpr"
13690 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
13691 (fma:SFDF
13692 (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>")
13693 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
13694 (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>"))))]
13695 "TARGET_<MODE>_FPR"
13696 "@
13697 fmsub<Ftrad> %0,%1,%2,%3
13698 xsmsuba<Fvsx> %x0,%x1,%x2
13699 xsmsubm<Fvsx> %x0,%x1,%x3"
13700 [(set_attr "type" "fp")
13701 (set_attr "fp_type" "fp_maddsub_<Fs>")])
13702
13703 ;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
13704 (define_expand "fnma<mode>4"
13705 [(set (match_operand:FMA_F 0 "gpc_reg_operand" "")
13706 (neg:FMA_F
13707 (fma:FMA_F
13708 (match_operand:FMA_F 1 "gpc_reg_operand" "")
13709 (match_operand:FMA_F 2 "gpc_reg_operand" "")
13710 (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand" "")))))]
13711 "!HONOR_SIGNED_ZEROS (<MODE>mode)"
13712 "")
13713
13714 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
13715 (define_expand "fnms<mode>4"
13716 [(set (match_operand:FMA_F 0 "gpc_reg_operand" "")
13717 (neg:FMA_F
13718 (fma:FMA_F
13719 (match_operand:FMA_F 1 "gpc_reg_operand" "")
13720 (match_operand:FMA_F 2 "gpc_reg_operand" "")
13721 (match_operand:FMA_F 3 "gpc_reg_operand" ""))))]
13722 "!HONOR_SIGNED_ZEROS (<MODE>mode) && !VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
13723 "")
13724
13725 ; Not an official optab name, but used from builtins.
13726 (define_expand "nfma<mode>4"
13727 [(set (match_operand:FMA_F 0 "gpc_reg_operand" "")
13728 (neg:FMA_F
13729 (fma:FMA_F
13730 (match_operand:FMA_F 1 "gpc_reg_operand" "")
13731 (match_operand:FMA_F 2 "gpc_reg_operand" "")
13732 (match_operand:FMA_F 3 "gpc_reg_operand" ""))))]
13733 "!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
13734 "")
13735
13736 (define_insn "*nfma<mode>4_fpr"
13737 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
13738 (neg:SFDF
13739 (fma:SFDF
13740 (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>")
13741 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
13742 (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>"))))]
13743 "TARGET_<MODE>_FPR"
13744 "@
13745 fnmadd<Ftrad> %0,%1,%2,%3
13746 xsnmadda<Fvsx> %x0,%x1,%x2
13747 xsnmaddm<Fvsx> %x0,%x1,%x3"
13748 [(set_attr "type" "fp")
13749 (set_attr "fp_type" "fp_maddsub_<Fs>")])
13750
13751 ; Not an official optab name, but used from builtins.
13752 (define_expand "nfms<mode>4"
13753 [(set (match_operand:FMA_F 0 "gpc_reg_operand" "")
13754 (neg:FMA_F
13755 (fma:FMA_F
13756 (match_operand:FMA_F 1 "gpc_reg_operand" "")
13757 (match_operand:FMA_F 2 "gpc_reg_operand" "")
13758 (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand" "")))))]
13759 ""
13760 "")
13761
13762 (define_insn "*nfmssf4_fpr"
13763 [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
13764 (neg:SFDF
13765 (fma:SFDF
13766 (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>")
13767 (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
13768 (neg:SFDF
13769 (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>")))))]
13770 "TARGET_<MODE>_FPR"
13771 "@
13772 fnmsub<Ftrad> %0,%1,%2,%3
13773 xsnmsuba<Fvsx> %x0,%x1,%x2
13774 xsnmsubm<Fvsx> %x0,%x1,%x3"
13775 [(set_attr "type" "fp")
13776 (set_attr "fp_type" "fp_maddsub_<Fs>")])
13777
13778 \f
13779 (define_expand "rs6000_get_timebase"
13780 [(use (match_operand:DI 0 "gpc_reg_operand" ""))]
13781 ""
13782 {
13783 if (TARGET_POWERPC64)
13784 emit_insn (gen_rs6000_mftb_di (operands[0]));
13785 else
13786 emit_insn (gen_rs6000_get_timebase_ppc32 (operands[0]));
13787 DONE;
13788 })
13789
13790 (define_insn "rs6000_get_timebase_ppc32"
13791 [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
13792 (unspec_volatile:DI [(const_int 0)] UNSPECV_MFTB))
13793 (clobber (match_scratch:SI 1 "=r"))
13794 (clobber (match_scratch:CC 2 "=y"))]
13795 "!TARGET_POWERPC64"
13796 {
13797 if (WORDS_BIG_ENDIAN)
13798 if (TARGET_MFCRF)
13799 {
13800 return "mfspr %0,269\;"
13801 "mfspr %L0,268\;"
13802 "mfspr %1,269\;"
13803 "cmpw %2,%0,%1\;"
13804 "bne- %2,$-16";
13805 }
13806 else
13807 {
13808 return "mftbu %0\;"
13809 "mftb %L0\;"
13810 "mftbu %1\;"
13811 "cmpw %2,%0,%1\;"
13812 "bne- %2,$-16";
13813 }
13814 else
13815 if (TARGET_MFCRF)
13816 {
13817 return "mfspr %L0,269\;"
13818 "mfspr %0,268\;"
13819 "mfspr %1,269\;"
13820 "cmpw %2,%L0,%1\;"
13821 "bne- %2,$-16";
13822 }
13823 else
13824 {
13825 return "mftbu %L0\;"
13826 "mftb %0\;"
13827 "mftbu %1\;"
13828 "cmpw %2,%L0,%1\;"
13829 "bne- %2,$-16";
13830 }
13831 }
13832 [(set_attr "length" "20")])
13833
13834 (define_insn "rs6000_mftb_<mode>"
13835 [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
13836 (unspec_volatile:GPR [(const_int 0)] UNSPECV_MFTB))]
13837 ""
13838 {
13839 if (TARGET_MFCRF)
13840 return "mfspr %0,268";
13841 else
13842 return "mftb %0";
13843 })
13844
13845 \f
13846 (define_insn "rs6000_mffs"
13847 [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
13848 (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFS))]
13849 "TARGET_HARD_FLOAT && TARGET_FPRS"
13850 "mffs %0")
13851
13852 (define_insn "rs6000_mtfsf"
13853 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")
13854 (match_operand:DF 1 "gpc_reg_operand" "d")]
13855 UNSPECV_MTFSF)]
13856 "TARGET_HARD_FLOAT && TARGET_FPRS"
13857 "mtfsf %0,%1")
13858
13859 \f
13860 ;; Power8 fusion support for fusing an addis instruction with a D-form load of
13861 ;; a GPR. The addis instruction must be adjacent to the load, and use the same
13862 ;; register that is being loaded. The fused ops must be physically adjacent.
13863
13864 ;; There are two parts to addis fusion. The support for fused TOCs occur
13865 ;; before register allocation, and is meant to reduce the lifetime for the
13866 ;; tempoary register that holds the ADDIS result. On Power8 GPR loads, we try
13867 ;; to use the register that is being load. The peephole2 then gathers any
13868 ;; other fused possibilities that it can find after register allocation. If
13869 ;; power9 fusion is selected, we also fuse floating point loads/stores.
13870
13871 ;; Fused TOC support: Replace simple GPR loads with a fused form. This is done
13872 ;; before register allocation, so that we can avoid allocating a temporary base
13873 ;; register that won't be used, and that we try to load into base registers,
13874 ;; and not register 0. If we can't get a fused GPR load, generate a P9 fusion
13875 ;; (addis followed by load) even on power8.
13876
13877 (define_split
13878 [(set (match_operand:INT1 0 "toc_fusion_or_p9_reg_operand" "")
13879 (match_operand:INT1 1 "toc_fusion_mem_raw" ""))]
13880 "TARGET_TOC_FUSION_INT && can_create_pseudo_p ()"
13881 [(parallel [(set (match_dup 0) (match_dup 2))
13882 (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS)
13883 (use (match_dup 3))
13884 (clobber (scratch:DI))])]
13885 {
13886 operands[2] = fusion_wrap_memory_address (operands[1]);
13887 operands[3] = gen_rtx_REG (Pmode, TOC_REGISTER);
13888 })
13889
13890 (define_insn "*toc_fusionload_<mode>"
13891 [(set (match_operand:QHSI 0 "int_reg_operand" "=&b,??r")
13892 (match_operand:QHSI 1 "toc_fusion_mem_wrapped" "wG,wG"))
13893 (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS)
13894 (use (match_operand:DI 2 "base_reg_operand" "r,r"))
13895 (clobber (match_scratch:DI 3 "=X,&b"))]
13896 "TARGET_TOC_FUSION_INT"
13897 {
13898 if (base_reg_operand (operands[0], <MODE>mode))
13899 return emit_fusion_gpr_load (operands[0], operands[1]);
13900
13901 return emit_fusion_p9_load (operands[0], operands[1], operands[3]);
13902 }
13903 [(set_attr "type" "load")
13904 (set_attr "length" "8")])
13905
13906 (define_insn "*toc_fusionload_di"
13907 [(set (match_operand:DI 0 "int_reg_operand" "=&b,??r,?d")
13908 (match_operand:DI 1 "toc_fusion_mem_wrapped" "wG,wG,wG"))
13909 (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS)
13910 (use (match_operand:DI 2 "base_reg_operand" "r,r,r"))
13911 (clobber (match_scratch:DI 3 "=X,&b,&b"))]
13912 "TARGET_TOC_FUSION_INT && TARGET_POWERPC64
13913 && (MEM_P (operands[1]) || int_reg_operand (operands[0], DImode))"
13914 {
13915 if (base_reg_operand (operands[0], DImode))
13916 return emit_fusion_gpr_load (operands[0], operands[1]);
13917
13918 return emit_fusion_p9_load (operands[0], operands[1], operands[3]);
13919 }
13920 [(set_attr "type" "load")
13921 (set_attr "length" "8")])
13922
13923 \f
13924 ;; Find cases where the addis that feeds into a load instruction is either used
13925 ;; once or is the same as the target register, and replace it with the fusion
13926 ;; insn
13927
13928 (define_peephole2
13929 [(set (match_operand:P 0 "base_reg_operand" "")
13930 (match_operand:P 1 "fusion_gpr_addis" ""))
13931 (set (match_operand:INT1 2 "base_reg_operand" "")
13932 (match_operand:INT1 3 "fusion_gpr_mem_load" ""))]
13933 "TARGET_P8_FUSION
13934 && fusion_gpr_load_p (operands[0], operands[1], operands[2],
13935 operands[3])"
13936 [(const_int 0)]
13937 {
13938 expand_fusion_gpr_load (operands);
13939 DONE;
13940 })
13941
13942 ;; Fusion insn, created by the define_peephole2 above (and eventually by
13943 ;; reload)
13944
13945 (define_insn "fusion_gpr_load_<mode>"
13946 [(set (match_operand:INT1 0 "base_reg_operand" "=b")
13947 (unspec:INT1 [(match_operand:INT1 1 "fusion_addis_mem_combo_load" "wF")]
13948 UNSPEC_FUSION_GPR))]
13949 "TARGET_P8_FUSION"
13950 {
13951 return emit_fusion_gpr_load (operands[0], operands[1]);
13952 }
13953 [(set_attr "type" "load")
13954 (set_attr "length" "8")])
13955
13956 \f
13957 ;; ISA 3.0 (power9) fusion support
13958 ;; Merge addis with floating load/store to FPRs (or GPRs).
13959 (define_peephole2
13960 [(set (match_operand:P 0 "base_reg_operand" "")
13961 (match_operand:P 1 "fusion_gpr_addis" ""))
13962 (set (match_operand:SFDF 2 "toc_fusion_or_p9_reg_operand" "")
13963 (match_operand:SFDF 3 "fusion_offsettable_mem_operand" ""))]
13964 "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0])
13965 && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])"
13966 [(const_int 0)]
13967 {
13968 expand_fusion_p9_load (operands);
13969 DONE;
13970 })
13971
13972 (define_peephole2
13973 [(set (match_operand:P 0 "base_reg_operand" "")
13974 (match_operand:P 1 "fusion_gpr_addis" ""))
13975 (set (match_operand:SFDF 2 "offsettable_mem_operand" "")
13976 (match_operand:SFDF 3 "toc_fusion_or_p9_reg_operand" ""))]
13977 "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0])
13978 && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])
13979 && !rtx_equal_p (operands[0], operands[3])"
13980 [(const_int 0)]
13981 {
13982 expand_fusion_p9_store (operands);
13983 DONE;
13984 })
13985
13986 (define_peephole2
13987 [(set (match_operand:SDI 0 "int_reg_operand" "")
13988 (match_operand:SDI 1 "upper16_cint_operand" ""))
13989 (set (match_dup 0)
13990 (ior:SDI (match_dup 0)
13991 (match_operand:SDI 2 "u_short_cint_operand" "")))]
13992 "TARGET_P9_FUSION"
13993 [(set (match_dup 0)
13994 (unspec:SDI [(match_dup 1)
13995 (match_dup 2)] UNSPEC_FUSION_P9))])
13996
13997 (define_peephole2
13998 [(set (match_operand:SDI 0 "int_reg_operand" "")
13999 (match_operand:SDI 1 "upper16_cint_operand" ""))
14000 (set (match_operand:SDI 2 "int_reg_operand" "")
14001 (ior:SDI (match_dup 0)
14002 (match_operand:SDI 3 "u_short_cint_operand" "")))]
14003 "TARGET_P9_FUSION
14004 && !rtx_equal_p (operands[0], operands[2])
14005 && peep2_reg_dead_p (2, operands[0])"
14006 [(set (match_dup 2)
14007 (unspec:SDI [(match_dup 1)
14008 (match_dup 3)] UNSPEC_FUSION_P9))])
14009
14010 ;; Fusion insns, created by the define_peephole2 above (and eventually by
14011 ;; reload). Because we want to eventually have secondary_reload generate
14012 ;; these, they have to have a single alternative that gives the register
14013 ;; classes. This means we need to have separate gpr/fpr/altivec versions.
14014 (define_insn "fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load"
14015 [(set (match_operand:GPR_FUSION 0 "int_reg_operand" "=r")
14016 (unspec:GPR_FUSION
14017 [(match_operand:GPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")]
14018 UNSPEC_FUSION_P9))
14019 (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
14020 "TARGET_P9_FUSION"
14021 {
14022 /* This insn is a secondary reload insn, which cannot have alternatives.
14023 If we are not loading up register 0, use the power8 fusion instead. */
14024 if (base_reg_operand (operands[0], <GPR_FUSION:MODE>mode))
14025 return emit_fusion_gpr_load (operands[0], operands[1]);
14026
14027 return emit_fusion_p9_load (operands[0], operands[1], operands[2]);
14028 }
14029 [(set_attr "type" "load")
14030 (set_attr "length" "8")])
14031
14032 (define_insn "fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store"
14033 [(set (match_operand:GPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF")
14034 (unspec:GPR_FUSION
14035 [(match_operand:GPR_FUSION 1 "int_reg_operand" "r")]
14036 UNSPEC_FUSION_P9))
14037 (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
14038 "TARGET_P9_FUSION"
14039 {
14040 return emit_fusion_p9_store (operands[0], operands[1], operands[2]);
14041 }
14042 [(set_attr "type" "store")
14043 (set_attr "length" "8")])
14044
14045 (define_insn "fusion_vsx_<P:mode>_<FPR_FUSION:mode>_load"
14046 [(set (match_operand:FPR_FUSION 0 "vsx_register_operand" "=dwb")
14047 (unspec:FPR_FUSION
14048 [(match_operand:FPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")]
14049 UNSPEC_FUSION_P9))
14050 (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
14051 "TARGET_P9_FUSION"
14052 {
14053 return emit_fusion_p9_load (operands[0], operands[1], operands[2]);
14054 }
14055 [(set_attr "type" "fpload")
14056 (set_attr "length" "8")])
14057
14058 (define_insn "fusion_vsx_<P:mode>_<FPR_FUSION:mode>_store"
14059 [(set (match_operand:FPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF")
14060 (unspec:FPR_FUSION
14061 [(match_operand:FPR_FUSION 1 "vsx_register_operand" "dwb")]
14062 UNSPEC_FUSION_P9))
14063 (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
14064 "TARGET_P9_FUSION"
14065 {
14066 return emit_fusion_p9_store (operands[0], operands[1], operands[2]);
14067 }
14068 [(set_attr "type" "fpstore")
14069 (set_attr "length" "8")])
14070
14071 (define_insn "*fusion_p9_<mode>_constant"
14072 [(set (match_operand:SDI 0 "int_reg_operand" "=r")
14073 (unspec:SDI [(match_operand:SDI 1 "upper16_cint_operand" "L")
14074 (match_operand:SDI 2 "u_short_cint_operand" "K")]
14075 UNSPEC_FUSION_P9))]
14076 "TARGET_P9_FUSION"
14077 {
14078 emit_fusion_addis (operands[0], operands[1], "constant", "<MODE>");
14079 return "ori %0,%0,%2";
14080 }
14081 [(set_attr "type" "two")
14082 (set_attr "length" "8")])
14083
14084 \f
14085 ;; Optimize cases where we want to do a D-form load (register+offset) on
14086 ;; ISA 2.06/2.07 to an Altivec register, and the register allocator
14087 ;; has generated:
14088 ;; LFD 0,32(3)
14089 ;; XXLOR 32,0,0
14090 ;;
14091 ;; and we change this to:
14092 ;; LI 0,32
14093 ;; LXSDX 32,3,9
14094
14095 (define_peephole2
14096 [(match_scratch:DI 0 "b")
14097 (set (match_operand:ALTIVEC_DFORM 1 "fpr_reg_operand")
14098 (match_operand:ALTIVEC_DFORM 2 "simple_offsettable_mem_operand"))
14099 (set (match_operand:ALTIVEC_DFORM 3 "altivec_register_operand")
14100 (match_dup 1))]
14101 "TARGET_VSX && TARGET_POWERPC64 && TARGET_UPPER_REGS_<MODE>
14102 && !TARGET_P9_DFORM_SCALAR && peep2_reg_dead_p (2, operands[1])"
14103 [(set (match_dup 0)
14104 (match_dup 4))
14105 (set (match_dup 3)
14106 (match_dup 5))]
14107 {
14108 rtx tmp_reg = operands[0];
14109 rtx mem = operands[2];
14110 rtx addr = XEXP (mem, 0);
14111 rtx add_op0, add_op1, new_addr;
14112
14113 gcc_assert (GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM);
14114 add_op0 = XEXP (addr, 0);
14115 add_op1 = XEXP (addr, 1);
14116 gcc_assert (REG_P (add_op0));
14117 new_addr = gen_rtx_PLUS (DImode, add_op0, tmp_reg);
14118
14119 operands[4] = add_op1;
14120 operands[5] = change_address (mem, <MODE>mode, new_addr);
14121 })
14122
14123 ;; Optimize cases were want to do a D-form store on ISA 2.06/2.07 from an
14124 ;; Altivec register, and the register allocator has generated:
14125 ;; XXLOR 0,32,32
14126 ;; STFD 0,32(3)
14127 ;;
14128 ;; and we change this to:
14129 ;; LI 0,32
14130 ;; STXSDX 32,3,9
14131
14132 (define_peephole2
14133 [(match_scratch:DI 0 "b")
14134 (set (match_operand:ALTIVEC_DFORM 1 "fpr_reg_operand")
14135 (match_operand:ALTIVEC_DFORM 2 "altivec_register_operand"))
14136 (set (match_operand:ALTIVEC_DFORM 3 "simple_offsettable_mem_operand")
14137 (match_dup 1))]
14138 "TARGET_VSX && TARGET_POWERPC64 && TARGET_UPPER_REGS_<MODE>
14139 && !TARGET_P9_DFORM_SCALAR && peep2_reg_dead_p (2, operands[1])"
14140 [(set (match_dup 0)
14141 (match_dup 4))
14142 (set (match_dup 5)
14143 (match_dup 2))]
14144 {
14145 rtx tmp_reg = operands[0];
14146 rtx mem = operands[3];
14147 rtx addr = XEXP (mem, 0);
14148 rtx add_op0, add_op1, new_addr;
14149
14150 gcc_assert (GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM);
14151 add_op0 = XEXP (addr, 0);
14152 add_op1 = XEXP (addr, 1);
14153 gcc_assert (REG_P (add_op0));
14154 new_addr = gen_rtx_PLUS (DImode, add_op0, tmp_reg);
14155
14156 operands[4] = add_op1;
14157 operands[5] = change_address (mem, <MODE>mode, new_addr);
14158 })
14159
14160 \f
14161 ;; Miscellaneous ISA 2.06 (power7) instructions
14162 (define_insn "addg6s"
14163 [(set (match_operand:SI 0 "register_operand" "=r")
14164 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
14165 (match_operand:SI 2 "register_operand" "r")]
14166 UNSPEC_ADDG6S))]
14167 "TARGET_POPCNTD"
14168 "addg6s %0,%1,%2"
14169 [(set_attr "type" "integer")
14170 (set_attr "length" "4")])
14171
14172 (define_insn "cdtbcd"
14173 [(set (match_operand:SI 0 "register_operand" "=r")
14174 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
14175 UNSPEC_CDTBCD))]
14176 "TARGET_POPCNTD"
14177 "cdtbcd %0,%1"
14178 [(set_attr "type" "integer")
14179 (set_attr "length" "4")])
14180
14181 (define_insn "cbcdtd"
14182 [(set (match_operand:SI 0 "register_operand" "=r")
14183 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
14184 UNSPEC_CBCDTD))]
14185 "TARGET_POPCNTD"
14186 "cbcdtd %0,%1"
14187 [(set_attr "type" "integer")
14188 (set_attr "length" "4")])
14189
14190 (define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE
14191 UNSPEC_DIVEO
14192 UNSPEC_DIVEU
14193 UNSPEC_DIVEUO])
14194
14195 (define_int_attr div_extend [(UNSPEC_DIVE "e")
14196 (UNSPEC_DIVEO "eo")
14197 (UNSPEC_DIVEU "eu")
14198 (UNSPEC_DIVEUO "euo")])
14199
14200 (define_insn "div<div_extend>_<mode>"
14201 [(set (match_operand:GPR 0 "register_operand" "=r")
14202 (unspec:GPR [(match_operand:GPR 1 "register_operand" "r")
14203 (match_operand:GPR 2 "register_operand" "r")]
14204 UNSPEC_DIV_EXTEND))]
14205 "TARGET_POPCNTD"
14206 "div<wd><div_extend> %0,%1,%2"
14207 [(set_attr "type" "div")
14208 (set_attr "size" "<bits>")])
14209
14210 \f
14211 ;; Pack/unpack 128-bit floating point types that take 2 scalar registers
14212
14213 ; Type of the 64-bit part when packing/unpacking 128-bit floating point types
14214 (define_mode_attr FP128_64 [(TF "DF")
14215 (IF "DF")
14216 (TD "DI")
14217 (KF "DI")])
14218
14219 (define_expand "unpack<mode>"
14220 [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
14221 (unspec:<FP128_64>
14222 [(match_operand:FMOVE128 1 "register_operand" "")
14223 (match_operand:QI 2 "const_0_to_1_operand" "")]
14224 UNSPEC_UNPACK_128BIT))]
14225 "FLOAT128_2REG_P (<MODE>mode)"
14226 "")
14227
14228 (define_insn_and_split "unpack<mode>_dm"
14229 [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m")
14230 (unspec:<FP128_64>
14231 [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
14232 (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
14233 UNSPEC_UNPACK_128BIT))]
14234 "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
14235 "#"
14236 "&& reload_completed"
14237 [(set (match_dup 0) (match_dup 3))]
14238 {
14239 unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]);
14240
14241 if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno)
14242 {
14243 emit_note (NOTE_INSN_DELETED);
14244 DONE;
14245 }
14246
14247 operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
14248 }
14249 [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")
14250 (set_attr "length" "4")])
14251
14252 (define_insn_and_split "unpack<mode>_nodm"
14253 [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m")
14254 (unspec:<FP128_64>
14255 [(match_operand:FMOVE128 1 "register_operand" "d,d")
14256 (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
14257 UNSPEC_UNPACK_128BIT))]
14258 "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
14259 "#"
14260 "&& reload_completed"
14261 [(set (match_dup 0) (match_dup 3))]
14262 {
14263 unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]);
14264
14265 if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno)
14266 {
14267 emit_note (NOTE_INSN_DELETED);
14268 DONE;
14269 }
14270
14271 operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
14272 }
14273 [(set_attr "type" "fp,fpstore")
14274 (set_attr "length" "4")])
14275
14276 (define_insn_and_split "pack<mode>"
14277 [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d")
14278 (unspec:FMOVE128
14279 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
14280 (match_operand:<FP128_64> 2 "register_operand" "d,d")]
14281 UNSPEC_PACK_128BIT))]
14282 "FLOAT128_2REG_P (<MODE>mode)"
14283 "@
14284 fmr %L0,%2
14285 #"
14286 "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])"
14287 [(set (match_dup 3) (match_dup 1))
14288 (set (match_dup 4) (match_dup 2))]
14289 {
14290 unsigned dest_hi = REGNO (operands[0]);
14291 unsigned dest_lo = dest_hi + 1;
14292
14293 gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo));
14294 gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo));
14295
14296 operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi);
14297 operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo);
14298 }
14299 [(set_attr "type" "fpsimple,fp")
14300 (set_attr "length" "4,8")])
14301
14302 (define_insn "unpack<mode>"
14303 [(set (match_operand:DI 0 "register_operand" "=d,d")
14304 (unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa")
14305 (match_operand:QI 2 "const_0_to_1_operand" "O,i")]
14306 UNSPEC_UNPACK_128BIT))]
14307 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
14308 {
14309 if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
14310 return ASM_COMMENT_START " xxpermdi to same register";
14311
14312 operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3);
14313 return "xxpermdi %x0,%x1,%x1,%3";
14314 }
14315 [(set_attr "type" "vecperm")])
14316
14317 (define_insn "pack<mode>"
14318 [(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa")
14319 (unspec:FMOVE128_VSX
14320 [(match_operand:DI 1 "register_operand" "d")
14321 (match_operand:DI 2 "register_operand" "d")]
14322 UNSPEC_PACK_128BIT))]
14323 "TARGET_VSX"
14324 "xxpermdi %x0,%x1,%x2,0"
14325 [(set_attr "type" "vecperm")])
14326
14327
14328 \f
14329 ;; ISA 2.08 IEEE 128-bit floating point support.
14330
14331 (define_insn "add<mode>3"
14332 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14333 (plus:IEEE128
14334 (match_operand:IEEE128 1 "altivec_register_operand" "v")
14335 (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
14336 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14337 "xsaddqp %0,%1,%2"
14338 [(set_attr "type" "vecfloat")
14339 (set_attr "size" "128")])
14340
14341 (define_insn "sub<mode>3"
14342 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14343 (minus:IEEE128
14344 (match_operand:IEEE128 1 "altivec_register_operand" "v")
14345 (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
14346 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14347 "xssubqp %0,%1,%2"
14348 [(set_attr "type" "vecfloat")
14349 (set_attr "size" "128")])
14350
14351 (define_insn "mul<mode>3"
14352 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14353 (mult:IEEE128
14354 (match_operand:IEEE128 1 "altivec_register_operand" "v")
14355 (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
14356 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14357 "xsmulqp %0,%1,%2"
14358 [(set_attr "type" "vecfloat")
14359 (set_attr "size" "128")])
14360
14361 (define_insn "div<mode>3"
14362 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14363 (div:IEEE128
14364 (match_operand:IEEE128 1 "altivec_register_operand" "v")
14365 (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
14366 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14367 "xsdivqp %0,%1,%2"
14368 [(set_attr "type" "vecdiv")
14369 (set_attr "size" "128")])
14370
14371 (define_insn "sqrt<mode>2"
14372 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14373 (sqrt:IEEE128
14374 (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14375 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14376 "xssqrtqp %0,%1"
14377 [(set_attr "type" "vecdiv")
14378 (set_attr "size" "128")])
14379
14380 (define_expand "copysign<mode>3"
14381 [(use (match_operand:IEEE128 0 "altivec_register_operand"))
14382 (use (match_operand:IEEE128 1 "altivec_register_operand"))
14383 (use (match_operand:IEEE128 2 "altivec_register_operand"))]
14384 "FLOAT128_IEEE_P (<MODE>mode)"
14385 {
14386 if (TARGET_FLOAT128_HW)
14387 emit_insn (gen_copysign<mode>3_hard (operands[0], operands[1],
14388 operands[2]));
14389 else
14390 {
14391 rtx tmp = gen_reg_rtx (<MODE>mode);
14392 emit_insn (gen_copysign<mode>3_soft (operands[0], operands[1],
14393 operands[2], tmp));
14394 }
14395 DONE;
14396 })
14397
14398 (define_insn "copysign<mode>3_hard"
14399 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14400 (unspec:IEEE128
14401 [(match_operand:IEEE128 1 "altivec_register_operand" "v")
14402 (match_operand:IEEE128 2 "altivec_register_operand" "v")]
14403 UNSPEC_COPYSIGN))]
14404 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14405 "xscpsgnqp %0,%2,%1"
14406 [(set_attr "type" "vecmove")
14407 (set_attr "size" "128")])
14408
14409 (define_insn "copysign<mode>3_soft"
14410 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14411 (unspec:IEEE128
14412 [(match_operand:IEEE128 1 "altivec_register_operand" "v")
14413 (match_operand:IEEE128 2 "altivec_register_operand" "v")
14414 (match_operand:IEEE128 3 "altivec_register_operand" "+v")]
14415 UNSPEC_COPYSIGN))]
14416 "!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14417 "xscpsgndp %x3,%x2,%x1\;xxpermdi %x0,%x3,%x1,1"
14418 [(set_attr "type" "veccomplex")
14419 (set_attr "length" "8")])
14420
14421 (define_insn "neg<mode>2_hw"
14422 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14423 (neg:IEEE128
14424 (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14425 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14426 "xsnegqp %0,%1"
14427 [(set_attr "type" "vecmove")
14428 (set_attr "size" "128")])
14429
14430
14431 (define_insn "abs<mode>2_hw"
14432 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14433 (abs:IEEE128
14434 (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14435 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14436 "xsabsqp %0,%1"
14437 [(set_attr "type" "vecmove")
14438 (set_attr "size" "128")])
14439
14440
14441 (define_insn "*nabs<mode>2_hw"
14442 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14443 (neg:IEEE128
14444 (abs:IEEE128
14445 (match_operand:IEEE128 1 "altivec_register_operand" "v"))))]
14446 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14447 "xsnabsqp %0,%1"
14448 [(set_attr "type" "vecmove")
14449 (set_attr "size" "128")])
14450
14451 ;; Initially don't worry about doing fusion
14452 (define_insn "*fma<mode>4_hw"
14453 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14454 (fma:IEEE128
14455 (match_operand:IEEE128 1 "altivec_register_operand" "%v")
14456 (match_operand:IEEE128 2 "altivec_register_operand" "v")
14457 (match_operand:IEEE128 3 "altivec_register_operand" "0")))]
14458 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14459 "xsmaddqp %0,%1,%2"
14460 [(set_attr "type" "vecfloat")
14461 (set_attr "size" "128")])
14462
14463 (define_insn "*fms<mode>4_hw"
14464 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14465 (fma:IEEE128
14466 (match_operand:IEEE128 1 "altivec_register_operand" "%v")
14467 (match_operand:IEEE128 2 "altivec_register_operand" "v")
14468 (neg:IEEE128
14469 (match_operand:IEEE128 3 "altivec_register_operand" "0"))))]
14470 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14471 "xsmsubqp %0,%1,%2"
14472 [(set_attr "type" "vecfloat")
14473 (set_attr "size" "128")])
14474
14475 (define_insn "*nfma<mode>4_hw"
14476 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14477 (neg:IEEE128
14478 (fma:IEEE128
14479 (match_operand:IEEE128 1 "altivec_register_operand" "%v")
14480 (match_operand:IEEE128 2 "altivec_register_operand" "v")
14481 (match_operand:IEEE128 3 "altivec_register_operand" "0"))))]
14482 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14483 "xsnmaddqp %0,%1,%2"
14484 [(set_attr "type" "vecfloat")
14485 (set_attr "size" "128")])
14486
14487 (define_insn "*nfms<mode>4_hw"
14488 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14489 (neg:IEEE128
14490 (fma:IEEE128
14491 (match_operand:IEEE128 1 "altivec_register_operand" "%v")
14492 (match_operand:IEEE128 2 "altivec_register_operand" "v")
14493 (neg:IEEE128
14494 (match_operand:IEEE128 3 "altivec_register_operand" "0")))))]
14495 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14496 "xsnmsubqp %0,%1,%2"
14497 [(set_attr "type" "vecfloat")
14498 (set_attr "size" "128")])
14499
14500 (define_insn "extend<SFDF:mode><IEEE128:mode>2_hw"
14501 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14502 (float_extend:IEEE128
14503 (match_operand:SFDF 1 "altivec_register_operand" "v")))]
14504 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<IEEE128:MODE>mode)"
14505 "xscvdpqp %0,%1"
14506 [(set_attr "type" "vecfloat")
14507 (set_attr "size" "128")])
14508
14509 ;; Conversion between KFmode and TFmode if TFmode is ieee 128-bit floating
14510 ;; point is a simple copy.
14511 (define_insn_and_split "extendkftf2"
14512 [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa")
14513 (float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))]
14514 "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
14515 "@
14516 #
14517 xxlor %x0,%x1,%x1"
14518 "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
14519 [(const_int 0)]
14520 {
14521 emit_note (NOTE_INSN_DELETED);
14522 DONE;
14523 }
14524 [(set_attr "type" "*,veclogical")
14525 (set_attr "length" "0,4")])
14526
14527 (define_insn_and_split "trunctfkf2"
14528 [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa")
14529 (float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))]
14530 "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
14531 "@
14532 #
14533 xxlor %x0,%x1,%x1"
14534 "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
14535 [(const_int 0)]
14536 {
14537 emit_note (NOTE_INSN_DELETED);
14538 DONE;
14539 }
14540 [(set_attr "type" "*,veclogical")
14541 (set_attr "length" "0,4")])
14542
14543 (define_insn "trunc<mode>df2_hw"
14544 [(set (match_operand:DF 0 "altivec_register_operand" "=v")
14545 (float_truncate:DF
14546 (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14547 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14548 "xscvqpdp %0,%1"
14549 [(set_attr "type" "vecfloat")
14550 (set_attr "size" "128")])
14551
14552 ;; There is no KFmode -> SFmode instruction. Preserve the accuracy by doing
14553 ;; the KFmode -> DFmode conversion using round to odd rather than the normal
14554 ;; conversion
14555 (define_insn_and_split "trunc<mode>sf2_hw"
14556 [(set (match_operand:SF 0 "vsx_register_operand" "=wy")
14557 (float_truncate:SF
14558 (match_operand:IEEE128 1 "altivec_register_operand" "v")))
14559 (clobber (match_scratch:DF 2 "=v"))]
14560 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14561 "#"
14562 "&& 1"
14563 [(set (match_dup 2)
14564 (unspec:DF [(match_dup 1)] UNSPEC_ROUND_TO_ODD))
14565 (set (match_dup 0)
14566 (float_truncate:SF (match_dup 2)))]
14567 {
14568 if (GET_CODE (operands[2]) == SCRATCH)
14569 operands[2] = gen_reg_rtx (DFmode);
14570 }
14571 [(set_attr "type" "vecfloat")
14572 (set_attr "length" "8")])
14573
14574 ;; Conversion between IEEE 128-bit and integer types
14575 (define_insn "fix_<mode>di2_hw"
14576 [(set (match_operand:DI 0 "altivec_register_operand" "=v")
14577 (fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14578 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14579 "xscvqpsdz %0,%1"
14580 [(set_attr "type" "vecfloat")
14581 (set_attr "size" "128")])
14582
14583 (define_insn "fixuns_<mode>di2_hw"
14584 [(set (match_operand:DI 0 "altivec_register_operand" "=v")
14585 (unsigned_fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14586 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14587 "xscvqpudz %0,%1"
14588 [(set_attr "type" "vecfloat")
14589 (set_attr "size" "128")])
14590
14591 (define_insn "fix_<mode>si2_hw"
14592 [(set (match_operand:SI 0 "altivec_register_operand" "=v")
14593 (fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14594 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14595 "xscvqpswz %0,%1"
14596 [(set_attr "type" "vecfloat")
14597 (set_attr "size" "128")])
14598
14599 (define_insn "fixuns_<mode>si2_hw"
14600 [(set (match_operand:SI 0 "altivec_register_operand" "=v")
14601 (unsigned_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))]
14602 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14603 "xscvqpuwz %0,%1"
14604 [(set_attr "type" "vecfloat")
14605 (set_attr "size" "128")])
14606
14607 ;; Combiner pattern to prevent moving the result of converting an IEEE 128-bit
14608 ;; floating point value to 32-bit integer to GPR in order to save it.
14609 (define_insn_and_split "*fix<uns>_<mode>_mem"
14610 [(set (match_operand:SI 0 "memory_operand" "=Z")
14611 (any_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))
14612 (clobber (match_scratch:SI 2 "=v"))]
14613 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14614 "#"
14615 "&& reload_completed"
14616 [(set (match_dup 2)
14617 (any_fix:SI (match_dup 1)))
14618 (set (match_dup 0)
14619 (match_dup 2))])
14620
14621 (define_insn "float_<mode>di2_hw"
14622 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14623 (float:IEEE128 (match_operand:DI 1 "altivec_register_operand" "v")))]
14624 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14625 "xscvsdqp %0,%1"
14626 [(set_attr "type" "vecfloat")
14627 (set_attr "size" "128")])
14628
14629 (define_insn_and_split "float_<mode>si2_hw"
14630 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14631 (float:IEEE128 (match_operand:SI 1 "nonimmediate_operand" "vrZ")))
14632 (clobber (match_scratch:DI 2 "=v"))]
14633 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14634 "#"
14635 "&& 1"
14636 [(set (match_dup 2)
14637 (sign_extend:DI (match_dup 1)))
14638 (set (match_dup 0)
14639 (float:IEEE128 (match_dup 2)))]
14640 {
14641 if (GET_CODE (operands[2]) == SCRATCH)
14642 operands[2] = gen_reg_rtx (DImode);
14643 })
14644
14645 (define_insn_and_split "float<QHI:mode><IEEE128:mode>2"
14646 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v,v,v")
14647 (float:IEEE128 (match_operand:QHI 1 "nonimmediate_operand" "v,r,Z")))
14648 (clobber (match_scratch:DI 2 "=X,r,X"))]
14649 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<IEEE128:MODE>mode)"
14650 "#"
14651 "&& reload_completed"
14652 [(const_int 0)]
14653 {
14654 rtx dest = operands[0];
14655 rtx src = operands[1];
14656 rtx dest_di = gen_rtx_REG (DImode, REGNO (dest));
14657
14658 if (altivec_register_operand (src, <QHI:MODE>mode))
14659 emit_insn (gen_extend<QHI:mode>di2 (dest_di, src));
14660 else if (int_reg_operand (src, <QHI:MODE>mode))
14661 {
14662 rtx ext_di = operands[2];
14663 emit_insn (gen_extend<QHI:mode>di2 (ext_di, src));
14664 emit_move_insn (dest_di, ext_di);
14665 }
14666 else if (MEM_P (src))
14667 {
14668 rtx dest_qhi = gen_rtx_REG (<QHI:MODE>mode, REGNO (dest));
14669 emit_move_insn (dest_qhi, src);
14670 emit_insn (gen_extend<QHI:mode>di2 (dest_di, dest_qhi));
14671 }
14672 else
14673 gcc_unreachable ();
14674
14675 emit_insn (gen_float_<IEEE128:mode>di2_hw (dest, dest_di));
14676 DONE;
14677 }
14678 [(set_attr "length" "8,12,12")
14679 (set_attr "type" "vecfloat")
14680 (set_attr "size" "128")])
14681
14682 (define_insn "floatuns_<mode>di2_hw"
14683 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14684 (unsigned_float:IEEE128
14685 (match_operand:DI 1 "altivec_register_operand" "v")))]
14686 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14687 "xscvudqp %0,%1"
14688 [(set_attr "type" "vecfloat")
14689 (set_attr "size" "128")])
14690
14691 (define_insn_and_split "floatuns_<mode>si2_hw"
14692 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
14693 (unsigned_float:IEEE128
14694 (match_operand:SI 1 "nonimmediate_operand" "vrZ")))
14695 (clobber (match_scratch:DI 2 "=v"))]
14696 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14697 "#"
14698 "&& 1"
14699 [(set (match_dup 2)
14700 (zero_extend:DI (match_dup 1)))
14701 (set (match_dup 0)
14702 (float:IEEE128 (match_dup 2)))]
14703 {
14704 if (GET_CODE (operands[2]) == SCRATCH)
14705 operands[2] = gen_reg_rtx (DImode);
14706 })
14707
14708 (define_insn_and_split "floatuns<QHI:mode><IEEE128:mode>2"
14709 [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v,v,v")
14710 (unsigned_float:IEEE128
14711 (match_operand:QHI 1 "nonimmediate_operand" "v,r,Z")))
14712 (clobber (match_scratch:DI 2 "=X,r,X"))]
14713 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<IEEE128:MODE>mode)"
14714 "#"
14715 "&& reload_completed"
14716 [(const_int 0)]
14717 {
14718 rtx dest = operands[0];
14719 rtx src = operands[1];
14720 rtx dest_di = gen_rtx_REG (DImode, REGNO (dest));
14721
14722 if (altivec_register_operand (src, <QHI:MODE>mode) || MEM_P (src))
14723 emit_insn (gen_zero_extend<QHI:mode>di2 (dest_di, src));
14724 else if (int_reg_operand (src, <QHI:MODE>mode))
14725 {
14726 rtx ext_di = operands[2];
14727 emit_insn (gen_zero_extend<QHI:mode>di2 (ext_di, src));
14728 emit_move_insn (dest_di, ext_di);
14729 }
14730 else
14731 gcc_unreachable ();
14732
14733 emit_insn (gen_floatuns_<IEEE128:mode>di2_hw (dest, dest_di));
14734 DONE;
14735 }
14736 [(set_attr "length" "8,12,8")
14737 (set_attr "type" "vecfloat")
14738 (set_attr "size" "128")])
14739
14740 ;; IEEE 128-bit instructions with round to odd semantics
14741 (define_insn "*trunc<mode>df2_odd"
14742 [(set (match_operand:DF 0 "vsx_register_operand" "=v")
14743 (unspec:DF [(match_operand:IEEE128 1 "altivec_register_operand" "v")]
14744 UNSPEC_ROUND_TO_ODD))]
14745 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14746 "xscvqpdpo %0,%1"
14747 [(set_attr "type" "vecfloat")
14748 (set_attr "size" "128")])
14749
14750 ;; IEEE 128-bit comparisons
14751 (define_insn "*cmp<mode>_hw"
14752 [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
14753 (compare:CCFP (match_operand:IEEE128 1 "altivec_register_operand" "v")
14754 (match_operand:IEEE128 2 "altivec_register_operand" "v")))]
14755 "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
14756 "xscmpuqp %0,%1,%2"
14757 [(set_attr "type" "veccmp")
14758 (set_attr "size" "128")])
14759
14760 \f
14761
14762 (include "sync.md")
14763 (include "vector.md")
14764 (include "vsx.md")
14765 (include "altivec.md")
14766 (include "spe.md")
14767 (include "dfp.md")
14768 (include "paired.md")
14769 (include "crypto.md")
14770 (include "htm.md")