Reverting merge from trunk
[official-gcc.git] / gcc / config / sh / sh.md
blob8cc9195c9887de6ad89c32345e28b31836ad1f92
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993-2013 Free Software Foundation, Inc.
3 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
4 ;;  Improved by Jim Wilson (wilson@cygnus.com).
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3.  If not see
20 ;; <http://www.gnu.org/licenses/>.
23 ;; ??? Should prepend a * to all pattern names which are not used.
24 ;; This will make the compiler smaller, and rebuilds after changes faster.
26 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
27 ;; sequences.  Especially the sequences for arithmetic right shifts.
29 ;; ??? Should check all DImode patterns for consistency and usefulness.
31 ;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
32 ;; way to generate them.
34 ;; BSR is not generated by the compiler proper, but when relaxing, it
35 ;; generates .uses pseudo-ops that allow linker relaxation to create
36 ;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
38 ;; Special constraints for SH machine description:
40 ;;    t -- T
41 ;;    x -- mac
42 ;;    l -- pr
43 ;;    z -- r0
45 ;; Special formats used for outputting SH instructions:
47 ;;   %.  --  print a .s if insn needs delay slot
48 ;;   %@  --  print rte/rts if is/isn't an interrupt function
49 ;;   %#  --  output a nop if there is nothing to put in the delay slot
50 ;;   %O  --  print a constant without the #
51 ;;   %R  --  print the lsw reg of a double
52 ;;   %S  --  print the msw reg of a double
53 ;;   %T  --  print next word of a double REG or MEM
55 ;; Special predicates:
57 ;;  arith_operand          -- operand is valid source for arithmetic op
58 ;;  arith_reg_operand      -- operand is valid register for arithmetic op
59 ;;  general_movdst_operand -- operand is valid move destination
60 ;;  general_movsrc_operand -- operand is valid move source
61 ;;  logical_operand        -- operand is valid source for logical op
63 ;; -------------------------------------------------------------------------
64 ;; Constants
65 ;; -------------------------------------------------------------------------
67 (define_constants [
68   (AP_REG       145)
69   (PR_REG       146)
70   (T_REG        147)
71   (GBR_REG      144)
72   (MACH_REG     148)
73   (MACL_REG     149)
74   (FPUL_REG     150)
75   (RAP_REG      152)
77   (FPSCR_REG    151)
79   (PIC_REG      12)
80   (FP_REG       14)
81   (SP_REG       15)
83   (PR_MEDIA_REG 18)
84   (T_MEDIA_REG  19)
86   (R0_REG       0)
87   (R1_REG       1)
88   (R2_REG       2)
89   (R3_REG       3)
90   (R4_REG       4)
91   (R5_REG       5)
92   (R6_REG       6)
93   (R7_REG       7)
94   (R8_REG       8)
95   (R9_REG       9)
96   (R10_REG      10)
97   (R20_REG      20)
98   (R21_REG      21)
99   (R22_REG      22)
100   (R23_REG      23)
102   (DR0_REG      64)
103   (DR2_REG      66)
104   (DR4_REG      68)
105   (FR23_REG     87)
107   (TR0_REG      128)
108   (TR1_REG      129)
109   (TR2_REG      130)
111   (XD0_REG      136)
113   ;; These are used with unspec.
114   (UNSPEC_COMPACT_ARGS  0)
115   (UNSPEC_MOVA          1)
116   (UNSPEC_CASESI        2)
117   (UNSPEC_DATALABEL     3)
118   (UNSPEC_BBR           4)
119   (UNSPEC_SFUNC         5)
120   (UNSPEC_PIC           6)
121   (UNSPEC_GOT           7)
122   (UNSPEC_GOTOFF        8)
123   (UNSPEC_PLT           9)
124   (UNSPEC_CALLER        10)
125   (UNSPEC_GOTPLT        11)
126   (UNSPEC_ICACHE        12)
127   (UNSPEC_INIT_TRAMP    13)
128   (UNSPEC_FCOSA         14)
129   (UNSPEC_FSRRA         15)
130   (UNSPEC_FSINA         16)
131   (UNSPEC_NSB           17)
132   (UNSPEC_ALLOCO        18)
133   (UNSPEC_TLSGD         20)
134   (UNSPEC_TLSLDM        21)
135   (UNSPEC_TLSIE         22)
136   (UNSPEC_DTPOFF        23)
137   (UNSPEC_GOTTPOFF      24)
138   (UNSPEC_TPOFF         25)
139   (UNSPEC_RA            26)
140   (UNSPEC_DIV_INV_M0    30)
141   (UNSPEC_DIV_INV_M1    31)
142   (UNSPEC_DIV_INV_M2    32)
143   (UNSPEC_DIV_INV_M3    33)
144   (UNSPEC_DIV_INV20     34)
145   (UNSPEC_DIV_INV_TABLE 37)
146   (UNSPEC_ASHIFTRT      35)
147   (UNSPEC_THUNK         36)
148   (UNSPEC_CHKADD        38)
149   (UNSPEC_SP_SET        40)
150   (UNSPEC_SP_TEST       41)
151   (UNSPEC_MOVUA         42)
153   ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
154   ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
155   (UNSPEC_EXTRACT_S16   43)
156   (UNSPEC_EXTRACT_U16   44)
158   ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
159   (UNSPEC_SYMOFF        45)
161   ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
162   (UNSPEC_PCREL_SYMOFF  46)
164   ;; Misc builtins
165   (UNSPEC_BUILTIN_STRLEN 47)
167   ;; These are used with unspec_volatile.
168   (UNSPECV_BLOCKAGE     0)
169   (UNSPECV_ALIGN        1)
170   (UNSPECV_CONST2       2)
171   (UNSPECV_CONST4       4)
172   (UNSPECV_CONST8       6)
173   (UNSPECV_WINDOW_END   10)
174   (UNSPECV_CONST_END    11)
175   (UNSPECV_EH_RETURN    12)
176   (UNSPECV_GBR          13)
177   (UNSPECV_SP_SWITCH_B  14)
178   (UNSPECV_SP_SWITCH_E  15)
181 ;; -------------------------------------------------------------------------
182 ;; Attributes
183 ;; -------------------------------------------------------------------------
185 ;; Target CPU.
187 (define_attr "cpu"
188  "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
189   (const (symbol_ref "sh_cpu_attr")))
191 (define_attr "endian" "big,little"
192  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
193                       (const_string "little") (const_string "big"))))
195 ;; Indicate if the default fpu mode is single precision.
196 (define_attr "fpu_single" "yes,no"
197   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
198                        (const_string "yes") (const_string "no"))))
200 (define_attr "fmovd" "yes,no"
201   (const (if_then_else (symbol_ref "TARGET_FMOVD")
202                        (const_string "yes") (const_string "no"))))
203 ;; pipeline model
204 (define_attr "pipe_model" "sh1,sh4,sh5media"
205   (const
206    (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
207           (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
208          (const_string "sh1"))))
210 ;; cbranch      conditional branch instructions
211 ;; jump         unconditional jumps
212 ;; arith        ordinary arithmetic
213 ;; arith3       a compound insn that behaves similarly to a sequence of
214 ;;              three insns of type arith
215 ;; arith3b      like above, but might end with a redirected branch
216 ;; load         from memory
217 ;; load_si      Likewise, SImode variant for general register.
218 ;; fload        Likewise, but load to fp register.
219 ;; store        to memory
220 ;; fstore       floating point register to memory
221 ;; move         general purpose register to register
222 ;; movi8        8-bit immediate to general purpose register
223 ;; mt_group     other sh4 mt instructions
224 ;; fmove        register to register, floating point
225 ;; smpy         word precision integer multiply
226 ;; dmpy         longword or doublelongword precision integer multiply
227 ;; return       rts
228 ;; pload        load of pr reg, which can't be put into delay slot of rts
229 ;; prset        copy register to pr reg, ditto
230 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
231 ;; prget        copy pr to register, ditto
232 ;; pcload       pc relative load of constant value
233 ;; pcfload      Likewise, but load to fp register.
234 ;; pcload_si    Likewise, SImode variant for general register.
235 ;; rte          return from exception
236 ;; sfunc        special function call with known used registers
237 ;; call         function call
238 ;; fp           floating point
239 ;; fpscr_toggle toggle a bit in the fpscr
240 ;; fdiv         floating point divide (or square root)
241 ;; gp_fpul      move from general purpose register to fpul
242 ;; fpul_gp      move from fpul to general purpose register
243 ;; mac_gp       move from mac[lh] to general purpose register
244 ;; gp_mac       move from general purpose register to mac[lh]
245 ;; mac_mem      move from mac[lh] to memory
246 ;; mem_mac      move from memory to mac[lh]
247 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
248 ;; ftrc_s       fix_truncsfsi2_i4
249 ;; dfdiv        double precision floating point divide (or square root)
250 ;; cwb          ic_invalidate_line_i
251 ;; movua        SH4a unaligned load
252 ;; fsrra        square root reciprocal approximate
253 ;; fsca         sine and cosine approximate
254 ;; tls_load     load TLS related address
255 ;; arith_media  SHmedia arithmetic, logical, and shift instructions
256 ;; cbranch_media SHmedia conditional branch instructions
257 ;; cmp_media    SHmedia compare instructions
258 ;; dfdiv_media  SHmedia double precision divide and square root
259 ;; dfmul_media  SHmedia double precision multiply instruction
260 ;; dfparith_media SHmedia double precision floating point arithmetic
261 ;; dfpconv_media SHmedia double precision floating point conversions
262 ;; dmpy_media   SHmedia longword multiply
263 ;; fcmp_media   SHmedia floating point compare instructions
264 ;; fdiv_media   SHmedia single precision divide and square root
265 ;; fload_media  SHmedia floating point register load instructions
266 ;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
267 ;; fparith_media SHmedia single precision floating point arithmetic
268 ;; fpconv_media SHmedia single precision floating point conversions
269 ;; fstore_media SHmedia floating point register store instructions
270 ;; gettr_media  SHmedia gettr instruction
271 ;; invalidate_line_media SHmedia invalidate_line sequence
272 ;; jump_media   SHmedia unconditional branch instructions
273 ;; load_media   SHmedia general register load instructions
274 ;; pt_media     SHmedia pt instruction (expanded by assembler)
275 ;; ptabs_media  SHmedia ptabs instruction
276 ;; store_media  SHmedia general register store instructions
277 ;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
278 ;; mac_media    SHmedia mac-style fixed point operations
279 ;; d2mpy_media  SHmedia: two 32-bit integer multiplies
280 ;; atrans_media SHmedia approximate transcendental functions
281 ;; ustore_media SHmedia unaligned stores
282 ;; nil          no-op move, will be deleted.
284 (define_attr "type"
285  "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
286   fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
287   prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
288   dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
289   gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
290   arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
291   dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
292   fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
293   jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
294   d2mpy_media,atrans_media,ustore_media,nil,other"
295   (const_string "other"))
297 ;; We define a new attribute namely "insn_class".We use
298 ;; this for the DFA based pipeline description.
300 ;; mt_group      SH4 "mt" group instructions.
302 ;; ex_group      SH4 "ex" group instructions.
304 ;; ls_group      SH4 "ls" group instructions.
306 (define_attr "insn_class"
307   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
308   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
309          (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
310          (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
311                           store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
312          (eq_attr "type" "cbranch,jump") (const_string "br_group")
313          (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
314            (const_string "fe_group")
315          (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
316                           prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
317                           gp_mac,mac_mem,mem_mac") (const_string "co_group")]
318         (const_string "none")))
320 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
321 ;; so these do not belong in an insn group, although they are modeled
322 ;; with their own define_insn_reservations.
324 ;; Indicate what precision must be selected in fpscr for this insn, if any.
325 (define_attr "fp_mode" "single,double,none" (const_string "none"))
327 ;; Indicate if the fpu mode is set by this instruction
328 ;; "unknown" must have the value as "none" in fp_mode, and means
329 ;; that the instruction/abi has left the processor in an unknown
330 ;; state.
331 ;; "none" means that nothing has changed and no mode is set.
332 ;; This attribute is only used for the Renesas ABI.
333 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
335 ; If a conditional branch destination is within -252..258 bytes away
336 ; from the instruction it can be 2 bytes long.  Something in the
337 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
338 ; branches are initially assumed to be 16 bytes long.
339 ; In machine_dependent_reorg, we split all branches that are longer than
340 ; 2 bytes.
342 ;; The maximum range used for SImode constant pool entries is 1018.  A final
343 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
344 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
345 ;; instruction around the pool table, 2 bytes of alignment before the table,
346 ;; and 30 bytes of alignment after the table.  That gives a maximum total
347 ;; pool size of 1058 bytes.
348 ;; Worst case code/pool content size ratio is 1:2 (using asms).
349 ;; Thus, in the worst case, there is one instruction in front of a maximum
350 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
351 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
352 ;; If we have a forward branch, the initial table will be put after the
353 ;; unconditional branch.
355 ;; ??? We could do much better by keeping track of the actual pcloads within
356 ;; the branch range and in the pcload range in front of the branch range.
358 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
359 ;; inside an le.
360 (define_attr "short_cbranch_p" "no,yes"
361   (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
362          (const_string "no")
363          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
364          (const_string "yes")
365          (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
366          (const_string "no")
367          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
368          (const_string "yes")
369          ] (const_string "no")))
371 (define_attr "med_branch_p" "no,yes"
372   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
373               (const_int 1988))
374          (const_string "yes")
375          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
376          (const_string "no")
377          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
378               (const_int 8186))
379          (const_string "yes")
380          ] (const_string "no")))
382 (define_attr "med_cbranch_p" "no,yes"
383   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
384               (const_int 1986))
385          (const_string "yes")
386          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
387          (const_string "no")
388          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
389                (const_int 8184))
390          (const_string "yes")
391          ] (const_string "no")))
393 (define_attr "braf_branch_p" "no,yes"
394   (cond [(match_test "! TARGET_SH2")
395          (const_string "no")
396          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
397               (const_int 20660))
398          (const_string "yes")
399          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
400          (const_string "no")
401          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
402               (const_int 65530))
403          (const_string "yes")
404          ] (const_string "no")))
406 (define_attr "braf_cbranch_p" "no,yes"
407   (cond [(match_test "! TARGET_SH2")
408          (const_string "no")
409          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
410               (const_int 20658))
411          (const_string "yes")
412          (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
413          (const_string "no")
414          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
415               (const_int 65528))
416          (const_string "yes")
417          ] (const_string "no")))
419 ;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
420 ;; For wider ranges, we need a combination of a code and a data part.
421 ;; If we can get a scratch register for a long range jump, the code
422 ;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
423 ;; If the jump is in the range -32764..32770, the data part can be 2 bytes
424 ;; long; otherwise, it must be 6 bytes long.
426 ;; All other instructions are two bytes long by default.
428 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
429 ;; but getattrtab doesn't understand this.
430 (define_attr "length" ""
431   (cond [(eq_attr "type" "cbranch")
432          (cond [(eq_attr "short_cbranch_p" "yes")
433                 (const_int 2)
434                 (eq_attr "med_cbranch_p" "yes")
435                 (const_int 6)
436                 (eq_attr "braf_cbranch_p" "yes")
437                 (const_int 12)
438 ;; ??? using pc is not computed transitively.
439                 (ne (match_dup 0) (match_dup 0))
440                 (const_int 14)
441                 (match_test "flag_pic")
442                 (const_int 24)
443                 ] (const_int 16))
444          (eq_attr "type" "jump")
445          (cond [(eq_attr "med_branch_p" "yes")
446                 (const_int 2)
447                 (and (match_test "prev_nonnote_insn (insn)")
448                      (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
449                               (symbol_ref "INSN"))
450                           (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
451                               (symbol_ref "code_for_indirect_jump_scratch"))))
452                 (cond [(eq_attr "braf_branch_p" "yes")
453                        (const_int 6)
454                        (not (match_test "flag_pic"))
455                        (const_int 10)
456                        (match_test "TARGET_SH2")
457                        (const_int 10)] (const_int 18))
458                 (eq_attr "braf_branch_p" "yes")
459                 (const_int 10)
460 ;; ??? using pc is not computed transitively.
461                 (ne (match_dup 0) (match_dup 0))
462                 (const_int 12)
463                 (match_test "flag_pic")
464                 (const_int 22)
465                 ] (const_int 14))
466          (eq_attr "type" "pt_media")
467          (if_then_else (match_test "TARGET_SHMEDIA64")
468                        (const_int 20) (const_int 12))
469          (and (eq_attr "type" "jump_media")
470               (match_test "TARGET_SH5_CUT2_WORKAROUND"))
471          (const_int 8)
472          ] (if_then_else (match_test "TARGET_SHMEDIA")
473                          (const_int 4)
474                          (const_int 2))))
476 ;; DFA descriptions for the pipelines
478 (include "sh1.md")
479 (include "shmedia.md")
480 (include "sh4.md")
482 (include "iterators.md")
483 (include "predicates.md")
484 (include "constraints.md")
486 ;; Definitions for filling delay slots
488 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
490 (define_attr "banked" "yes,no" 
491         (cond [(match_test "sh_loads_bankedreg_p (insn)")
492                (const_string "yes")]
493               (const_string "no")))
495 ;; ??? This should be (nil) instead of (const_int 0)
496 (define_attr "hit_stack" "yes,no"
497         (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
498                (const_string "no")]
499               (const_string "yes")))
501 (define_attr "interrupt_function" "no,yes"
502   (const (symbol_ref "current_function_interrupt")))
504 (define_attr "in_delay_slot" "yes,no"
505   (cond [(eq_attr "type" "cbranch") (const_string "no")
506          (eq_attr "type" "pcload,pcload_si") (const_string "no")
507          (eq_attr "needs_delay_slot" "yes") (const_string "no")
508          (eq_attr "length" "2") (const_string "yes")
509          ] (const_string "no")))
511 (define_attr "cond_delay_slot" "yes,no"
512   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
513          ] (const_string "no")))
515 (define_attr "is_sfunc" ""
516   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
518 (define_attr "is_mac_media" ""
519   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
521 (define_attr "branch_zero" "yes,no"
522   (cond [(eq_attr "type" "!cbranch") (const_string "no")
523          (ne (symbol_ref "(next_active_insn (insn)\
524                            == (prev_active_insn\
525                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
526                           && get_attr_length (next_active_insn (insn)) == 2")
527              (const_int 0))
528          (const_string "yes")]
529         (const_string "no")))
531 ;; SH4 Double-precision computation with double-precision result -
532 ;; the two halves are ready at different times.
533 (define_attr "dfp_comp" "yes,no"
534   (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
535         (const_string "no")))
537 ;; Insns for which the latency of a preceding fp insn is decreased by one.
538 (define_attr "late_fp_use" "yes,no" (const_string "no"))
539 ;; And feeding insns for which this relevant.
540 (define_attr "any_fp_comp" "yes,no"
541   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
542          (const_string "yes")]
543         (const_string "no")))
545 (define_attr "any_int_load" "yes,no"
546   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
547          (const_string "yes")]
548         (const_string "no")))
550 (define_attr "highpart" "user, ignore, extend, depend, must_split"
551   (const_string "user"))
553 (define_delay
554   (eq_attr "needs_delay_slot" "yes")
555   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
557 ;; Since a normal return (rts) implicitly uses the PR register,
558 ;; we can't allow PR register loads in an rts delay slot.
559 ;; On the SH1* and SH2*, the rte instruction reads the return pc from the
560 ;; stack, and thus we can't put a pop instruction in its delay slot.
561 ;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
562 ;; pop instruction can go in the delay slot, unless it references a banked
563 ;; register (the register bank is switched by rte).
564 (define_delay
565   (eq_attr "type" "return")
566   [(and (eq_attr "in_delay_slot" "yes")
567         (ior (and (eq_attr "interrupt_function" "no")
568                   (eq_attr "type" "!pload,prset"))
569              (and (eq_attr "interrupt_function" "yes")
570                   (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
571                   (eq_attr "banked" "no"))))
572    (nil) (nil)])
574 ;; Since a call implicitly uses the PR register, we can't allow
575 ;; a PR register store in a jsr delay slot.
577 (define_delay
578   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
579   [(and (eq_attr "in_delay_slot" "yes")
580         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
582 ;; Say that we have annulled true branches, since this gives smaller and
583 ;; faster code when branches are predicted as not taken.
585 ;; ??? The non-annulled condition should really be "in_delay_slot",
586 ;; but insns that can be filled in non-annulled get priority over insns
587 ;; that can only be filled in anulled.
589 (define_delay
590   (and (eq_attr "type" "cbranch")
591        (match_test "TARGET_SH2"))
592   ;; SH2e has a hardware bug that pretty much prohibits the use of
593   ;; annulled delay slots.
594   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
595                                           (not (eq_attr "cpu" "sh2e"))) (nil)])
597 ;; -------------------------------------------------------------------------
598 ;; SImode signed integer comparisons
599 ;; -------------------------------------------------------------------------
601 ;; Various patterns to generate the TST #imm, R0 instruction.
602 ;; Although this adds some pressure on the R0 register, it can potentially
603 ;; result in faster code, even if the operand has to be moved to R0 first.
604 ;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group 
605 ;; instructions and thus will be executed in parallel.  On SH4A TST #imm, R0
606 ;; is an EX group instruction but still can be executed in parallel with the
607 ;; MT group MOV Rm, Rn instruction.
609 ;; Usual TST #imm, R0 patterns for SI, HI and QI
610 ;; This is usually used for bit patterns other than contiguous bits 
611 ;; and single bits.
612 (define_insn "tstsi_t"
613   [(set (reg:SI T_REG)
614         (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
615                        (match_operand:SI 1 "logical_operand" "K08,r"))
616                (const_int 0)))]
617   "TARGET_SH1"
618   "tst  %1,%0"
619   [(set_attr "type" "mt_group")])
621 (define_insn "tsthi_t"
622   [(set (reg:SI T_REG)
623         (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
624                                   (match_operand 1 "const_int_operand")) 0)
625                (const_int 0)))]
626   "TARGET_SH1
627    && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
628   "tst  %1,%0"
629   [(set_attr "type" "mt_group")])
631 (define_insn "tstqi_t"
632   [(set (reg:SI T_REG)
633         (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
634                                   (match_operand 1 "const_int_operand")) 0)
635                (const_int 0)))]
636   "TARGET_SH1
637    && (CONST_OK_FOR_K08 (INTVAL (operands[1])) 
638        || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
640   operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
641   return "tst   %1,%0";
643   [(set_attr "type" "mt_group")])
645 ;; Test low QI subreg against zero.
646 ;; This avoids unnecessary zero extension before the test.
647 (define_insn "*tstqi_t_zero"
648   [(set (reg:SI T_REG)
649         (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
650   "TARGET_SH1"
651   "tst  #255,%0"
652   [(set_attr "type" "mt_group")])
654 ;; This pattern might be risky because it also tests the upper bits and not
655 ;; only the subreg.  However, it seems that combine will get to this only
656 ;; when testing sign/zero extended values.  In this case the extended upper
657 ;; bits do not matter.
658 (define_insn "*tst<mode>_t_zero"
659   [(set (reg:SI T_REG)
660         (eq:SI
661           (subreg:QIHI
662             (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
663                     (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_le>)
664           (const_int 0)))]
665   "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
666   "tst  %0,%1"
667   [(set_attr "type" "mt_group")])
669 (define_insn "*tst<mode>_t_zero"
670   [(set (reg:SI T_REG)
671         (eq:SI
672           (subreg:QIHI
673             (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
674                     (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
675           (const_int 0)))]
676   "TARGET_SH1 && TARGET_BIG_ENDIAN"
677   "tst  %0,%1"
678   [(set_attr "type" "mt_group")])
680 ;; Extract LSB, negate and store in T bit.
681 (define_insn "tstsi_t_and_not"
682   [(set (reg:SI T_REG)
683          (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
684                  (const_int 1)))]
685   "TARGET_SH1"
686   "tst  #1,%0"
687   [(set_attr "type" "mt_group")])
689 ;; Extract contiguous bits and compare them against zero.
690 (define_insn "tst<mode>_t_zero_extract_eq"
691   [(set (reg:SI T_REG)
692         (eq:SI (zero_extract:SI (match_operand:QIHISIDI 0 "logical_operand" "z")
693                                 (match_operand:SI 1 "const_int_operand")
694                                 (match_operand:SI 2 "const_int_operand"))
695                (const_int 0)))]
696   "TARGET_SH1
697    && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
699   operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
700   return "tst   %1,%0";
702   [(set_attr "type" "mt_group")])
704 ;; This split is required when testing bits in a QI subreg.
705 (define_split
706   [(set (reg:SI T_REG)
707         (eq:SI
708           (if_then_else:SI
709             (zero_extract:SI (match_operand 0 "logical_operand")
710                              (match_operand 1 "const_int_operand")
711                              (match_operand 2 "const_int_operand"))
712             (match_operand 3 "const_int_operand")
713             (const_int 0))
714           (const_int 0)))]
715   "TARGET_SH1
716    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
717    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
718   [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
719                               (const_int 0)))]
721   if (GET_MODE (operands[0]) == QImode)
722     operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
725 ;; Extract single bit, negate and store it in the T bit.
726 ;; Not used for SH4A.
727 (define_insn "tstsi_t_zero_extract_xor"
728   [(set (reg:SI T_REG)
729         (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
730                                  (match_operand:SI 3 "const_int_operand"))
731                          (match_operand:SI 1 "const_int_operand")
732                          (match_operand:SI 2 "const_int_operand")))]
733   "TARGET_SH1
734    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
735    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
736   "tst  %3,%0"
737   [(set_attr "type" "mt_group")])
739 ;; Extract single bit, negate and store it in the T bit.
740 ;; Used for SH4A little endian.
741 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
742   [(set (reg:SI T_REG)
743         (zero_extract:SI
744          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
745                             (match_operand:SI 3 "const_int_operand")) 0)
746          (match_operand:SI 1 "const_int_operand")
747          (match_operand:SI 2 "const_int_operand")))]
748   "TARGET_SH1 && TARGET_LITTLE_ENDIAN
749    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
750       == (INTVAL (operands[3]) & 255)
751    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
753   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
754   return "tst   %3,%0";
756   [(set_attr "type" "mt_group")])
758 ;; Extract single bit, negate and store it in the T bit.
759 ;; Used for SH4A big endian.
760 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
761   [(set (reg:SI T_REG)
762         (zero_extract:SI
763          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
764                             (match_operand:SI 3 "const_int_operand")) 3)
765          (match_operand:SI 1 "const_int_operand")
766          (match_operand:SI 2 "const_int_operand")))]
767   "TARGET_SH1 && TARGET_BIG_ENDIAN
768    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
769       == (INTVAL (operands[3]) & 255)
770    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
772   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
773   return "tst   %3,%0";
775   [(set_attr "type" "mt_group")])
777 (define_insn "cmpeqsi_t"
778   [(set (reg:SI T_REG)
779         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
780                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
781   "TARGET_SH1"
782   "@
783         tst     %0,%0
784         cmp/eq  %1,%0
785         cmp/eq  %1,%0"
786   [(set_attr "type" "mt_group")])
788 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
789 ;; pattern by itself.  What this actually does is:
790 ;;      x == 0: (1 >> 0-0) & 1 = 1
791 ;;      x != 0: (1 >> 0-x) & 1 = 0
792 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
793 (define_insn_and_split "*cmpeqsi_t"
794   [(set (reg:SI T_REG)
795         (and:SI (lshiftrt:SI
796                   (const_int 1)
797                   (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
798                 (const_int 1)))]
799   "TARGET_SH1"
800   "#"
801   "&& 1"
802   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
804 (define_insn "cmpgtsi_t"
805   [(set (reg:SI T_REG)
806         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
807                (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
808   "TARGET_SH1"
809   "@
810         cmp/pl  %0
811         cmp/gt  %1,%0"
812   [(set_attr "type" "mt_group")])
814 (define_insn "cmpgesi_t"
815   [(set (reg:SI T_REG)
816         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
817                (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
818   "TARGET_SH1"
819   "@
820         cmp/pz  %0
821         cmp/ge  %1,%0"
822   [(set_attr "type" "mt_group")])
824 ;; FIXME: This is actually wrong.  There is no way to literally move a
825 ;; general reg to t reg.  Luckily, it seems that this pattern will be only
826 ;; used when the general reg is known be either '0' or '1' during combine.
827 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
828 ;; Due to interactions with other patterns, combine fails to pick the latter
829 ;; and invert the dependent logic.
830 (define_insn "*negtstsi"
831   [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
832   "TARGET_SH1"
833   "cmp/pl       %0"
834   [(set_attr "type" "mt_group")])
836 ;; Some integer sign comparison patterns can be realized with the div0s insn.
837 ;;      div0s   Rm,Rn           T = (Rm >> 31) ^ (Rn >> 31)
838 (define_insn "cmp_div0s_0"
839   [(set (reg:SI T_REG)
840         (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
841                              (match_operand:SI 1 "arith_reg_operand" "r"))
842                      (const_int 31)))]
843   "TARGET_SH1"
844   "div0s        %0,%1"
845   [(set_attr "type" "arith")])
847 (define_insn "cmp_div0s_1"
848   [(set (reg:SI T_REG)
849         (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
850                        (match_operand:SI 1 "arith_reg_operand" "r"))
851                (const_int 0)))]
852   "TARGET_SH1"
853   "div0s        %0,%1"
854   [(set_attr "type" "arith")])
856 (define_insn_and_split "*cmp_div0s_0"
857   [(set (match_operand:SI 0 "arith_reg_dest" "")
858         (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
859                              (match_operand:SI 2 "arith_reg_operand" ""))
860                      (const_int 31)))
861    (clobber (reg:SI T_REG))]
862   "TARGET_SH1"
863   "#"
864   "&& 1"
865   [(set (reg:SI T_REG)
866         (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
867    (set (match_dup 0) (reg:SI T_REG))])
869 (define_insn "*cmp_div0s_0"
870   [(set (reg:SI T_REG)
871         (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
872                             (const_int 31))
873                (ge:SI (match_operand:SI 1 "arith_reg_operand")
874                       (const_int 0))))]
875   "TARGET_SH1"
876   "div0s        %0,%1"
877   [(set_attr "type" "arith")])
879 (define_insn_and_split "*cmp_div0s_1"
880   [(set (match_operand:SI 0 "arith_reg_dest" "")
881         (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
882                        (match_operand:SI 2 "arith_reg_operand" ""))
883                (const_int 0)))
884    (clobber (reg:SI T_REG))]
885   "TARGET_SH1"
886   "#"
887   "&& can_create_pseudo_p ()"
888   [(const_int 0)]
889 ;; We have to go through the movnegt expander here which will handle the
890 ;; SH2A vs non-SH2A cases.
892   emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
893   emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
894   DONE;
897 (define_insn_and_split "*cmp_div0s_1"
898   [(set (reg:SI T_REG)
899         (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
900                        (match_operand:SI 1 "arith_reg_operand" ""))
901                (const_int 0)))]
902   "TARGET_SH1"
903   "#"
904   "&& can_create_pseudo_p ()"
905   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
906                               (const_int 0)))
907    (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
909 (define_insn_and_split "*cmp_div0s_1"
910   [(set (reg:SI T_REG)
911         (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
912                             (const_int 31))
913                (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
914                             (const_int 31))))]
915   "TARGET_SH1"
916   "#"
917   "&& can_create_pseudo_p ()"
918   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
919                               (const_int 0)))
920    (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
922 ;; -------------------------------------------------------------------------
923 ;; SImode compare and branch
924 ;; -------------------------------------------------------------------------
926 (define_expand "cbranchsi4"
927   [(set (pc)
928         (if_then_else (match_operator 0 "comparison_operator"
929                         [(match_operand:SI 1 "arith_operand" "")
930                          (match_operand:SI 2 "arith_operand" "")])
931                       (label_ref (match_operand 3 "" ""))
932                       (pc)))
933    (clobber (reg:SI T_REG))]
934   ""
936   if (TARGET_SHMEDIA)
937     emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
938                                            operands[2], operands[3]));
939   else
940     expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
942   DONE;
945 ;; Combine patterns to invert compare and branch operations for which we
946 ;; don't have actual comparison insns.  These patterns are used in cases
947 ;; which appear after the initial cbranchsi expansion, which also does
948 ;; some condition inversion.
949 (define_split
950   [(set (pc)
951         (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
952                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
953                       (label_ref (match_operand 2))
954                       (pc)))
955    (clobber (reg:SI T_REG))]
956   "TARGET_SH1"
957   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
958    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
959                            (label_ref (match_dup 2))
960                            (pc)))])
962 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
963 ;; and SH2A combine fails to simplify this pattern by itself.
964 ;; What this actually does is:
965 ;;      x == 0: (1 >> 0-0) & 1 = 1
966 ;;      x != 0: (1 >> 0-x) & 1 = 0
967 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
968 (define_split
969   [(set (pc)
970         (if_then_else
971           (eq (and:SI (lshiftrt:SI
972                         (const_int 1)
973                         (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
974                       (const_int 1))
975               (const_int 0))
976           (label_ref (match_operand 2))
977           (pc)))
978    (clobber (reg:SI T_REG))]
979   "TARGET_SH1"
980   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
981    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
982                            (label_ref (match_dup 2))
983                            (pc)))])
985 ;; FIXME: These could probably use code iterators for the compare op.
986 (define_split
987   [(set (pc)
988         (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
989                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
990                       (label_ref (match_operand 2))
991                       (pc)))
992    (clobber (reg:SI T_REG))]
993   "TARGET_SH1"
994   [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
995    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
996                            (label_ref (match_dup 2))
997                            (pc)))])
999 (define_split
1000   [(set (pc)
1001         (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
1002                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1003                       (label_ref (match_operand 2))
1004                       (pc)))
1005    (clobber (reg:SI T_REG))]
1006   "TARGET_SH1"
1007   [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
1008    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1009                            (label_ref (match_dup 2))
1010                            (pc)))])
1012 (define_split
1013   [(set (pc)
1014         (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
1015                            (match_operand:SI 1 "arith_reg_operand" ""))
1016                       (label_ref (match_operand 2))
1017                       (pc)))
1018    (clobber (reg:SI T_REG))]
1019   "TARGET_SH1"
1020   [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
1021    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1022                            (label_ref (match_dup 2))
1023                            (pc)))])
1025 (define_split
1026   [(set (pc)
1027         (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1028                            (match_operand:SI 1 "arith_reg_operand" ""))
1029                       (label_ref (match_operand 2))
1030                       (pc)))
1031    (clobber (reg:SI T_REG))]
1032   "TARGET_SH1"
1033   [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1034    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1035                            (label_ref (match_dup 2))
1036                            (pc)))])
1038 ;; Compare and branch combine patterns for div0s comparisons.
1039 (define_insn_and_split "*cbranch_div0s"
1040   [(set (pc)
1041         (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1042                                   (match_operand:SI 1 "arith_reg_operand" ""))
1043                           (const_int 0))
1044                       (label_ref (match_operand 2))
1045                       (pc)))
1046    (clobber (reg:SI T_REG))]
1047   "TARGET_SH1"
1048   "#"
1049   "&& 1"
1050   [(set (reg:SI T_REG)
1051         (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1052    (set (pc)
1053         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1054                       (label_ref (match_dup 2))
1055                       (pc)))])
1057 (define_insn_and_split "*cbranch_div0s"
1058   [(set (pc)
1059         (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1060                                   (match_operand:SI 1 "arith_reg_operand" ""))
1061                           (const_int 0))
1062                       (label_ref (match_operand 2))
1063                       (pc)))
1064    (clobber (reg:SI T_REG))]
1065   "TARGET_SH1"
1066   "#"
1067   "&& 1"
1068   [(set (reg:SI T_REG)
1069         (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1070    (set (pc)
1071         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1072                       (label_ref (match_dup 2))
1073                       (pc)))])
1075 ;; Conditional move combine pattern for div0s comparisons.
1076 ;; This is used when TARGET_PRETEND_CMOVE is in effect.
1077 (define_insn_and_split "*movsicc_div0s"
1078   [(set (match_operand:SI 0 "arith_reg_dest" "")
1079         (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1080                                      (match_operand:SI 2 "arith_reg_operand" ""))
1081                              (const_int 0))
1082                          (match_operand:SI 3 "arith_reg_operand" "")
1083                          (match_operand:SI 4 "general_movsrc_operand" "")))
1084    (clobber (reg:SI T_REG))]
1085   "TARGET_PRETEND_CMOVE"
1086   "#"
1087   "&& 1"
1088   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1089                               (const_int 0)))
1090    (set (match_dup 0)
1091         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1092                       (match_dup 4)
1093                       (match_dup 3)))])
1095 (define_insn_and_split "*movsicc_div0s"
1096   [(set (match_operand:SI 0 "arith_reg_dest")
1097         (if_then_else:SI (eq (lshiftrt:SI
1098                                 (match_operand:SI 1 "arith_reg_operand")
1099                                 (const_int 31))
1100                              (lshiftrt:SI
1101                                 (match_operand:SI 2 "arith_reg_operand")
1102                                 (const_int 31)))
1103                          (match_operand:SI 3 "arith_reg_operand")
1104                          (match_operand:SI 4 "general_movsrc_operand")))
1105    (clobber (reg:SI T_REG))]
1106    "TARGET_PRETEND_CMOVE"
1107    "#"
1108    "&& 1"
1109   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1110                               (const_int 0)))
1111    (set (match_dup 0)
1112         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1113                       (match_dup 4)
1114                       (match_dup 3)))])
1116 ;; -------------------------------------------------------------------------
1117 ;; SImode unsigned integer comparisons
1118 ;; -------------------------------------------------------------------------
1120 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1121 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1122 ;; might remain and we have to handle them.  If the '>= 0' case wasn't
1123 ;; handled here, something else would just load a '0' into the second operand
1124 ;; and do the comparison.  We can do slightly better by just setting the
1125 ;; T bit to '1'.
1126 (define_insn_and_split "cmpgeusi_t"
1127   [(set (reg:SI T_REG)
1128         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1129                 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1130   "TARGET_SH1"
1131   "cmp/hs       %1,%0"
1132   "&& satisfies_constraint_Z (operands[1])"
1133   [(set (reg:SI T_REG) (const_int 1))]
1134   ""
1135   [(set_attr "type" "mt_group")])
1137 (define_insn "cmpgtusi_t"
1138   [(set (reg:SI T_REG)
1139         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1140                 (match_operand:SI 1 "arith_reg_operand" "r")))]
1141   "TARGET_SH1"
1142   "cmp/hi       %1,%0"
1143   [(set_attr "type" "mt_group")])
1145 ;; -------------------------------------------------------------------------
1146 ;; DImode compare and branch
1147 ;; -------------------------------------------------------------------------
1149 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1150 ;; Therefore, we aim to have a set of three branches that go straight to the
1151 ;; destination, i.e. only one of them is taken at any one time.
1152 ;; This mechanism should also be slightly better for the sh4-200.
1154 (define_expand "cbranchdi4"
1155   [(set (pc)
1156         (if_then_else (match_operator 0 "comparison_operator"
1157                         [(match_operand:DI 1 "arith_operand" "")
1158                          (match_operand:DI 2 "arith_operand" "")])
1159                       (label_ref (match_operand 3 "" ""))
1160                       (pc)))
1161    (clobber (match_dup 4))
1162    (clobber (reg:SI T_REG))]
1163   "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1165   enum rtx_code comparison;
1167   if (TARGET_SHMEDIA)
1168     {
1169       emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1170                                              operands[2], operands[3]));
1171       DONE;
1172     }
1173   else if (!TARGET_CBRANCHDI4)
1174     {
1175       sh_emit_compare_and_branch (operands, DImode);
1176       DONE;
1177     }
1178   else
1179     {
1180       if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1181         DONE;
1183       comparison = prepare_cbranch_operands (operands, DImode,
1184                                              LAST_AND_UNUSED_RTX_CODE);
1185       if (comparison != GET_CODE (operands[0]))
1186         operands[0]
1187           = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1188        operands[4] = gen_rtx_SCRATCH (SImode);
1189     }
1192 (define_insn_and_split "cbranchdi4_i"
1193   [(set (pc)
1194         (if_then_else (match_operator 0 "comparison_operator"
1195                         [(match_operand:DI 1 "arith_operand" "r,r")
1196                          (match_operand:DI 2 "arith_operand" "rN,I08")])
1197                       (label_ref (match_operand 3 "" ""))
1198                       (pc)))
1199    (clobber (match_scratch:SI 4 "=X,&r"))
1200    (clobber (reg:SI T_REG))]
1201   "TARGET_CBRANCHDI4"
1202   "#"
1203   "&& reload_completed"
1204   [(pc)]
1206   if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1207     FAIL;
1208   DONE;
1211 ;; -------------------------------------------------------------------------
1212 ;; DImode signed integer comparisons
1213 ;; -------------------------------------------------------------------------
1215 (define_insn ""
1216   [(set (reg:SI T_REG)
1217         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1218                        (match_operand:DI 1 "arith_operand" "r"))
1219                (const_int 0)))]
1220   "TARGET_SH1"
1222   return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1223                               insn, operands);
1225   [(set_attr "length" "6")
1226    (set_attr "type" "arith3b")])
1228 (define_insn "cmpeqdi_t"
1229   [(set (reg:SI T_REG)
1230         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1231                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1232   "TARGET_SH1"
1234   static const char* alt[] =
1235   {
1236        "tst     %S0,%S0"        "\n"
1237     "   bf      0f"             "\n"
1238     "   tst     %R0,%R0"        "\n"
1239     "0:",
1241        "cmp/eq  %S1,%S0"        "\n"
1242     "   bf      0f"             "\n"
1243     "   cmp/eq  %R1,%R0"        "\n"
1244     "0:"
1245   };
1246   return alt[which_alternative];
1248   [(set_attr "length" "6")
1249    (set_attr "type" "arith3b")])
1251 (define_split
1252   [(set (reg:SI T_REG)
1253         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1254                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1255 ;; If we applied this split when not optimizing, it would only be
1256 ;; applied during the machine-dependent reorg, when no new basic blocks
1257 ;; may be created.
1258   "TARGET_SH1 && reload_completed && optimize"
1259   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1260    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1261                            (label_ref (match_dup 6))
1262                            (pc)))
1263    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1264    (match_dup 6)]
1266   operands[2] = gen_highpart (SImode, operands[0]);
1267   operands[3] = operands[1] == const0_rtx
1268                 ? const0_rtx
1269                 : gen_highpart (SImode, operands[1]);
1270   operands[4] = gen_lowpart (SImode, operands[0]);
1271   operands[5] = gen_lowpart (SImode, operands[1]);
1272   operands[6] = gen_label_rtx ();
1275 (define_insn "cmpgtdi_t"
1276   [(set (reg:SI T_REG)
1277         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1278                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1279   "TARGET_SH2"
1281   static const char* alt[] =
1282   {
1283        "cmp/eq  %S1,%S0"        "\n"
1284     "   bf{.|/}s        0f"     "\n"
1285     "   cmp/gt  %S1,%S0"        "\n"
1286     "   cmp/hi  %R1,%R0"        "\n"
1287     "0:",
1289         "tst    %S0,%S0"        "\n"
1290     "   bf{.|/}s        0f"     "\n"
1291     "   cmp/pl  %S0"            "\n"
1292     "   cmp/hi  %S0,%R0"        "\n"
1293     "0:"
1294   };
1295   return alt[which_alternative];
1297   [(set_attr "length" "8")
1298    (set_attr "type" "arith3")])
1300 (define_insn "cmpgedi_t"
1301   [(set (reg:SI T_REG)
1302         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1303                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1304   "TARGET_SH2"
1306   static const char* alt[] =
1307   {
1308        "cmp/eq  %S1,%S0"        "\n"
1309     "   bf{.|/}s        0f"     "\n"
1310     "   cmp/ge  %S1,%S0"        "\n"
1311     "   cmp/hs  %R1,%R0"        "\n"
1312     "0:",
1314        "cmp/pz  %S0"
1315   };
1316   return alt[which_alternative];
1318   [(set_attr "length" "8,2")
1319    (set_attr "type" "arith3,mt_group")])
1321 ;; -------------------------------------------------------------------------
1322 ;; DImode unsigned integer comparisons
1323 ;; -------------------------------------------------------------------------
1325 (define_insn "cmpgeudi_t"
1326   [(set (reg:SI T_REG)
1327         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1328                 (match_operand:DI 1 "arith_reg_operand" "r")))]
1329   "TARGET_SH2"
1331   return       "cmp/eq  %S1,%S0"        "\n"
1332          "      bf{.|/}s        0f"     "\n"
1333          "      cmp/hs  %S1,%S0"        "\n"
1334          "      cmp/hs  %R1,%R0"        "\n"
1335          "0:";
1337   [(set_attr "length" "8")
1338    (set_attr "type" "arith3")])
1340 (define_insn "cmpgtudi_t"
1341   [(set (reg:SI T_REG)
1342         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1343                 (match_operand:DI 1 "arith_reg_operand" "r")))]
1344   "TARGET_SH2"
1346   return       "cmp/eq  %S1,%S0"        "\n"
1347          "      bf{.|/}s        0f"     "\n"
1348          "      cmp/hi  %S1,%S0"        "\n"
1349          "      cmp/hi  %R1,%R0"        "\n"
1350          "0:";
1352   [(set_attr "length" "8")
1353    (set_attr "type" "arith3")])
1355 (define_insn "cmpeqsi_media"
1356   [(set (match_operand:SI 0 "register_operand" "=r")
1357         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1358                (match_operand:SI 2 "cmp_operand" "Nr")))]
1359   "TARGET_SHMEDIA"
1360   "cmpeq        %1, %N2, %0"
1361   [(set_attr "type" "cmp_media")])
1363 (define_insn "cmpeqdi_media"
1364   [(set (match_operand:SI 0 "register_operand" "=r")
1365         (eq:SI (match_operand:DI 1 "register_operand" "%r")
1366                (match_operand:DI 2 "cmp_operand" "Nr")))]
1367   "TARGET_SHMEDIA"
1368   "cmpeq        %1, %N2, %0"
1369   [(set_attr "type" "cmp_media")])
1371 (define_insn "cmpgtsi_media"
1372   [(set (match_operand:SI 0 "register_operand" "=r")
1373         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1374                (match_operand:SI 2 "cmp_operand" "rN")))]
1375   "TARGET_SHMEDIA"
1376   "cmpgt        %N1, %N2, %0"
1377   [(set_attr "type" "cmp_media")])
1379 (define_insn "cmpgtdi_media"
1380   [(set (match_operand:SI 0 "register_operand" "=r")
1381         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1382                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1383   "TARGET_SHMEDIA"
1384   "cmpgt        %N1, %N2, %0"
1385   [(set_attr "type" "cmp_media")])
1387 (define_insn "cmpgtusi_media"
1388   [(set (match_operand:SI 0 "register_operand" "=r")
1389         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1390                 (match_operand:SI 2 "cmp_operand" "rN")))]
1391   "TARGET_SHMEDIA"
1392   "cmpgtu       %N1, %N2, %0"
1393   [(set_attr "type" "cmp_media")])
1395 (define_insn "cmpgtudi_media"
1396   [(set (match_operand:SI 0 "register_operand" "=r")
1397         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1398                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1399   "TARGET_SHMEDIA"
1400   "cmpgtu       %N1, %N2, %0"
1401   [(set_attr "type" "cmp_media")])
1403 ; This pattern is for combine.
1404 (define_insn "*cmpne0sisi_media"
1405   [(set (match_operand:SI 0 "register_operand" "=r")
1406         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1407   "TARGET_SHMEDIA"
1408   "cmpgtu       %1,r63,%0"
1409   [(set_attr "type" "cmp_media")])
1411 ;; -------------------------------------------------------------------------
1412 ;; Conditional move instructions
1413 ;; -------------------------------------------------------------------------
1415 ;; The insn names may seem reversed, but note that cmveq performs the move
1416 ;; if op1 == 0, and cmvne does it if op1 != 0.
1418 (define_insn "movdicc_false"
1419   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1420         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1421                              (const_int 0))
1422          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1423          (match_operand:DI 3 "arith_reg_operand" "0")))]
1424   "TARGET_SHMEDIA"
1425   "cmveq        %1, %N2, %0"
1426   [(set_attr "type" "arith_media")])
1428 (define_insn "movdicc_true"
1429   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1430         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1431                              (const_int 0))
1432          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1433          (match_operand:DI 3 "arith_reg_operand" "0")))]
1434   "TARGET_SHMEDIA"
1435   "cmvne        %1, %N2, %0"
1436   [(set_attr "type" "arith_media")])
1438 (define_peephole2
1439   [(set (match_operand:DI 0 "arith_reg_dest" "")
1440         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1441                            [(match_operand:DI 1 "arith_reg_operand" "")
1442                             (const_int 0)])
1443          (match_operand:DI 2 "arith_reg_dest" "")
1444          (match_dup 0)))
1445    (set (match_dup 2) (match_dup 0))]
1446   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1447   [(set (match_dup 2)
1448         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1450   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1451                                 VOIDmode, operands[1], CONST0_RTX (DImode));
1454 (define_peephole2
1455   [(set (match_operand:DI 0 "general_movdst_operand" "")
1456         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1457    (set (match_operand:DI 2 "arith_reg_dest" "")
1458         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1459                            [(match_operand:DI 3 "arith_reg_operand" "")
1460                             (const_int 0)])
1461          (match_dup 0)
1462          (match_dup 2)))]
1463   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1464   [(set (match_dup 2)
1465         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1466   "")
1468 (define_expand "movdicc"
1469   [(set (match_operand:DI 0 "register_operand" "")
1470         (if_then_else:DI (match_operand 1 "comparison_operator" "")
1471                          (match_operand:DI 2 "register_operand" "")
1472                          (match_operand:DI 3 "register_operand" "")))]
1473   "TARGET_SHMEDIA"
1475   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1476       && GET_MODE (XEXP (operands[1], 0)) == DImode
1477       && XEXP (operands[1], 1) == const0_rtx)
1478     ;
1479   else
1480     {
1481       if (!can_create_pseudo_p ())
1482         FAIL;
1484       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1485                                               GET_CODE (operands[1]),
1486                                               XEXP (operands[1], 0),
1487                                               XEXP (operands[1], 1));
1488       if (!operands[1])
1489         FAIL;
1490     }
1493 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1494 ;; SImode to DImode.
1495 (define_insn "movsicc_false"
1496   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1497         (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1498                           (const_int 0))
1499          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1500          (match_operand:SI 3 "arith_reg_operand" "0")))]
1501   "TARGET_SHMEDIA"
1502   "cmveq        %1, %N2, %0"
1503   [(set_attr "type" "arith_media")])
1505 (define_insn "movsicc_true"
1506   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1507         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1508                           (const_int 0))
1509          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1510          (match_operand:SI 3 "arith_reg_operand" "0")))]
1511   "TARGET_SHMEDIA"
1512   "cmvne        %1, %N2, %0"
1513   [(set_attr "type" "arith_media")])
1515 (define_peephole2
1516   [(set (match_operand:SI 0 "arith_reg_dest" "")
1517         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1518                            [(match_operand:SI 1 "arith_reg_operand" "")
1519                             (const_int 0)])
1520          (match_operand:SI 2 "arith_reg_dest" "")
1521          (match_dup 0)))
1522    (set (match_dup 2) (match_dup 0))]
1523   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1524   [(set (match_dup 2)
1525         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1527   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1528                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1531 (define_peephole2
1532   [(set (match_operand:SI 0 "general_movdst_operand" "")
1533         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1534    (set (match_operand:SI 2 "arith_reg_dest" "")
1535         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1536                            [(match_operand:SI 3 "arith_reg_operand" "")
1537                             (const_int 0)])
1538          (match_dup 0)
1539          (match_dup 2)))]
1540   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1541    && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1542   [(set (match_dup 2)
1543         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1545   replace_rtx (operands[4], operands[0], operands[1]);
1548 (define_peephole2
1549   [(set (match_operand 0 "any_register_operand" "")
1550         (match_operand 1 "any_register_operand" ""))
1551    (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1552    (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1553   "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1554     <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1555    && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1556    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1557    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1558    && ! reg_overlap_mentioned_p (operands[0], operands[3])
1559    && ! reg_overlap_mentioned_p (operands[2], operands[0])
1560    && ! reg_overlap_mentioned_p (operands[0], operands[1])
1561    && (REGNO_REG_CLASS (REGNO (operands[0]))
1562        == REGNO_REG_CLASS (REGNO (operands[2])))
1563    && (REGNO_REG_CLASS (REGNO (operands[1]))
1564        == REGNO_REG_CLASS (REGNO (operands[0])))"
1565   [(set (match_dup 0) (match_dup 3))
1566    (set (match_dup 4) (match_dup 5))]
1568   rtx set1, set2, insn2;
1569   rtx replacements[4];
1571   /* We want to replace occurrences of operands[0] with operands[1] and
1572      operands[2] with operands[0] in operands[4]/operands[5].
1573      Doing just two replace_rtx calls naively would result in the second
1574      replacement undoing all that the first did if operands[1] and operands[2]
1575      are identical, so we must do this simultaneously.  */
1576   replacements[0] = operands[0];
1577   replacements[1] = operands[1];
1578   replacements[2] = operands[2];
1579   replacements[3] = operands[0];
1580   if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1581       || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1582       || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1583     FAIL;
1585   operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1586   replace_n_hard_rtx (operands[4], replacements, 2, 1);
1587   operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1588   /* The operands array is aliased to recog_data.operand, which gets
1589      clobbered by extract_insn, so finish with it now.  */
1590   set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1591   set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1592   /* ??? The last insn might be a jump insn, but the generic peephole2 code
1593      always uses emit_insn.  */
1594   /* Check that we don't violate matching constraints or earlyclobbers.  */
1595   extract_insn (emit_insn (set1));
1596   if (! constrain_operands (1))
1597     goto failure;
1598   insn2 = emit (set2);
1599   if (GET_CODE (insn2) == BARRIER)
1600     goto failure;
1601   extract_insn (insn2);
1602   if (! constrain_operands (1))
1603     {
1604       rtx tmp;
1605     failure:
1606       tmp = replacements[0];
1607       replacements[0] = replacements[1];
1608       replacements[1] = tmp;
1609       tmp = replacements[2];
1610       replacements[2] = replacements[3];
1611       replacements[3] = tmp;
1612       replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1613       replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1614       replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1615       FAIL;
1616     }
1617   DONE;
1620 ;; The register allocator is rather clumsy in handling multi-way conditional
1621 ;; moves, so allow the combiner to make them, and we split them up after
1622 ;; reload.  */
1623 (define_insn_and_split "*movsicc_umin"
1624   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1625         (umin:SI (if_then_else:SI
1626                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1627                        (const_int 0))
1628                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1629                    (match_operand:SI 3 "register_operand" "0"))
1630                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1631    (clobber (match_scratch:SI 5 "=&r"))]
1632   "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1633   "#"
1634   "TARGET_SHMEDIA && reload_completed"
1635   [(pc)]
1637   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1638                                 operands[3]));
1639   emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1640   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1641                                 operands[0]));
1642   DONE;
1645 (define_insn "*movsicc_t_false"
1646   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1647         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1648                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1649                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1650   "TARGET_PRETEND_CMOVE
1651    && (arith_reg_operand (operands[1], SImode)
1652        || (immediate_operand (operands[1], SImode)
1653            && satisfies_constraint_I08 (operands[1])))"
1655   return       "bt      0f"     "\n"
1656          "      mov     %1,%0"  "\n"
1657          "0:";
1659   [(set_attr "type" "mt_group,arith") ;; poor approximation
1660    (set_attr "length" "4")])
1662 (define_insn "*movsicc_t_true"
1663   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1664         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1665                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1666                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1667   "TARGET_PRETEND_CMOVE
1668    && (arith_reg_operand (operands[1], SImode)
1669        || (immediate_operand (operands[1], SImode)
1670            && satisfies_constraint_I08 (operands[1])))"
1672   return       "bf      0f"     "\n"
1673          "      mov     %1,%0"  "\n"
1674          "0:";
1676   [(set_attr "type" "mt_group,arith") ;; poor approximation
1677    (set_attr "length" "4")])
1679 (define_expand "movsicc"
1680   [(set (match_operand:SI 0 "arith_reg_dest" "")
1681         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1682                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1683                          (match_operand:SI 3 "arith_reg_operand" "")))]
1684   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1686   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1687       && GET_MODE (XEXP (operands[1], 0)) == SImode
1688       && (TARGET_SHMEDIA
1689           || (REG_P (XEXP (operands[1], 0))
1690               && REGNO (XEXP (operands[1], 0)) == T_REG))
1691       && XEXP (operands[1], 1) == const0_rtx)
1692     ;
1694   else if (TARGET_PRETEND_CMOVE)
1695     {
1696       enum rtx_code code = GET_CODE (operands[1]);
1697       enum rtx_code new_code = code;
1698       rtx op0 = XEXP (operands[1], 0);
1699       rtx op1 = XEXP (operands[1], 1);
1701       if (! currently_expanding_to_rtl)
1702         FAIL;
1703       switch (code)
1704         {
1705         case LT: case LE: case LEU: case LTU:
1706           if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1707             break;
1708         case NE:
1709           new_code = reverse_condition (code);
1710           break;
1711         case EQ: case GT: case GE: case GEU: case GTU:
1712           break;
1713         default:
1714           FAIL;
1715         }
1716       sh_emit_scc_to_t (new_code, op0, op1);
1717       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1718                                     gen_rtx_REG (SImode, T_REG), const0_rtx);
1719     }
1720   else
1721     {
1722       if (!can_create_pseudo_p ())
1723         FAIL;
1725       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1726                                               GET_CODE (operands[1]),
1727                                               XEXP (operands[1], 0),
1728                                               XEXP (operands[1], 1));
1729       if (!operands[1])
1730         FAIL;
1731     }
1734 (define_expand "movqicc"
1735   [(set (match_operand:QI 0 "register_operand" "")
1736         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1737                          (match_operand:QI 2 "register_operand" "")
1738                          (match_operand:QI 3 "register_operand" "")))]
1739   "TARGET_SHMEDIA"
1741   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1742   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1743   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1744   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1745   DONE;
1748 ;; -------------------------------------------------------------------------
1749 ;; Addition instructions
1750 ;; -------------------------------------------------------------------------
1752 (define_expand "adddi3"
1753   [(set (match_operand:DI 0 "arith_reg_operand")
1754         (plus:DI (match_operand:DI 1 "arith_reg_operand")
1755                  (match_operand:DI 2 "arith_operand")))]
1756   ""
1758   if (TARGET_SH1)
1759     {
1760       operands[2] = force_reg (DImode, operands[2]);
1761       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1762       DONE;
1763     }
1766 (define_insn "*adddi3_media"
1767   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1768         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1769                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1770   "TARGET_SHMEDIA"
1771   "@
1772         add     %1, %2, %0
1773         addi    %1, %2, %0"
1774   [(set_attr "type" "arith_media")])
1776 (define_insn "*adddisi3_media"
1777   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1778         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1779                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1780   "TARGET_SHMEDIA"
1781   "@
1782         add.l   %1, %2, %0
1783         addi.l  %1, %2, %0"
1784   [(set_attr "type" "arith_media")
1785    (set_attr "highpart" "ignore")])
1787 (define_insn "adddi3z_media"
1788   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1789         (zero_extend:DI
1790          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1791                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1792   "TARGET_SHMEDIA"
1793   "addz.l       %1, %N2, %0"
1794   [(set_attr "type" "arith_media")
1795    (set_attr "highpart" "ignore")])
1797 (define_insn_and_split "adddi3_compact"
1798   [(set (match_operand:DI 0 "arith_reg_dest")
1799         (plus:DI (match_operand:DI 1 "arith_reg_operand")
1800                  (match_operand:DI 2 "arith_reg_operand")))
1801    (clobber (reg:SI T_REG))]
1802   "TARGET_SH1"
1803   "#"
1804   "&& can_create_pseudo_p ()"
1805   [(const_int 0)]
1807   emit_insn (gen_clrt ());
1808   emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1809                        gen_lowpart (SImode, operands[1]),
1810                        gen_lowpart (SImode, operands[2])));
1811   emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1812                        gen_highpart (SImode, operands[1]),
1813                        gen_highpart (SImode, operands[2])));
1814   DONE;
1817 (define_insn "addc"
1818   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1819         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1820                           (match_operand:SI 2 "arith_reg_operand" "r"))
1821                  (reg:SI T_REG)))
1822    (set (reg:SI T_REG)
1823         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1824   "TARGET_SH1"
1825   "addc %2,%0"
1826   [(set_attr "type" "arith")])
1828 ;; A simplified version of the addc insn, where the exact value of the
1829 ;; T bit doesn't matter.  This is easier for combine to pick up.
1830 ;; We allow a reg or 0 for one of the operands in order to be able to
1831 ;; do 'reg + T' sequences.  Reload will load the constant 0 into the reg
1832 ;; as needed.
1833 (define_insn "*addc"
1834   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1835         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1836                           (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1837                  (match_operand:SI 3 "t_reg_operand" "")))
1838    (clobber (reg:SI T_REG))]
1839   "TARGET_SH1"
1840   "addc %2,%0"
1841   [(set_attr "type" "arith")])
1843 ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1844 ;; better, if the sett insn can be done early.
1845 (define_insn_and_split "*addc_r_r_1"
1846   [(set (match_operand:SI 0 "arith_reg_dest" "")
1847         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1848                           (match_operand:SI 2 "arith_reg_operand" ""))
1849                  (const_int 1)))
1850    (clobber (reg:SI T_REG))]
1851   "TARGET_SH1"
1852   "#"
1853   "&& 1"
1854   [(set (reg:SI T_REG) (const_int 1))
1855    (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1856                                           (reg:SI T_REG)))
1857               (clobber (reg:SI T_REG))])])
1859 ;; Left shifts by one are usually done with an add insn to avoid T_REG
1860 ;; clobbers.  Thus addc can also be used to do something like '(x << 1) + 1'.
1861 (define_insn_and_split "*addc_2r_1"
1862   [(set (match_operand:SI 0 "arith_reg_dest")
1863         (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1864                           (const_int 2))
1865                  (const_int 1)))
1866    (clobber (reg:SI T_REG))]
1867   "TARGET_SH1"
1868   "#"
1869   "&& 1"
1870   [(set (reg:SI T_REG) (const_int 1))
1871    (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1872                                           (reg:SI T_REG)))
1873               (clobber (reg:SI T_REG))])])
1875 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1876 ;; matched.  Split this up into a simple sub add sequence, as this will save
1877 ;; us one sett insn.
1878 (define_insn_and_split "*minus_plus_one"
1879   [(set (match_operand:SI 0 "arith_reg_dest" "")
1880         (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1881                            (match_operand:SI 2 "arith_reg_operand" ""))
1882                  (const_int 1)))]
1883   "TARGET_SH1"
1884   "#"
1885   "&& 1"
1886   [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1887    (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1889 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1890 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1891 ;; operation, as opposed to sequences such as
1892 ;;      movt    r2
1893 ;;      add     r2,r3
1895 ;; Even if the constant is not CSE-ed, a sequence such as
1896 ;;      mov     #0,r2
1897 ;;      addc    r2,r3
1898 ;; can be scheduled much better since the load of the constant can be
1899 ;; done earlier, before any comparison insns that store the result in
1900 ;; the T bit.
1901 (define_insn_and_split "*addc_r_1"
1902   [(set (match_operand:SI 0 "arith_reg_dest" "")
1903         (plus:SI (match_operand:SI 1 "t_reg_operand" "")
1904                  (match_operand:SI 2 "arith_reg_operand" "")))
1905    (clobber (reg:SI T_REG))]
1906   "TARGET_SH1"
1907   "#"
1908   "&& 1"
1909   [(parallel [(set (match_dup 0)
1910                    (plus:SI (plus:SI (match_dup 2) (const_int 0))
1911                             (match_dup 1)))
1912               (clobber (reg:SI T_REG))])])
1914 ;; Use shlr-addc to do 'reg + (reg & 1)'.
1915 (define_insn_and_split "*addc_r_lsb"
1916   [(set (match_operand:SI 0 "arith_reg_dest")
1917         (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1918                          (const_int 1))
1919                  (match_operand:SI 2 "arith_reg_operand")))
1920    (clobber (reg:SI T_REG))]
1921   "TARGET_SH1"
1922   "#"
1923   "&& can_create_pseudo_p ()"
1924   [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1925               (clobber (reg:SI T_REG))])]
1927   emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1930 ;; Use shlr-addc to do 'reg + reg + (reg & 1)'.
1931 (define_insn_and_split "*addc_r_r_lsb"
1932   [(set (match_operand:SI 0 "arith_reg_dest")
1933         (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1934                                   (const_int 1))
1935                           (match_operand:SI 2 "arith_reg_operand"))
1936                  (match_operand:SI 3 "arith_reg_operand")))
1937    (clobber (reg:SI T_REG))]
1938   "TARGET_SH1"
1939   "#"
1940   "&& can_create_pseudo_p ()"
1941   [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1942                                           (reg:SI T_REG)))
1943               (clobber (reg:SI T_REG))])]
1945   emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1948 ;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'.
1949 (define_insn_and_split "*addc_r_lsb_r"
1950   [(set (match_operand:SI 0 "arith_reg_dest")
1951         (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1952                          (const_int 1))
1953                  (plus:SI (match_operand:SI 2 "arith_reg_operand")
1954                           (match_operand:SI 3 "arith_reg_operand"))))
1955    (clobber (reg:SI T_REG))]
1956   "TARGET_SH1"
1957   "#"
1958   "&& can_create_pseudo_p ()"
1959   [(parallel [(set (match_dup 0)
1960                    (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1961                                      (match_dup 2))
1962                             (match_dup 3)))
1963               (clobber (reg:SI T_REG))])])
1965 ;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'.
1966 (define_insn_and_split "*addc_2r_lsb"
1967   [(set (match_operand:SI 0 "arith_reg_dest")
1968         (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1969                          (const_int 1))
1970                  (mult:SI (match_operand:SI 2 "arith_reg_operand")
1971                           (const_int 2))))
1972    (clobber (reg:SI T_REG))]
1973   "TARGET_SH1"
1974   "#"
1975   "&& can_create_pseudo_p ()"
1976   [(parallel [(set (match_dup 0)
1977                    (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1978                                      (match_dup 2))
1979                             (match_dup 2)))
1980               (clobber (reg:SI T_REG))])])
1982 ;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'.
1983 (define_insn_and_split "*addc_r_msb"
1984   [(set (match_operand:SI 0 "arith_reg_dest")
1985         (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1986                               (const_int 31))
1987                  (match_operand:SI 2 "arith_reg_operand")))
1988    (clobber (reg:SI T_REG))]
1989   "TARGET_SH1"
1990   "#"
1991   "&& can_create_pseudo_p ()"
1992   [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1993               (clobber (reg:SI T_REG))])]
1995   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
1998 ;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'.
1999 (define_insn_and_split "*addc_r_r_msb"
2000   [(set (match_operand:SI 0 "arith_reg_dest")
2001         (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
2002                                        (const_int 31))
2003                           (match_operand:SI 2 "arith_reg_operand"))
2004                  (match_operand:SI 3 "arith_reg_operand")))
2005    (clobber (reg:SI T_REG))]
2006   "TARGET_SH1"
2007   "#"
2008   "&& can_create_pseudo_p ()"
2009   [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
2010                                           (reg:SI T_REG)))
2011               (clobber (reg:SI T_REG))])]
2013   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
2016 ;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)'
2017 ;; into 'reg + reg + (reg & 1)'.
2018 (define_insn_and_split "*addc_2r_msb"
2019   [(set (match_operand:SI 0 "arith_reg_dest")
2020         (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
2021                           (const_int 2))
2022                  (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
2023                               (const_int 31))))
2024    (clobber (reg:SI T_REG))]
2025   "TARGET_SH1"
2026   "#"
2027   "&& can_create_pseudo_p ()"
2028   [(parallel [(set (match_dup 0)
2029                    (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31))
2030                                      (match_dup 1))
2031                             (match_dup 1)))
2032               (clobber (reg:SI T_REG))])])
2034 (define_expand "addsi3"
2035   [(set (match_operand:SI 0 "arith_reg_operand" "")
2036         (plus:SI (match_operand:SI 1 "arith_operand" "")
2037                  (match_operand:SI 2 "arith_operand" "")))]
2038   ""
2040   if (TARGET_SHMEDIA)
2041     operands[1] = force_reg (SImode, operands[1]);
2044 (define_insn "addsi3_media"
2045   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2046         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
2047                  (match_operand:SI 2 "arith_operand" "r,I10")))]
2048   "TARGET_SHMEDIA"
2049   "@
2050         add.l   %1, %2, %0
2051         addi.l  %1, %2, %0"
2052   [(set_attr "type" "arith_media")
2053    (set_attr "highpart" "ignore")])
2055 (define_insn "addsidi3_media"
2056   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
2057         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
2058                                   "%r,r")
2059                                  (match_operand:SI 2 "arith_operand"
2060                                   "r,I10"))))]
2061   "TARGET_SHMEDIA"
2062   "@
2063         add.l   %1, %2, %0
2064         addi.l  %1, %2, %0"
2065   [(set_attr "type" "arith_media")
2066    (set_attr "highpart" "ignore")])
2068 (define_insn "*addsi3_compact"
2069   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2070         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
2071                  (match_operand:SI 2 "arith_operand" "rI08")))]
2072   "TARGET_SH1"
2073   "add  %2,%0"
2074   [(set_attr "type" "arith")])
2076 ;; -------------------------------------------------------------------------
2077 ;; Subtraction instructions
2078 ;; -------------------------------------------------------------------------
2080 (define_expand "subdi3"
2081   [(set (match_operand:DI 0 "arith_reg_operand" "")
2082         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
2083                   (match_operand:DI 2 "arith_reg_operand" "")))]
2084   ""
2086   if (TARGET_SH1)
2087     {
2088       operands[1] = force_reg (DImode, operands[1]);
2089       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
2090       DONE;
2091     }
2094 (define_insn "*subdi3_media"
2095   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2096         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2097                   (match_operand:DI 2 "arith_reg_operand" "r")))]
2098   "TARGET_SHMEDIA"
2099   "sub  %N1, %2, %0"
2100   [(set_attr "type" "arith_media")])
2101   
2102 (define_insn "subdisi3_media"
2103   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2104         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2105                   (match_operand:DI 2 "arith_reg_operand" "r")))]
2106   "TARGET_SHMEDIA"
2107   "sub.l        %N1, %2, %0"
2108   [(set_attr "type" "arith_media")
2109    (set_attr "highpart" "ignore")])
2111 (define_insn_and_split "subdi3_compact"
2112   [(set (match_operand:DI 0 "arith_reg_dest")
2113         (minus:DI (match_operand:DI 1 "arith_reg_operand")
2114                  (match_operand:DI 2 "arith_reg_operand")))
2115    (clobber (reg:SI T_REG))]
2116   "TARGET_SH1"
2117   "#"
2118   "&& can_create_pseudo_p ()"
2119   [(const_int 0)]
2121   emit_insn (gen_clrt ());
2122   emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2123                        gen_lowpart (SImode, operands[1]),
2124                        gen_lowpart (SImode, operands[2])));
2125   emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2126                        gen_highpart (SImode, operands[1]),
2127                        gen_highpart (SImode, operands[2])));
2128   DONE;
2131 (define_insn "subc"
2132   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2133         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2134                             (match_operand:SI 2 "arith_reg_operand" "r"))
2135                   (reg:SI T_REG)))
2136    (set (reg:SI T_REG)
2137         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2138                           (reg:SI T_REG))
2139                 (match_dup 1)))]
2140   "TARGET_SH1"
2141   "subc %2,%0"
2142   [(set_attr "type" "arith")])
2144 ;; A simplified version of the subc insn, where the exact value of the
2145 ;; T bit doesn't matter.  This is easier for combine to pick up.
2146 ;; We allow a reg or 0 for one of the operands in order to be able to
2147 ;; do 'reg - T' sequences.  Reload will load the constant 0 into the reg
2148 ;; as needed.
2149 (define_insn "*subc"
2150   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2151         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2152                             (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
2153                   (match_operand:SI 3 "t_reg_operand" "")))
2154    (clobber (reg:SI T_REG))]
2155   "TARGET_SH1"
2156   "subc %2,%0"
2157   [(set_attr "type" "arith")])
2159 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2160 ;; better, if the sett insn can be done early.
2161 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2162 (define_insn_and_split "*subc"
2163   [(set (match_operand:SI 0 "arith_reg_dest" "")
2164         (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2165                  (match_operand:SI 2 "arith_reg_operand" "")))
2166    (clobber (reg:SI T_REG))]
2167   "TARGET_SH1"
2168   "#"
2169   "&& 1"
2170   [(set (reg:SI T_REG) (const_int 1))
2171    (parallel [(set (match_dup 0)
2172                    (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2173                              (reg:SI T_REG)))
2174               (clobber (reg:SI T_REG))])])
2176 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2177 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2178 ;; operation, as opposed to sequences such as
2179 ;;      movt    r2
2180 ;;      sub     r2,r3
2182 ;; Even if the constant is not CSE-ed, a sequence such as
2183 ;;      mov     #0,r2
2184 ;;      subc    r2,r3
2185 ;; can be scheduled much better since the load of the constant can be
2186 ;; done earlier, before any comparison insns that store the result in
2187 ;; the T bit.
2188 (define_insn_and_split "*subc"
2189   [(set (match_operand:SI 0 "arith_reg_dest" "")
2190         (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2191                   (match_operand:SI 2 "t_reg_operand" "")))
2192    (clobber (reg:SI T_REG))]
2193   "TARGET_SH1"
2194   "#"
2195   "&& 1"
2196   [(parallel [(set (match_dup 0)
2197                    (minus:SI (minus:SI (match_dup 1) (const_int 0))
2198                              (match_dup 2)))
2199               (clobber (reg:SI T_REG))])])
2201 (define_insn "*subsi3_internal"
2202   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2203         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2204                   (match_operand:SI 2 "arith_reg_operand" "r")))]
2205   "TARGET_SH1"
2206   "sub  %2,%0"
2207   [(set_attr "type" "arith")])
2209 (define_insn_and_split "*subsi3_media"
2210   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2211         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2212                   (match_operand:SI 2 "extend_reg_operand" "r")))]
2213   "TARGET_SHMEDIA
2214    && (operands[1] != constm1_rtx
2215        || (GET_CODE (operands[2]) != TRUNCATE
2216            && GET_CODE (operands[2]) != SUBREG))"
2217   "sub.l        %N1, %2, %0"
2218   "operands[1] == constm1_rtx"
2219   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2220   ""
2221   [(set_attr "type" "arith_media")
2222    (set_attr "highpart" "ignore")])
2224 (define_split
2225   [(set (match_operand:SI 0 "arith_reg_dest" "")
2226         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2227                                                        "general_extend_operand"
2228                                                        "") 0)) 0)))]
2229   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2230   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2231    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2232   "")
2234 (define_split
2235   [(set (match_operand:SI 0 "arith_reg_dest" "")
2236         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2237                                                        "general_extend_operand"
2238                                                        "") 0)) 3)))]
2239   "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2240   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2241    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2242   "")
2244 ;; Convert
2245 ;;      constant - reg
2246 ;; to
2247 ;;      neg reg
2248 ;;      add reg, #const
2249 ;; since this will sometimes save one instruction.
2250 ;; Otherwise we might get a sequence like
2251 ;;      mov #const, rY
2252 ;;      sub rY, rX
2253 ;;      mov rX, rY
2254 ;; if the source and dest regs are the same.
2255 (define_expand "subsi3"
2256   [(set (match_operand:SI 0 "arith_reg_operand" "")
2257         (minus:SI (match_operand:SI 1 "arith_operand" "")
2258                   (match_operand:SI 2 "arith_reg_operand" "")))]
2259   ""
2261   if (TARGET_SH1 && CONST_INT_P (operands[1]))
2262     {
2263       emit_insn (gen_negsi2 (operands[0], operands[2]));
2264       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2265       DONE;
2266     }
2267   if (TARGET_SHMEDIA)
2268     {
2269       if (!can_create_pseudo_p ()
2270           && ! arith_reg_or_0_operand (operands[1], SImode))
2271         FAIL;
2272       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2273         operands[1] = force_reg (SImode, operands[1]);
2274     }
2277 ;; -------------------------------------------------------------------------
2278 ;; Division instructions
2279 ;; -------------------------------------------------------------------------
2281 ;; We take advantage of the library routines which don't clobber as many
2282 ;; registers as a normal function call would.
2284 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2285 ;; also has an effect on the register that holds the address of the sfunc.
2286 ;; To make this work, we have an extra dummy insn that shows the use
2287 ;; of this register for reorg.
2289 (define_insn "use_sfunc_addr"
2290   [(set (reg:SI PR_REG)
2291         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2292   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2293   ""
2294   [(set_attr "length" "0")])
2296 (define_insn "udivsi3_sh2a"
2297   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2298         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2299                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2300   "TARGET_SH2A"
2301   "divu %2,%1"
2302   [(set_attr "type" "arith")
2303    (set_attr "in_delay_slot" "no")])
2305 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2306 ;; hard register 0.  If we used hard register 0, then the next instruction
2307 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
2308 ;; gets allocated to a stack slot that needs its address reloaded, then
2309 ;; there is nothing to prevent reload from using r0 to reload the address.
2310 ;; This reload would clobber the value in r0 we are trying to store.
2311 ;; If we let reload allocate r0, then this problem can never happen.
2312 (define_insn "udivsi3_i1"
2313   [(set (match_operand:SI 0 "register_operand" "=z")
2314         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2315    (clobber (reg:SI T_REG))
2316    (clobber (reg:SI PR_REG))
2317    (clobber (reg:SI R4_REG))
2318    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2319   "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2320   "jsr  @%1%#"
2321   [(set_attr "type" "sfunc")
2322    (set_attr "needs_delay_slot" "yes")])
2324 ; Since shmedia-nofpu code could be linked against shcompact code, and
2325 ; the udivsi3 libcall has the same name, we must consider all registers
2326 ; clobbered that are in the union of the registers clobbered by the
2327 ; shmedia and the shcompact implementation.  Note, if the shcompact
2328 ; implementation actually used shcompact code, we'd need to clobber
2329 ; also r23 and fr23.
2330 (define_insn "udivsi3_i1_media"
2331   [(set (match_operand:SI 0 "register_operand" "=z")
2332         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2333    (clobber (reg:SI T_MEDIA_REG))
2334    (clobber (reg:SI PR_MEDIA_REG))
2335    (clobber (reg:SI R20_REG))
2336    (clobber (reg:SI R21_REG))
2337    (clobber (reg:SI R22_REG))
2338    (clobber (reg:DI TR0_REG))
2339    (clobber (reg:DI TR1_REG))
2340    (clobber (reg:DI TR2_REG))
2341    (use (match_operand 1 "target_reg_operand" "b"))]
2342   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2343   "blink        %1, r18"
2344   [(set_attr "type" "sfunc")
2345    (set_attr "needs_delay_slot" "yes")])
2347 (define_expand "udivsi3_i4_media"
2348   [(set (match_dup 3)
2349         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2350    (set (match_dup 4)
2351         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2352    (set (match_dup 5) (float:DF (match_dup 3)))
2353    (set (match_dup 6) (float:DF (match_dup 4)))
2354    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2355    (set (match_dup 8) (fix:DI (match_dup 7)))
2356    (set (match_operand:SI 0 "register_operand" "")
2357         (truncate:SI (match_dup 8)))]
2358   "TARGET_SHMEDIA_FPU"
2360   operands[3] = gen_reg_rtx (DImode);
2361   operands[4] = gen_reg_rtx (DImode);
2362   operands[5] = gen_reg_rtx (DFmode);
2363   operands[6] = gen_reg_rtx (DFmode);
2364   operands[7] = gen_reg_rtx (DFmode);
2365   operands[8] = gen_reg_rtx (DImode);
2368 (define_insn "udivsi3_i4"
2369   [(set (match_operand:SI 0 "register_operand" "=y")
2370         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2371    (clobber (reg:SI T_REG))
2372    (clobber (reg:SI PR_REG))
2373    (clobber (reg:DF DR0_REG))
2374    (clobber (reg:DF DR2_REG))
2375    (clobber (reg:DF DR4_REG))
2376    (clobber (reg:SI R0_REG))
2377    (clobber (reg:SI R1_REG))
2378    (clobber (reg:SI R4_REG))
2379    (clobber (reg:SI R5_REG))
2380    (use (reg:PSI FPSCR_REG))
2381    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2382   "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2383   "jsr  @%1%#"
2384   [(set_attr "type" "sfunc")
2385    (set_attr "fp_mode" "double")
2386    (set_attr "needs_delay_slot" "yes")])
2388 (define_insn "udivsi3_i4_single"
2389   [(set (match_operand:SI 0 "register_operand" "=y")
2390         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2391    (clobber (reg:SI T_REG))
2392    (clobber (reg:SI PR_REG))
2393    (clobber (reg:DF DR0_REG))
2394    (clobber (reg:DF DR2_REG))
2395    (clobber (reg:DF DR4_REG))
2396    (clobber (reg:SI R0_REG))
2397    (clobber (reg:SI R1_REG))
2398    (clobber (reg:SI R4_REG))
2399    (clobber (reg:SI R5_REG))
2400    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2401   "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2402    && TARGET_FPU_SINGLE"
2403   "jsr  @%1%#"
2404   [(set_attr "type" "sfunc")
2405    (set_attr "needs_delay_slot" "yes")])
2407 (define_insn "udivsi3_i4_int"
2408   [(set (match_operand:SI 0 "register_operand" "=z")
2409         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2410    (clobber (reg:SI T_REG))
2411    (clobber (reg:SI R1_REG))
2412    (clobber (reg:SI PR_REG))
2413    (clobber (reg:SI MACH_REG))
2414    (clobber (reg:SI MACL_REG))
2415    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2416   "TARGET_SH1"
2417   "jsr  @%1%#"
2418   [(set_attr "type" "sfunc")
2419    (set_attr "needs_delay_slot" "yes")])
2422 (define_expand "udivsi3"
2423   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2424    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2425    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2426    (parallel [(set (match_operand:SI 0 "register_operand" "")
2427                    (udiv:SI (reg:SI R4_REG)
2428                             (reg:SI R5_REG)))
2429               (clobber (reg:SI T_REG))
2430               (clobber (reg:SI PR_REG))
2431               (clobber (reg:SI R4_REG))
2432               (use (match_dup 3))])]
2433   ""
2435   rtx last;
2437   operands[3] = gen_reg_rtx (Pmode);
2438   /* Emit the move of the address to a pseudo outside of the libcall.  */
2439   if (TARGET_DIVIDE_CALL_TABLE)
2440     {
2441       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2442          that causes problems when the divide code is supposed to come from a
2443          separate library.  Division by zero is undefined, so dividing 1 can be
2444          implemented by comparing with the divisor.  */
2445       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2446         {
2447           rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2448           emit_insn (gen_cstoresi4 (operands[0], test,
2449                                     operands[1], operands[2]));
2450           DONE;
2451         }
2452       else if (operands[2] == const0_rtx)
2453         {
2454           emit_move_insn (operands[0], operands[2]);
2455           DONE;
2456         }
2457       function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2458       last = gen_udivsi3_i4_int (operands[0], operands[3]);
2459     }
2460   else if (TARGET_DIVIDE_CALL_FP)
2461     {
2462       function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2463       if (TARGET_FPU_SINGLE)
2464         last = gen_udivsi3_i4_single (operands[0], operands[3]);
2465       else
2466         last = gen_udivsi3_i4 (operands[0], operands[3]);
2467     }
2468   else if (TARGET_SHMEDIA_FPU)
2469     {
2470       operands[1] = force_reg (SImode, operands[1]);
2471       operands[2] = force_reg (SImode, operands[2]);
2472       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2473       DONE;
2474     }
2475   else if (TARGET_SH2A)
2476     {
2477       operands[1] = force_reg (SImode, operands[1]);
2478       operands[2] = force_reg (SImode, operands[2]);
2479       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2480       DONE;
2481     }
2482   else if (TARGET_SH5)
2483     {
2484       function_symbol (operands[3],
2485                        TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2486                        SFUNC_STATIC);
2488       if (TARGET_SHMEDIA)
2489         last = gen_udivsi3_i1_media (operands[0], operands[3]);
2490       else if (TARGET_FPU_ANY)
2491         last = gen_udivsi3_i4_single (operands[0], operands[3]);
2492       else
2493         last = gen_udivsi3_i1 (operands[0], operands[3]);
2494     }
2495   else
2496     {
2497       function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2498       last = gen_udivsi3_i1 (operands[0], operands[3]);
2499     }
2500   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2501   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2502   emit_insn (last);
2503   DONE;
2506 (define_insn "divsi3_sh2a"
2507   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2508         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2509                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2510   "TARGET_SH2A"
2511   "divs %2,%1"
2512   [(set_attr "type" "arith")
2513    (set_attr "in_delay_slot" "no")])
2515 (define_insn "divsi3_i1"
2516   [(set (match_operand:SI 0 "register_operand" "=z")
2517         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2518    (clobber (reg:SI T_REG))
2519    (clobber (reg:SI PR_REG))
2520    (clobber (reg:SI R1_REG))
2521    (clobber (reg:SI R2_REG))
2522    (clobber (reg:SI R3_REG))
2523    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2524   "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2525   "jsr  @%1%#"
2526   [(set_attr "type" "sfunc")
2527    (set_attr "needs_delay_slot" "yes")])
2529 (define_insn "divsi3_i1_media"
2530   [(set (match_operand:SI 0 "register_operand" "=z")
2531         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2532    (clobber (reg:SI T_MEDIA_REG))
2533    (clobber (reg:SI PR_MEDIA_REG))
2534    (clobber (reg:SI R1_REG))
2535    (clobber (reg:SI R20_REG))
2536    (clobber (reg:SI R21_REG))
2537    (clobber (reg:SI TR0_REG))
2538    (use (match_operand 1 "target_reg_operand" "b"))]
2539   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2540   "blink        %1, r18"
2541   [(set_attr "type" "sfunc")])
2543 (define_insn "divsi3_media_2"
2544   [(set (match_operand:SI 0 "register_operand" "=z")
2545         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2546    (clobber (reg:SI T_MEDIA_REG))
2547    (clobber (reg:SI PR_MEDIA_REG))
2548    (clobber (reg:SI R1_REG))
2549    (clobber (reg:SI R21_REG))
2550    (clobber (reg:SI TR0_REG))
2551    (use (reg:SI R20_REG))
2552    (use (match_operand 1 "target_reg_operand" "b"))]
2553   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2554   "blink        %1, r18"
2555   [(set_attr "type" "sfunc")])
2557 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2558 ;; hard reg clobbers and data dependencies that we need when we want
2559 ;; to rematerialize the division into a call.
2560 (define_insn_and_split "divsi_inv_call"
2561   [(set (match_operand:SI 0 "register_operand" "=r")
2562         (div:SI (match_operand:SI 1 "register_operand" "r")
2563                 (match_operand:SI 2 "register_operand" "r")))
2564    (clobber (reg:SI R4_REG))
2565    (clobber (reg:SI R5_REG))
2566    (clobber (reg:SI T_MEDIA_REG))
2567    (clobber (reg:SI PR_MEDIA_REG))
2568    (clobber (reg:SI R1_REG))
2569    (clobber (reg:SI R21_REG))
2570    (clobber (reg:SI TR0_REG))
2571    (clobber (reg:SI R20_REG))
2572    (use (match_operand:SI 3 "register_operand" "r"))]
2573   "TARGET_SHMEDIA"
2574   "#"
2575   "&& (reload_in_progress || reload_completed)"
2576   [(set (match_dup 0) (match_dup 3))]
2577   ""
2578   [(set_attr "highpart" "must_split")])
2580 ;; This is the combiner pattern for -mdiv=inv:call .
2581 (define_insn_and_split "*divsi_inv_call_combine"
2582   [(set (match_operand:SI 0 "register_operand" "=z")
2583         (div:SI (match_operand:SI 1 "register_operand" "r")
2584                 (match_operand:SI 2 "register_operand" "r")))
2585    (clobber (reg:SI R4_REG))
2586    (clobber (reg:SI R5_REG))
2587    (clobber (reg:SI T_MEDIA_REG))
2588    (clobber (reg:SI PR_MEDIA_REG))
2589    (clobber (reg:SI R1_REG))
2590    (clobber (reg:SI R21_REG))
2591    (clobber (reg:SI TR0_REG))
2592    (clobber (reg:SI R20_REG))
2593    (use (unspec:SI [(match_dup 1)
2594                     (match_operand:SI 3 "" "")
2595                     (unspec:SI [(match_operand:SI 4 "" "")
2596                                 (match_dup 3)
2597                                 (match_operand:DI 5 "" "")]
2598                      UNSPEC_DIV_INV_M2)
2599                     (match_operand:DI 6 "" "")
2600                     (const_int 0)
2601                     (const_int 0)]
2602          UNSPEC_DIV_INV_M3))]
2603   "TARGET_SHMEDIA"
2604   "#"
2605   "&& (reload_in_progress || reload_completed)"
2606   [(pc)]
2608   const char *name = sh_divsi3_libfunc;
2609   enum sh_function_kind kind = SFUNC_GOT;
2610   rtx sym;
2612   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2613   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2614   while (TARGET_DIVIDE_INV_CALL2)
2615     {
2616       rtx x = operands[3];
2618       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2619         break;
2620       x = XVECEXP (x, 0, 0);
2621       name = "__sdivsi3_2";
2622       kind = SFUNC_STATIC;
2623       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2624       break;
2625     }
2626   sym = function_symbol (NULL, name, kind);
2627   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2628   DONE;
2630   [(set_attr "highpart" "must_split")])
2632 (define_expand "divsi3_i4_media"
2633   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2634    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2635    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2636    (set (match_operand:SI 0 "register_operand" "=r")
2637         (fix:SI (match_dup 5)))]
2638   "TARGET_SHMEDIA_FPU"
2640   operands[3] = gen_reg_rtx (DFmode);
2641   operands[4] = gen_reg_rtx (DFmode);
2642   operands[5] = gen_reg_rtx (DFmode);
2645 (define_insn "divsi3_i4"
2646   [(set (match_operand:SI 0 "register_operand" "=y")
2647         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2648    (clobber (reg:SI PR_REG))
2649    (clobber (reg:DF DR0_REG))
2650    (clobber (reg:DF DR2_REG))
2651    (use (reg:PSI FPSCR_REG))
2652    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2653   "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2654   "jsr  @%1%#"
2655   [(set_attr "type" "sfunc")
2656    (set_attr "fp_mode" "double")
2657    (set_attr "needs_delay_slot" "yes")])
2659 (define_insn "divsi3_i4_single"
2660   [(set (match_operand:SI 0 "register_operand" "=y")
2661         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2662    (clobber (reg:SI PR_REG))
2663    (clobber (reg:DF DR0_REG))
2664    (clobber (reg:DF DR2_REG))
2665    (clobber (reg:SI R2_REG))
2666    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2667   "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2668    && TARGET_FPU_SINGLE"
2669   "jsr  @%1%#"
2670   [(set_attr "type" "sfunc")
2671    (set_attr "needs_delay_slot" "yes")])
2673 (define_insn "divsi3_i4_int"
2674   [(set (match_operand:SI 0 "register_operand" "=z")
2675         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2676    (clobber (reg:SI T_REG))
2677    (clobber (reg:SI PR_REG))
2678    (clobber (reg:SI R1_REG))
2679    (clobber (reg:SI MACH_REG))
2680    (clobber (reg:SI MACL_REG))
2681    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2682   "TARGET_SH1"
2683   "jsr  @%1%#"
2684   [(set_attr "type" "sfunc")
2685    (set_attr "needs_delay_slot" "yes")])
2687 (define_expand "divsi3"
2688   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2689    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2690    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2691    (parallel [(set (match_operand:SI 0 "register_operand" "")
2692                    (div:SI (reg:SI R4_REG)
2693                            (reg:SI R5_REG)))
2694               (clobber (reg:SI T_REG))
2695               (clobber (reg:SI PR_REG))
2696               (clobber (reg:SI R1_REG))
2697               (clobber (reg:SI R2_REG))
2698               (clobber (reg:SI R3_REG))
2699               (use (match_dup 3))])]
2700   ""
2702   rtx last;
2704   operands[3] = gen_reg_rtx (Pmode);
2705   /* Emit the move of the address to a pseudo outside of the libcall.  */
2706   if (TARGET_DIVIDE_CALL_TABLE)
2707     {
2708       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2709       last = gen_divsi3_i4_int (operands[0], operands[3]);
2710     }
2711   else if (TARGET_DIVIDE_CALL_FP)
2712     {
2713       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2714       if (TARGET_FPU_SINGLE)
2715         last = gen_divsi3_i4_single (operands[0], operands[3]);
2716       else
2717         last = gen_divsi3_i4 (operands[0], operands[3]);
2718     }
2719   else if (TARGET_SH2A)
2720     {
2721       operands[1] = force_reg (SImode, operands[1]);
2722       operands[2] = force_reg (SImode, operands[2]);
2723       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2724       DONE;
2725     }
2726   else if (TARGET_DIVIDE_INV)
2727     {
2728       rtx dividend = operands[1];
2729       rtx divisor = operands[2];
2730       rtx tab_base;
2731       rtx nsb_res = gen_reg_rtx (DImode);
2732       rtx norm64 = gen_reg_rtx (DImode);
2733       rtx tab_ix = gen_reg_rtx (DImode);
2734       rtx norm32 = gen_reg_rtx (SImode);
2735       rtx i92 = force_reg (DImode, GEN_INT (92));
2736       rtx scratch0a = gen_reg_rtx (DImode);
2737       rtx scratch0b = gen_reg_rtx (DImode);
2738       rtx inv0 = gen_reg_rtx (SImode);
2739       rtx scratch1a = gen_reg_rtx (DImode);
2740       rtx scratch1b = gen_reg_rtx (DImode);
2741       rtx shift = gen_reg_rtx (DImode);
2742       rtx i2p27, i43;
2743       rtx inv1 = gen_reg_rtx (SImode);
2744       rtx scratch2a = gen_reg_rtx (DImode);
2745       rtx scratch2b = gen_reg_rtx (SImode);
2746       rtx inv2 = gen_reg_rtx (SImode);
2747       rtx scratch3a = gen_reg_rtx (DImode);
2748       rtx scratch3b = gen_reg_rtx (DImode);
2749       rtx scratch3c = gen_reg_rtx (DImode);
2750       rtx scratch3d = gen_reg_rtx (SImode);
2751       rtx scratch3e = gen_reg_rtx (DImode);
2752       rtx result = gen_reg_rtx (SImode);
2754       if (! arith_reg_or_0_operand (dividend, SImode))
2755         dividend = force_reg (SImode, dividend);
2756       if (! arith_reg_operand (divisor, SImode))
2757         divisor = force_reg (SImode, divisor);
2758       if (flag_pic && Pmode != DImode)
2759         {
2760           tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2761           tab_base = gen_datalabel_ref (tab_base);
2762           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2763         }
2764       else
2765         {
2766           tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2767           tab_base = gen_datalabel_ref (tab_base);
2768           tab_base = force_reg (DImode, tab_base);
2769         }
2770       if (TARGET_DIVIDE_INV20U)
2771         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2772       else
2773         i2p27 = GEN_INT (0);
2774       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2775         i43 = force_reg (DImode, GEN_INT (43));
2776       else
2777         i43 = GEN_INT (0);
2778       emit_insn (gen_nsbdi (nsb_res,
2779                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2780       emit_insn (gen_ashldi3_media (norm64,
2781                                     gen_rtx_SUBREG (DImode, divisor, 0),
2782                                     nsb_res));
2783       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2784       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2785       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2786                                    inv0, scratch0a, scratch0b,
2787                                    scratch1a, scratch1b));
2788       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2789       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2790                                    scratch2a));
2791       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2792                                    i2p27, i43,
2793                                    scratch3a, scratch3b, scratch3c,
2794                                    scratch2a, scratch2b, scratch3d, scratch3e));
2795       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2796         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2797       else if (TARGET_DIVIDE_INV_FP)
2798         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2799                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2800                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2801                                      gen_reg_rtx (DFmode)));
2802       else
2803         emit_move_insn (operands[0], result);
2804       DONE;
2805     }
2806   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2807     {
2808       operands[1] = force_reg (SImode, operands[1]);
2809       operands[2] = force_reg (SImode, operands[2]);
2810       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2811       DONE;
2812     }
2813   else if (TARGET_SH5)
2814     {
2815       if (TARGET_DIVIDE_CALL2)
2816         {
2817           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2818           tab_base = gen_datalabel_ref (tab_base);
2819           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2820         }
2821       if (TARGET_FPU_ANY && TARGET_SH1)
2822         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2823       else if (TARGET_DIVIDE_CALL2)
2824         function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2825       else
2826         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2828       if (TARGET_SHMEDIA)
2829         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2830                 (operands[0], operands[3]));
2831       else if (TARGET_FPU_ANY)
2832         last = gen_divsi3_i4_single (operands[0], operands[3]);
2833       else
2834         last = gen_divsi3_i1 (operands[0], operands[3]);
2835     }
2836   else
2837     {
2838       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2839       last = gen_divsi3_i1 (operands[0], operands[3]);
2840     }
2841   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2842   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2843   emit_insn (last);
2844   DONE;
2847 ;; operands: scratch, tab_base, tab_ix
2848 ;; These are unspecs because we could generate an indexed addressing mode
2849 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2850 ;; confuse reload.  See PR27117.
2851 (define_insn "divsi_inv_qitable"
2852   [(set (match_operand:DI 0 "register_operand" "=r")
2853         (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2854                                     (match_operand:DI 2 "register_operand" "r")]
2855                          UNSPEC_DIV_INV_TABLE)))]
2856   "TARGET_SHMEDIA"
2857   "ldx.ub       %1, %2, %0"
2858   [(set_attr "type" "load_media")
2859    (set_attr "highpart" "user")])
2861 ;; operands: scratch, tab_base, tab_ix
2862 (define_insn "divsi_inv_hitable"
2863   [(set (match_operand:DI 0 "register_operand" "=r")
2864         (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2865                                     (match_operand:DI 2 "register_operand" "r")]
2866                          UNSPEC_DIV_INV_TABLE)))]
2867   "TARGET_SHMEDIA"
2868   "ldx.w        %1, %2, %0"
2869   [(set_attr "type" "load_media")
2870    (set_attr "highpart" "user")])
2872 ;; operands: inv0, tab_base, tab_ix, norm32
2873 ;; scratch equiv in sdivsi3_2: r19, r21
2874 (define_expand "divsi_inv_m0"
2875   [(set (match_operand:SI 0 "register_operand" "=r")
2876         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2877                     (match_operand:DI 2 "register_operand" "r")
2878                     (match_operand:SI 3 "register_operand" "r")]
2879          UNSPEC_DIV_INV_M0))
2880    (clobber (match_operand:DI 4 "register_operand" "=r"))
2881    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2882   "TARGET_SHMEDIA"
2885 tab_base: r20
2886 tab_ix: r21
2887 norm32: r25
2888  ldx.ub r20, r21, r19 // u0.8
2889  shlli r21, 1, r21
2890  muls.l r25, r19, r19 // s2.38
2891  ldx.w r20, r21, r21  // s2.14
2892  shari r19, 24, r19   // truncate to s2.14
2893  sub r21, r19, r19    // some 11 bit inverse in s1.14
2896   rtx inv0 = operands[0];
2897   rtx tab_base = operands[1];
2898   rtx tab_ix = operands[2];
2899   rtx norm32 = operands[3];
2900   rtx scratch0 = operands[4];
2901   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2902   rtx scratch1 = operands[5];
2904   emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2905   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2906   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2907   emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2908   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2909   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2910   DONE;
2913 ;; operands: inv1, tab_base, tab_ix, norm32
2914 (define_insn_and_split "divsi_inv_m1"
2915   [(set (match_operand:SI 0 "register_operand" "=r")
2916         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2917                     (match_operand:DI 2 "register_operand" "r")
2918                     (match_operand:SI 3 "register_operand" "r")]
2919          UNSPEC_DIV_INV_M1))
2920    (clobber (match_operand:SI 4 "register_operand" "=r"))
2921    (clobber (match_operand:DI 5 "register_operand" "=r"))
2922    (clobber (match_operand:DI 6 "register_operand" "=r"))
2923    (clobber (match_operand:DI 7 "register_operand" "=r"))
2924    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2925   "TARGET_SHMEDIA"
2926   "#"
2927   "&& !can_create_pseudo_p ()"
2928   [(pc)]
2930 /* inv0: r19
2931  muls.l r19, r19, r18 // u0.28
2932  muls.l r25, r18, r18 // s2.58
2933  shlli r19, 45, r0    // multiply by two and convert to s2.58
2934  sub r0, r18, r18
2935  shari r18, 28, r18   // some 18 bit inverse in s1.30
2938   rtx inv1 = operands[0];
2939   rtx tab_base = operands[1];
2940   rtx tab_ix = operands[2];
2941   rtx norm32 = operands[3];
2942   rtx inv0 = operands[4];
2943   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2944   rtx scratch0a = operands[5];
2945   rtx scratch0b = operands[6];
2946   rtx scratch0 = operands[7];
2947   rtx scratch1 = operands[8];
2948   rtx scratch1_si = gen_lowpart (SImode, scratch1);
2950   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2951                                scratch0a, scratch0b));
2952   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2953   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2954   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2955   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2956   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2957   DONE;
2960 ;; operands: inv2, norm32, inv1, i92
2961 (define_insn_and_split "divsi_inv_m2"
2962   [(set (match_operand:SI 0 "register_operand" "=r")
2963         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2964                     (match_operand:SI 2 "register_operand" "r")
2965                     (match_operand:DI 3 "register_operand" "r")]
2966          UNSPEC_DIV_INV_M2))
2967    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2968   "TARGET_SHMEDIA"
2969   "#"
2970   "&& !can_create_pseudo_p ()"
2971   [(pc)]
2974  muls.l r18, r25, r0  // s2.60
2975  shari r0, 16, r0     // s-16.44
2976   sub
2977  muls.l r0, r18, r19  // s-16.74
2978  shari r19, 30, r19   // s-16.44
2980   rtx inv2 = operands[0];
2981   rtx norm32 = operands[1];
2982   rtx inv1 = operands[2];
2983   rtx i92 = operands[3];
2984   rtx scratch0 = operands[4];
2985   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2987   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2988   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2989   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2990   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2991   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2992   DONE;
2995 (define_insn_and_split "divsi_inv_m3"
2996   [(set (match_operand:SI 0 "register_operand" "=r")
2997         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2998                     (match_operand:SI 2 "register_operand" "r")
2999                     (match_operand:SI 3 "register_operand" "r")
3000                     (match_operand:DI 4 "register_operand" "r")
3001                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
3002                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
3003          UNSPEC_DIV_INV_M3))
3004    (clobber (match_operand:DI 7 "register_operand" "=r"))
3005    (clobber (match_operand:DI 8 "register_operand" "=r"))
3006    (clobber (match_operand:DI 9 "register_operand" "=r"))
3007    (clobber (match_operand:DI 10 "register_operand" "=r"))
3008    (clobber (match_operand:SI 11 "register_operand" "=r"))
3009    (clobber (match_operand:SI 12 "register_operand" "=r"))
3010    (clobber (match_operand:DI 13 "register_operand" "=r"))]
3011   "TARGET_SHMEDIA"
3012   "#"
3013   "&& !can_create_pseudo_p ()"
3014   [(pc)]
3017   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
3018   r0: scratch0  r19: scratch1 r21: scratch2
3020   muls.l r18, r4, r25 // s32.30
3021  muls.l r19, r4, r19  // s15.30
3022  shari r25, 63, r21
3023   shari r19, 14, r19  // s18.-14
3024  sub r25, r19, r0
3025  shard r0, r1, r0
3026  sub r0, r21, r0
3029   rtx result = operands[0];
3030   rtx dividend = operands[1];
3031   rtx inv1 = operands[2];
3032   rtx inv2 = operands[3];
3033   rtx shift = operands[4];
3034   rtx scratch0 = operands[7];
3035   rtx scratch1 = operands[8];
3036   rtx scratch2 = operands[9];
3038   if (satisfies_constraint_N (dividend))
3039     {
3040       emit_move_insn (result, dividend);
3041       DONE;
3042     }
3044   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
3045   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
3046   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
3047   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
3048   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
3049   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
3050   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
3051   DONE;
3054 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
3055 ;; inv1: tab_base, tab_ix, norm32
3056 ;; inv2: norm32, inv1, i92
3057 (define_insn_and_split "divsi_inv_m1_3"
3058   [(set (match_operand:SI 0 "register_operand" "=r")
3059         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3060                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
3061                                 (match_operand:DI 3 "register_operand" "r")
3062                                 (match_operand:SI 4 "register_operand" "r")]
3063                      UNSPEC_DIV_INV_M1)
3064                     (unspec:SI [(match_dup 4)
3065                                 (unspec:SI [(match_dup 2)
3066                                             (match_dup 3)
3067                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
3068                                 (match_operand:SI 5 "" "")]
3069                      UNSPEC_DIV_INV_M2)
3070                     (match_operand:DI 6 "register_operand" "r")
3071                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
3072                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
3073          UNSPEC_DIV_INV_M3))
3074    (clobber (match_operand:DI 9 "register_operand" "=r"))
3075    (clobber (match_operand:DI 10 "register_operand" "=r"))
3076    (clobber (match_operand:DI 11 "register_operand" "=r"))
3077    (clobber (match_operand:DI 12 "register_operand" "=r"))
3078    (clobber (match_operand:SI 13 "register_operand" "=r"))
3079    (clobber (match_operand:SI 14 "register_operand" "=r"))
3080    (clobber (match_operand:DI 15 "register_operand" "=r"))]
3081   "TARGET_SHMEDIA
3082    && (TARGET_DIVIDE_INV_MINLAT
3083        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3084   "#"
3085   "&& !can_create_pseudo_p ()"
3086   [(pc)]
3088   rtx result = operands[0];
3089   rtx dividend = operands[1];
3090   rtx tab_base = operands[2];
3091   rtx tab_ix = operands[3];
3092   rtx norm32 = operands[4];
3093   /* rtx i92 = operands[5]; */
3094   rtx shift = operands[6];
3095   rtx i2p27 = operands[7];
3096   rtx i43 = operands[8];
3097   rtx scratch0 = operands[9];
3098   rtx scratch0_si = gen_lowpart (SImode, scratch0);
3099   rtx scratch1 = operands[10];
3100   rtx scratch1_si = gen_lowpart (SImode, scratch1);
3101   rtx scratch2 = operands[11];
3102   rtx scratch3 = operands[12];
3103   rtx scratch4 = operands[13];
3104   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3105   rtx scratch5 = operands[14];
3106   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3107   rtx scratch6 = operands[15];
3109   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3110                                scratch0, scratch1));
3111   /* inv0 == scratch4 */
3112   if (! TARGET_DIVIDE_INV20U)
3113     {
3114       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3115       i2p27 = scratch0;
3116       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3117     }
3118   else
3119     {
3120       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3121       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3122     }
3123   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3124   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3125   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3126   /* inv1 == scratch4 */
3128   if (TARGET_DIVIDE_INV_MINLAT)
3129     {
3130       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3131       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3132       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3133       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3134       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3135       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3136       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3137       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3138       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3139       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3140       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3141     }
3142   else
3143     {
3144       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3145       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
3146       emit_insn (gen_nsbdi (scratch6,
3147                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
3148       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3149       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3150       emit_insn (gen_divsi_inv20 (scratch2,
3151                                   norm32, scratch4, dividend,
3152                                   scratch6, scratch3, i43,
3153                                   /* scratch0 may be shared with i2p27.  */
3154                                   scratch0, scratch1, scratch5,
3155                                   label, label, i2p27));
3156     }
3157   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3158   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3159   DONE;
3162 (define_insn "divsi_inv20"
3163   [(set (match_operand:DI 0 "register_operand" "=&r")
3164         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
3165                     (match_operand:SI 2 "register_operand" "r")
3166                     (match_operand:SI 3 "register_operand" "r")
3167                     (match_operand:DI 4 "register_operand" "r")
3168                     (match_operand:DI 5 "register_operand" "r")
3169                     (match_operand:DI 6 "register_operand" "r")
3170                     (match_operand:DI 12 "register_operand" "r")
3171                     (match_operand 10 "target_operand" "b")
3172                     (match_operand 11 "immediate_operand" "i")]
3173          UNSPEC_DIV_INV20))
3174    (clobber (match_operand:DI 7 "register_operand" "=&r"))
3175    (clobber (match_operand:DI 8 "register_operand" "=&r"))
3176    (clobber (match_operand:SI 9 "register_operand" "=r"))]
3177   "TARGET_SHMEDIA
3178    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3180 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3181              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3182              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3183              %10 label (tr), %11 label (imm)
3185  muls.l inv1, norm32, scratch0  // s2.60
3186   muls.l inv1, dividend, result // s32.30
3187   xor i2p27, result_sign, round_scratch
3188  bge/u dividend_nsb, i43, tr.. (label)
3189  shari scratch0, 16, scratch0   // s-16.44
3190  muls.l sratch0_si, inv1, scratch0 // s-16.74
3191   sub result, round_scratch, result
3192   shari dividend, 14, scratch1   // s19.-14
3193  shari scratch0, 30, scratch0   // s-16.44
3194  muls.l scratch0, scratch1, round_scratch // s15.30
3195 label:
3196  sub result, round_scratch, result */
3198   const bool likely = TARGET_DIVIDE_INV20L;
3199   if (likely)
3200     return
3201                "muls.l  %2, %3, %0"     "\n"
3202         "       xor     %12, %5, %7"    "\n"
3203         "       bge/l   %4, %6, %10"    "\n"
3204         "       muls.l  %2, %1, %8"     "\n"
3205         "       shari   %8, 16, %8"     "\n"
3206         "       muls.l  %8, %2, %8"     "\n"
3207         "       shari   %3, 14, %9"     "\n"
3208         "       shari   %8, 30, %8"     "\n"
3209         "       muls.l  %8, %9, %8"     "\n"
3210         "       sub     %0, %8, %0"     "\n"
3211         "%11:   add     %0, %7, %0";
3212   else
3213     return
3214                "muls.l  %2, %1, %8"     "\n"
3215         "       muls.l  %2, %3, %0"     "\n"
3216         "       xor     %12, %5, %7"    "\n"
3217         "       bge/u   %4, %6, %10"    "\n"
3218         "       shari   %8, 16, %8"     "\n"
3219         "       muls.l  %8, %2, %8"     "\n"
3220         "       sub     %0, %7, %0"     "\n"
3221         "       shari   %3, 14, %9"     "\n"
3222         "       shari   %8, 30, %8"     "\n"
3223         "       muls.l  %8, %9, %7"     "\n"
3224         "%11:   sub     %0, %7, %0";
3227 (define_insn_and_split "divsi_inv_fp"
3228   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3229         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3230                 (match_operand:SI 2 "register_operand" "rf")))
3231    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3232    (clobber (match_operand:SI 4 "register_operand" "=r"))
3233    (clobber (match_operand:SI 5 "register_operand" "=r"))
3234    (clobber (match_operand:DF 6 "register_operand" "=r"))
3235    (clobber (match_operand:DF 7 "register_operand" "=r"))
3236    (clobber (match_operand:DF 8 "register_operand" "=r"))]
3237   "TARGET_SHMEDIA_FPU"
3238   "#"
3239   "&& (reload_in_progress || reload_completed)"
3240   [(set (match_dup 0) (match_dup 3))]
3241   ""
3242   [(set_attr "highpart" "must_split")])
3244 ;; If a matching group of divide-by-inverse instructions is in the same
3245 ;; basic block after gcse & loop optimizations, we want to transform them
3246 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3247 (define_insn_and_split "*divsi_inv_fp_combine"
3248   [(set (match_operand:SI 0 "register_operand" "=f")
3249         (div:SI (match_operand:SI 1 "register_operand" "f")
3250                 (match_operand:SI 2 "register_operand" "f")))
3251    (use (unspec:SI [(match_dup 1)
3252                     (match_operand:SI 3 "" "")
3253                     (unspec:SI [(match_operand:SI 4 "" "")
3254                                 (match_dup 3)
3255                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3256                     (match_operand:DI 6 "" "")
3257                     (const_int 0)
3258                     (const_int 0)] UNSPEC_DIV_INV_M3))
3259    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3260    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3261    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3262    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3263    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3264   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3265   "#"
3266   "&& 1"
3267   [(set (match_dup 9) (float:DF (match_dup 1)))
3268    (set (match_dup 10) (float:DF (match_dup 2)))
3269    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3270    (set (match_dup 8)
3271         (fix:SI (match_dup 11)))
3272    (set (match_dup 0) (match_dup 8))]
3274   if (! fp_arith_reg_operand (operands[1], SImode))
3275     {
3276       emit_move_insn (operands[7], operands[1]);
3277       operands[1] = operands[7];
3278     }
3279   if (! fp_arith_reg_operand (operands[2], SImode))
3280     {
3281       emit_move_insn (operands[8], operands[2]);
3282       operands[2] = operands[8];
3283     }
3285   [(set_attr "highpart" "must_split")])
3287 ;; -------------------------------------------------------------------------
3288 ;; Multiplication instructions
3289 ;; -------------------------------------------------------------------------
3291 (define_insn "umulhisi3_i"
3292   [(set (reg:SI MACL_REG)
3293         (mult:SI (zero_extend:SI
3294                   (match_operand:HI 0 "arith_reg_operand" "r"))
3295                  (zero_extend:SI
3296                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
3297   "TARGET_SH1"
3298   "mulu.w       %1,%0"
3299   [(set_attr "type" "smpy")])
3301 (define_insn "mulhisi3_i"
3302   [(set (reg:SI MACL_REG)
3303         (mult:SI (sign_extend:SI
3304                   (match_operand:HI 0 "arith_reg_operand" "r"))
3305                  (sign_extend:SI
3306                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
3307   "TARGET_SH1"
3308   "muls.w       %1,%0"
3309   [(set_attr "type" "smpy")])
3311 (define_expand "mulhisi3"
3312   [(set (reg:SI MACL_REG)
3313         (mult:SI (sign_extend:SI
3314                   (match_operand:HI 1 "arith_reg_operand" ""))
3315                  (sign_extend:SI
3316                   (match_operand:HI 2 "arith_reg_operand" ""))))
3317    (set (match_operand:SI 0 "arith_reg_operand" "")
3318         (reg:SI MACL_REG))]
3319   "TARGET_SH1"
3321   rtx insn, macl;
3323   macl = gen_rtx_REG (SImode, MACL_REG);
3324   start_sequence ();
3325   emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3326   insn = get_insns ();  
3327   end_sequence ();
3328   /* expand_binop can't find a suitable code in umul_widen_optab to
3329      make a REG_EQUAL note from, so make one here.
3330      See also smulsi3_highpart.
3331      ??? Alternatively, we could put this at the calling site of expand_binop,
3332      i.e. expand_expr.  */
3333   /* Use emit_libcall_block for loop invariant code motion and to make
3334      a REG_EQUAL note.  */
3335   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3337   DONE;
3340 (define_expand "umulhisi3"
3341   [(set (reg:SI MACL_REG)
3342         (mult:SI (zero_extend:SI
3343                   (match_operand:HI 1 "arith_reg_operand" ""))
3344                  (zero_extend:SI
3345                   (match_operand:HI 2 "arith_reg_operand" ""))))
3346    (set (match_operand:SI 0 "arith_reg_operand" "")
3347         (reg:SI MACL_REG))]
3348   "TARGET_SH1"
3350   rtx insn, macl;
3352   macl = gen_rtx_REG (SImode, MACL_REG);
3353   start_sequence ();
3354   emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3355   insn = get_insns ();  
3356   end_sequence ();
3357   /* expand_binop can't find a suitable code in umul_widen_optab to
3358      make a REG_EQUAL note from, so make one here.
3359      See also smulsi3_highpart.
3360      ??? Alternatively, we could put this at the calling site of expand_binop,
3361      i.e. expand_expr.  */
3362   /* Use emit_libcall_block for loop invariant code motion and to make
3363      a REG_EQUAL note.  */
3364   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3366   DONE;
3369 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3370 ;; a call to a routine which clobbers known registers.
3371 (define_insn ""
3372   [(set (match_operand:SI 1 "register_operand" "=z")
3373         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3374    (clobber (reg:SI MACL_REG))
3375    (clobber (reg:SI T_REG))
3376    (clobber (reg:SI PR_REG))
3377    (clobber (reg:SI R3_REG))
3378    (clobber (reg:SI R2_REG))
3379    (clobber (reg:SI R1_REG))
3380    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3381   "TARGET_SH1"
3382   "jsr  @%0%#"
3383   [(set_attr "type" "sfunc")
3384    (set_attr "needs_delay_slot" "yes")])
3386 (define_expand "mulsi3_call"
3387   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3388    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3389    (parallel[(set (match_operand:SI 0 "register_operand" "")
3390                   (mult:SI (reg:SI R4_REG)
3391                            (reg:SI R5_REG)))
3392              (clobber (reg:SI MACL_REG))
3393              (clobber (reg:SI T_REG))
3394              (clobber (reg:SI PR_REG))
3395              (clobber (reg:SI R3_REG))
3396              (clobber (reg:SI R2_REG))
3397              (clobber (reg:SI R1_REG))
3398              (use (match_operand:SI 3 "register_operand" ""))])]
3399   "TARGET_SH1"
3400   "")
3402 (define_insn "mul_r"
3403   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3404         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3405                  (match_operand:SI 2 "arith_reg_operand" "z")))]
3406   "TARGET_SH2A"
3407   "mulr %2,%0"
3408   [(set_attr "type" "dmpy")])
3410 (define_insn "mul_l"
3411   [(set (reg:SI MACL_REG)
3412         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3413                  (match_operand:SI 1 "arith_reg_operand" "r")))]
3414   "TARGET_SH2"
3415   "mul.l        %1,%0"
3416   [(set_attr "type" "dmpy")])
3418 (define_expand "mulsi3"
3419   [(set (reg:SI MACL_REG)
3420         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
3421                   (match_operand:SI 2 "arith_reg_operand" "")))
3422    (set (match_operand:SI 0 "arith_reg_operand" "")
3423         (reg:SI MACL_REG))]
3424   "TARGET_SH1"
3426   if (!TARGET_SH2)
3427     {
3428       /* The address must be set outside the libcall,
3429          since it goes into a pseudo.  */
3430       rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3431       rtx addr = force_reg (SImode, sym);
3432       rtx insns = gen_mulsi3_call (operands[0], operands[1],
3433                                    operands[2], addr);
3434       emit_insn (insns);
3435     }
3436   else
3437     {
3438       rtx macl = gen_rtx_REG (SImode, MACL_REG);
3440       emit_insn (gen_mul_l (operands[1], operands[2]));
3441       /* consec_sets_giv can only recognize the first insn that sets a
3442          giv as the giv insn.  So we must tag this also with a REG_EQUAL
3443          note.  */
3444       emit_insn (gen_movsi_i ((operands[0]), macl));
3445     }
3446   DONE;
3449 (define_insn "mulsidi3_i"
3450   [(set (reg:SI MACH_REG)
3451         (truncate:SI
3452          (lshiftrt:DI
3453           (mult:DI
3454            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3455            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3456           (const_int 32))))
3457    (set (reg:SI MACL_REG)
3458         (mult:SI (match_dup 0)
3459                  (match_dup 1)))]
3460   "TARGET_SH2"
3461   "dmuls.l      %1,%0"
3462   [(set_attr "type" "dmpy")])
3464 (define_expand "mulsidi3"
3465   [(set (match_operand:DI 0 "arith_reg_dest" "")
3466         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3467                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3468   "TARGET_SH2 || TARGET_SHMEDIA"
3470   if (TARGET_SH2)
3471     {
3472       emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3473       DONE;
3474     }
3477 (define_insn "mulsidi3_media"
3478   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3479         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3480                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3481   "TARGET_SHMEDIA"
3482   "muls.l       %1, %2, %0"
3483   [(set_attr "type" "dmpy_media")
3484    (set_attr "highpart" "ignore")])
3486 (define_insn_and_split "mulsidi3_compact"
3487   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3488         (mult:DI
3489          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3490          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3491    (clobber (reg:SI MACH_REG))
3492    (clobber (reg:SI MACL_REG))]
3493   "TARGET_SH2"
3494   "#"
3495   "&& 1"
3496   [(const_int 0)]
3498   rtx low_dst = gen_lowpart (SImode, operands[0]);
3499   rtx high_dst = gen_highpart (SImode, operands[0]);
3501   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3503   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3504   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3505   /* We need something to tag the possible REG_EQUAL notes on to.  */
3506   emit_move_insn (operands[0], operands[0]);
3507   DONE;
3510 (define_insn "umulsidi3_i"
3511   [(set (reg:SI MACH_REG)
3512         (truncate:SI
3513          (lshiftrt:DI
3514           (mult:DI
3515            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3516            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3517           (const_int 32))))
3518    (set (reg:SI MACL_REG)
3519         (mult:SI (match_dup 0)
3520                  (match_dup 1)))]
3521   "TARGET_SH2"
3522   "dmulu.l      %1,%0"
3523   [(set_attr "type" "dmpy")])
3525 (define_expand "umulsidi3"
3526   [(set (match_operand:DI 0 "arith_reg_dest" "")
3527         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3528                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3529   "TARGET_SH2 || TARGET_SHMEDIA"
3531   if (TARGET_SH2)
3532     {
3533       emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3534       DONE;
3535     }
3538 (define_insn "umulsidi3_media"
3539   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3540         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3541                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3542   "TARGET_SHMEDIA"
3543   "mulu.l       %1, %2, %0"
3544   [(set_attr "type" "dmpy_media")
3545    (set_attr "highpart" "ignore")])
3547 (define_insn_and_split "umulsidi3_compact"
3548   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3549         (mult:DI
3550          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3551          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3552    (clobber (reg:SI MACH_REG))
3553    (clobber (reg:SI MACL_REG))]
3554   "TARGET_SH2"
3555   "#"
3556   "&& 1"
3557   [(const_int 0)]
3559   rtx low_dst = gen_lowpart (SImode, operands[0]);
3560   rtx high_dst = gen_highpart (SImode, operands[0]);
3562   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3564   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3565   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3566   /* We need something to tag the possible REG_EQUAL notes on to.  */
3567   emit_move_insn (operands[0], operands[0]);
3568   DONE;
3571 (define_insn "smulsi3_highpart_i"
3572   [(set (reg:SI MACH_REG)
3573         (truncate:SI
3574          (lshiftrt:DI
3575           (mult:DI
3576            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3577            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3578           (const_int 32))))
3579    (clobber (reg:SI MACL_REG))]
3580   "TARGET_SH2"
3581   "dmuls.l      %1,%0"
3582   [(set_attr "type" "dmpy")])
3584 (define_expand "smulsi3_highpart"
3585   [(parallel
3586     [(set (reg:SI MACH_REG)
3587           (truncate:SI
3588            (lshiftrt:DI
3589             (mult:DI
3590              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3591              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3592             (const_int 32))))
3593     (clobber (reg:SI MACL_REG))])
3594    (set (match_operand:SI 0 "arith_reg_operand" "")
3595         (reg:SI MACH_REG))]
3596   "TARGET_SH2"
3598   rtx insn, mach;
3600   mach = gen_rtx_REG (SImode, MACH_REG);
3601   start_sequence ();
3602   emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3603   insn = get_insns ();  
3604   end_sequence ();
3605   /* expand_binop can't find a suitable code in mul_highpart_optab to
3606      make a REG_EQUAL note from, so make one here.
3607      See also {,u}mulhisi.
3608      ??? Alternatively, we could put this at the calling site of expand_binop,
3609      i.e. expand_mult_highpart.  */
3610   /* Use emit_libcall_block for loop invariant code motion and to make
3611      a REG_EQUAL note.  */
3612   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3614   DONE;
3617 (define_insn "umulsi3_highpart_i"
3618   [(set (reg:SI MACH_REG)
3619         (truncate:SI
3620          (lshiftrt:DI
3621           (mult:DI
3622            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3623            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3624           (const_int 32))))
3625    (clobber (reg:SI MACL_REG))]
3626   "TARGET_SH2"
3627   "dmulu.l      %1,%0"
3628   [(set_attr "type" "dmpy")])
3630 (define_expand "umulsi3_highpart"
3631   [(parallel
3632     [(set (reg:SI MACH_REG)
3633           (truncate:SI
3634            (lshiftrt:DI
3635             (mult:DI
3636              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3637              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3638             (const_int 32))))
3639     (clobber (reg:SI MACL_REG))])
3640    (set (match_operand:SI 0 "arith_reg_operand" "")
3641         (reg:SI MACH_REG))]
3642   "TARGET_SH2"
3644   rtx insn, mach;
3646   mach = gen_rtx_REG (SImode, MACH_REG);
3647   start_sequence ();
3648   emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3649   insn = get_insns ();  
3650   end_sequence ();
3651   /* Use emit_libcall_block for loop invariant code motion and to make
3652      a REG_EQUAL note.  */
3653   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3655   DONE;
3658 (define_insn_and_split "muldi3"
3659   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3660         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3661                  (match_operand:DI 2 "arith_reg_operand" "r")))
3662    (clobber (match_scratch:DI 3 "=&r"))
3663    (clobber (match_scratch:DI 4 "=r"))]
3664   "TARGET_SHMEDIA"
3665   "#"
3666   "reload_completed"
3667   [(const_int 0)]
3669   rtx op3_v2si, op2_v2si;
3671   op3_v2si = operands[3];
3672   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3673     {
3674       op3_v2si = XEXP (op3_v2si, 0);
3675       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3676     }
3677   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3678   op2_v2si = operands[2];
3679   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3680     {
3681       op2_v2si = XEXP (op2_v2si, 0);
3682       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3683     }
3684   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3685   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3686   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3687   emit_insn (gen_umulsidi3_media (operands[4],
3688                                  sh_gen_truncate (SImode, operands[1], 0),
3689                                  sh_gen_truncate (SImode, operands[2], 0)));
3690   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3691   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3692   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3693   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3694   DONE;
3697 ;; -------------------------------------------------------------------------
3698 ;; Logical operations
3699 ;; -------------------------------------------------------------------------
3701 (define_expand "andsi3"
3702   [(set (match_operand:SI 0 "arith_reg_operand" "")
3703         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3704                 (match_operand:SI 2 "logical_and_operand" "")))]
3705   ""
3707   /* If it is possible to turn the and insn into a zero extension
3708      already, redundant zero extensions will be folded, which results
3709      in better code.  
3710      Ideally the splitter of *andsi_compact would be enough, if redundant
3711      zero extensions were detected after the combine pass, which does not
3712      happen at the moment.  */
3713   if (TARGET_SH1)
3714     {
3715       if (satisfies_constraint_Jmb (operands[2]))
3716         {
3717           emit_insn (gen_zero_extendqisi2 (operands[0],
3718                                            gen_lowpart (QImode, operands[1])));
3719           DONE;
3720         }
3721       else if (satisfies_constraint_Jmw (operands[2]))
3722         {
3723           emit_insn (gen_zero_extendhisi2 (operands[0],
3724                                            gen_lowpart (HImode, operands[1])));
3725           DONE;
3726         }
3727     }
3730 (define_insn_and_split "*andsi_compact"
3731   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3732         (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3733                 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3734   "TARGET_SH1"
3735   "@
3736         extu.b  %1,%0
3737         extu.w  %1,%0
3738         and     %2,%0
3739         and     %2,%0"
3740   "&& 1"
3741  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3743   if (satisfies_constraint_Jmb (operands[2]))
3744     operands[1] = gen_lowpart (QImode, operands[1]);
3745   else if (satisfies_constraint_Jmw (operands[2]))
3746     operands[1] = gen_lowpart (HImode, operands[1]);
3747   else
3748     FAIL;
3750   [(set_attr "type" "arith")])
3752 (define_insn "*andsi3_media"
3753   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3754         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3755                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3756   "TARGET_SHMEDIA"
3757   "@
3758         and     %1, %2, %0
3759         andi    %1, %2, %0"
3760   [(set_attr "type" "arith_media")])
3762 (define_insn "*andsi3_bclr"
3763   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3764         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3765                 (match_operand:SI 2 "const_int_operand" "Psz")))]
3766   "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3767   "bclr %W2,%0"
3768   [(set_attr "type" "arith")])
3770 (define_insn_and_split "anddi3"
3771   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3772         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3773                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3774   "TARGET_SHMEDIA"
3775   "@
3776         and     %1, %2, %0
3777         andi    %1, %2, %0
3778         #"
3779   "reload_completed
3780    && ! logical_operand (operands[2], DImode)"
3781   [(const_int 0)]
3783   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3784     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3785   else
3786     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3787   DONE;
3789   [(set_attr "type" "arith_media")])
3791 (define_insn "andcsi3"
3792   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3793         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3794                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3795   "TARGET_SHMEDIA"
3796   "andc %1,%2,%0"
3797   [(set_attr "type" "arith_media")])
3799 (define_insn "andcdi3"
3800   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3801         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3802                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3803   "TARGET_SHMEDIA"
3804   "andc %1,%2,%0"
3805   [(set_attr "type" "arith_media")])
3807 (define_expand "iorsi3"
3808   [(set (match_operand:SI 0 "arith_reg_operand" "")
3809         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3810                 (match_operand:SI 2 "logical_operand" "")))]
3811   ""
3812   "")
3814 (define_insn "*iorsi3_compact"
3815   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3816         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3817                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3818   "TARGET_SH1
3819    && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3820   "or   %2,%0"
3821   [(set_attr "type" "arith")])
3823 (define_insn "*iorsi3_media"
3824   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3825         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3826                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3827   "TARGET_SHMEDIA"
3828   "@
3829         or      %1, %2, %0
3830         ori     %1, %2, %0"
3831   [(set_attr "type" "arith_media")])
3833 (define_insn "*iorsi3_bset"
3834   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3835         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3836         (match_operand:SI 2 "const_int_operand" "Pso")))]
3837   "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3838   "bset %V2,%0"
3839   [(set_attr "type" "arith")])
3841 (define_insn "iordi3"
3842   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3843         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3844                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3845   "TARGET_SHMEDIA"
3846   "@
3847         or      %1, %2, %0
3848         ori     %1, %2, %0"
3849   [(set_attr "type" "arith_media")])
3851 (define_insn_and_split "*logical_sidi3"
3852   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3853         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3854                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3855                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3856   "TARGET_SHMEDIA"
3857   "#"
3858   "&& reload_completed"
3859   [(set (match_dup 0) (match_dup 3))]
3861   operands[3]
3862     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3863                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3864                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3867 (define_insn_and_split "*logical_sidisi3"
3868   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3869         (truncate:SI (sign_extend:DI
3870                         (match_operator:SI 3 "logical_operator"
3871                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3872                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3873   "TARGET_SHMEDIA"
3874   "#"
3875   "&& 1"
3876   [(set (match_dup 0) (match_dup 3))])
3878 (define_insn_and_split "*logical_sidi3_2"
3879   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3880         (sign_extend:DI (truncate:SI (sign_extend:DI
3881                         (match_operator:SI 3 "logical_operator"
3882                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3883                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3884   "TARGET_SHMEDIA"
3885   "#"
3886   "&& 1"
3887   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3889 (define_expand "xorsi3"
3890   [(set (match_operand:SI 0 "arith_reg_operand" "")
3891         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3892                 (match_operand:SI 2 "xor_operand" "")))]
3893   ""
3894   "")
3896 (define_insn "*xorsi3_compact"
3897   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3898         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3899                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3900   "TARGET_SH1"
3901   "xor  %2,%0"
3902   [(set_attr "type" "arith")])
3904 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3905 ;; of results where one of the inputs is a T bit store.  Notice that this
3906 ;; pattern must not match during reload.  If reload picks this pattern it
3907 ;; will be impossible to split it afterwards.
3908 (define_insn_and_split "*logical_op_t"
3909   [(set (match_operand:SI 0 "arith_reg_dest")
3910         (match_operator:SI 3 "logical_operator"
3911           [(match_operand:SI 1 "arith_reg_operand")
3912            (match_operand:SI 2 "t_reg_operand")]))]
3913   "TARGET_SH1 && can_create_pseudo_p ()"
3914   "#"
3915   "&& 1"
3916   [(set (match_dup 4) (reg:SI T_REG))
3917    (set (match_dup 0) (match_dup 3))]
3919   operands[4] = gen_reg_rtx (SImode);
3920   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3921                                 operands[1], operands[4]);
3924 (define_insn "*xorsi3_media"
3925   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3926         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3927                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3928   "TARGET_SHMEDIA"
3929   "@
3930         xor     %1, %2, %0
3931         xori    %1, %2, %0"
3932   [(set_attr "type" "arith_media")])
3934 (define_insn "xordi3"
3935   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3936         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3937                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3938   "TARGET_SHMEDIA"
3939   "@
3940         xor     %1, %2, %0
3941         xori    %1, %2, %0"
3942   [(set_attr "type" "arith_media")])
3944 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3945 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3946 (define_split
3947   [(set (match_operand:DI 0 "arith_reg_dest" "")
3948         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3949                           [(match_operand 1 "any_register_operand" "")
3950                            (match_operand 2 "any_register_operand" "")])))]
3951   "TARGET_SHMEDIA"
3952   [(set (match_dup 5) (match_dup 4))
3953    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3955   enum machine_mode inmode = GET_MODE (operands[1]);
3956   int offset = 0;
3958   if (GET_CODE (operands[0]) == SUBREG)
3959     {
3960       offset = SUBREG_BYTE (operands[0]);
3961       operands[0] = SUBREG_REG (operands[0]);
3962     }
3963   gcc_assert (REG_P (operands[0]));
3964   if (TARGET_BIG_ENDIAN)
3965     offset += 8 - GET_MODE_SIZE (inmode);
3966   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3969 ;; -------------------------------------------------------------------------
3970 ;; Shifts and rotates
3971 ;; -------------------------------------------------------------------------
3973 (define_expand "rotldi3"
3974   [(set (match_operand:DI 0 "arith_reg_dest" "")
3975         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3976                    (match_operand:HI 2 "mextr_bit_offset" "")))]
3977   "TARGET_SHMEDIA"
3979   if (! mextr_bit_offset (operands[2], HImode))
3980     FAIL;
3983 (define_insn "rotldi3_mextr"
3984   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3985         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3986                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3987   "TARGET_SHMEDIA"
3989   static char templ[16];
3990   sprintf (templ, "mextr%d      %%1,%%1,%%0",
3991            8 - (int) (INTVAL (operands[2]) >> 3));
3992   return templ;
3994   [(set_attr "type" "arith_media")])
3996 (define_expand "rotrdi3"
3997   [(set (match_operand:DI 0 "arith_reg_dest" "")
3998         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
3999                      (match_operand:HI 2 "mextr_bit_offset" "")))]
4000   "TARGET_SHMEDIA"
4002   if (! mextr_bit_offset (operands[2], HImode))
4003     FAIL;
4006 (define_insn "rotrdi3_mextr"
4007   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4008         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
4009                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
4010   "TARGET_SHMEDIA"
4012   static char templ[16];
4013   sprintf (templ, "mextr%d      %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
4014   return templ;
4016   [(set_attr "type" "arith_media")])
4018 (define_split
4019   [(set (match_operand:DI 0 "arith_reg_dest" "")
4020         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
4021                                          "ua_address_operand" "")))
4022                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
4023                            (const_int 8))))
4024    (clobber (match_operand:DI 3 "register_operand" ""))]
4025   "TARGET_SHMEDIA"
4026   [(match_dup 4) (match_dup 5)]
4028   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
4029                  (operands[3], operands[1]));
4030   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
4031                               GEN_INT (56), GEN_INT (8));
4034 (define_expand "rotrsi3"
4035   [(set (match_operand:SI 0 "arith_reg_dest")
4036         (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
4037                      (match_operand:SI 2 "const_int_operand")))]
4038   "TARGET_SH1"
4040   HOST_WIDE_INT ival = INTVAL (operands[2]);
4041   if (ival == 1)
4042     {
4043       emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
4044       DONE;
4045     }
4047   FAIL;
4050 (define_insn "rotrsi3_1"
4051   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4052         (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4053                      (const_int 1)))
4054    (set (reg:SI T_REG)
4055         (and:SI (match_dup 1) (const_int 1)))]
4056   "TARGET_SH1"
4057   "rotr %0"
4058   [(set_attr "type" "arith")])
4060 ;; A slimplified version of rotr for combine.
4061 (define_insn "*rotrsi3_1"
4062   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4063         (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4064                      (const_int 1)))
4065    (clobber (reg:SI T_REG))]
4066   "TARGET_SH1"
4067   "rotr %0"
4068   [(set_attr "type" "arith")])
4070 (define_insn "rotlsi3_1"
4071   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4072         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4073                    (const_int 1)))
4074    (set (reg:SI T_REG)
4075         (lshiftrt:SI (match_dup 1) (const_int 31)))]
4076   "TARGET_SH1"
4077   "rotl %0"
4078   [(set_attr "type" "arith")])
4080 ;; A simplified version of rotl for combine.
4081 (define_insn "*rotlsi3_1"
4082   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4083         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4084                    (const_int 1)))
4085    (clobber (reg:SI T_REG))]
4086   "TARGET_SH1"
4087   "rotl %0"
4088   [(set_attr "type" "arith")])
4090 (define_insn "rotlsi3_31"
4091   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4092         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4093                    (const_int 31)))
4094    (clobber (reg:SI T_REG))]
4095   "TARGET_SH1"
4096   "rotr %0"
4097   [(set_attr "type" "arith")])
4099 (define_insn "rotlsi3_16"
4100   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4101         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4102                    (const_int 16)))]
4103   "TARGET_SH1"
4104   "swap.w       %1,%0"
4105   [(set_attr "type" "arith")])
4107 (define_expand "rotlsi3"
4108   [(set (match_operand:SI 0 "arith_reg_dest")
4109         (rotate:SI (match_operand:SI 1 "arith_reg_operand")
4110                    (match_operand:SI 2 "const_int_operand")))]
4111   "TARGET_SH1"
4113   static const char rot_tab[] = {
4114     000, 000, 000, 000, 000, 000, 010, 001,
4115     001, 001, 011, 013, 003, 003, 003, 003,
4116     003, 003, 003, 003, 003, 013, 012, 002,
4117     002, 002, 010, 000, 000, 000, 000, 000,
4118   };
4120   int count = INTVAL (operands[2]);
4121   int choice = rot_tab[count];
4122   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4123     FAIL;
4124   choice &= 7;
4125   switch (choice)
4126     {
4127     case 0:
4128       emit_move_insn (operands[0], operands[1]);
4129       count -= (count & 16) * 2;
4130       break;
4131     case 3:
4132      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4133      count -= 16;
4134      break;
4135     case 1:
4136     case 2:
4137       {
4138         rtx parts[2];
4139         parts[0] = gen_reg_rtx (SImode);
4140         parts[1] = gen_reg_rtx (SImode);
4141         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4142         emit_move_insn (parts[choice-1], operands[1]);
4143         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4144         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4145         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4146         count = (count & ~16) - 8;
4147       }
4148     }
4150   for (; count > 0; count--)
4151     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4152   for (; count < 0; count++)
4153     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4155   DONE;
4158 (define_insn "rotlhi3_8"
4159   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4160         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4161                    (const_int 8)))]
4162   "TARGET_SH1"
4163   "swap.b       %1,%0"
4164   [(set_attr "type" "arith")])
4166 (define_expand "rotlhi3"
4167   [(set (match_operand:HI 0 "arith_reg_operand")
4168         (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4169                    (match_operand:HI 2 "const_int_operand")))]
4170   "TARGET_SH1"
4172   if (INTVAL (operands[2]) != 8)
4173     FAIL;
4176 ;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4177 ;; They can also be used to implement things like
4178 ;;      bool t = a == b;
4179 ;;      int x0 = (y >> 1) | (t << 31);  // rotcr
4180 ;;      int x1 = (y << 1) | t;          // rotcl
4181 (define_insn "rotcr"
4182   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4183         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4184                              (const_int 1))
4185                 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4186                            (const_int 31))))
4187    (set (reg:SI T_REG)
4188         (and:SI (match_dup 1) (const_int 1)))]
4189   "TARGET_SH1"
4190   "rotcr        %0"
4191   [(set_attr "type" "arith")])
4193 (define_insn "rotcl"
4194   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4195         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4196                            (const_int 1))
4197                 (match_operand:SI 2 "t_reg_operand")))
4198    (set (reg:SI T_REG)
4199         (lshiftrt:SI (match_dup 1) (const_int 31)))]
4200   "TARGET_SH1"
4201   "rotcl        %0"
4202   [(set_attr "type" "arith")])
4204 ;; Simplified rotcr version for combine, which allows arbitrary shift
4205 ;; amounts for the reg.  If the shift amount is '1' rotcr can be used
4206 ;; directly.  Otherwise we have to insert a shift in between.
4207 (define_insn_and_split "*rotcr"
4208   [(set (match_operand:SI 0 "arith_reg_dest")
4209         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4210                              (match_operand:SI 2 "const_int_operand"))
4211                 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4212                            (const_int 31))))
4213    (clobber (reg:SI T_REG))]
4214   "TARGET_SH1"
4215   "#"
4216   "&& can_create_pseudo_p ()"
4217   [(const_int 0)]
4219   if (INTVAL (operands[2]) > 1)
4220     {
4221       const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4222       rtx prev_set_t_insn = NULL_RTX;
4223       rtx tmp_t_reg = NULL_RTX;
4225       /* If we're going to emit a shift sequence that clobbers the T_REG,
4226          try to find the previous insn that sets the T_REG and emit the 
4227          shift insn before that insn, to remove the T_REG dependency.
4228          If the insn that sets the T_REG cannot be found, store the T_REG
4229          in a temporary reg and restore it after the shift.  */
4230       if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4231           && ! sh_dynamicalize_shift_p (shift_count))
4232         {
4233           prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4235           /* Skip the nott insn, which was probably inserted by the splitter
4236              of *rotcr_neg_t.  Don't use one of the recog functions
4237              here during insn splitting, since that causes problems in later
4238              passes.  */
4239           if (prev_set_t_insn != NULL_RTX)
4240             {
4241               rtx pat = PATTERN (prev_set_t_insn);
4242               if (GET_CODE (pat) == SET
4243                   && t_reg_operand (XEXP (pat, 0), SImode)
4244                   && negt_reg_operand (XEXP (pat, 1), SImode))
4245               prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4246             }
4248           if (! (prev_set_t_insn != NULL_RTX
4249                  && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4250                  && ! reg_referenced_p (get_t_reg_rtx (),
4251                                         PATTERN (prev_set_t_insn))))
4252             {
4253               prev_set_t_insn = NULL_RTX;
4254               tmp_t_reg = gen_reg_rtx (SImode);
4255               emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4256             } 
4257         }
4259       rtx shift_result = gen_reg_rtx (SImode);
4260       rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4261       operands[1] = shift_result;
4263       /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4264       if (prev_set_t_insn != NULL_RTX)
4265         emit_insn_before (shift_insn, prev_set_t_insn);
4266       else
4267         emit_insn (shift_insn);
4269       /* Restore T_REG if it has been saved before.  */
4270       if (tmp_t_reg != NULL_RTX)
4271         emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4272     }
4274   /* For the rotcr insn to work, operands[3] must be in T_REG.
4275      If it is not we can get it there by shifting it right one bit.
4276      In this case T_REG is not an input for this insn, thus we don't have to
4277      pay attention as of where to insert the shlr insn.  */
4278   if (! t_reg_operand (operands[3], SImode))
4279     {
4280       /* We don't care about the shifted result here, only the T_REG.  */
4281       emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4282       operands[3] = get_t_reg_rtx ();
4283     }
4285   emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4286   DONE;
4289 ;; If combine tries the same as above but with swapped operands, split
4290 ;; it so that it will try the pattern above.
4291 (define_split
4292   [(set (match_operand:SI 0 "arith_reg_dest")
4293         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4294                            (const_int 31))
4295                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4296                              (match_operand:SI 3 "const_int_operand"))))]
4297   "TARGET_SH1 && can_create_pseudo_p ()"
4298   [(parallel [(set (match_dup 0)
4299                    (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4300                            (ashift:SI (match_dup 1) (const_int 31))))
4301               (clobber (reg:SI T_REG))])])
4303 ;; Basically the same as the rotcr pattern above, but for rotcl.
4304 ;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4305 (define_insn_and_split "*rotcl"
4306   [(set (match_operand:SI 0 "arith_reg_dest")
4307         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4308                            (match_operand:SI 2 "const_int_operand"))
4309                 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4310                         (const_int 1))))
4311    (clobber (reg:SI T_REG))]
4312   "TARGET_SH1"
4313   "#"
4314   "&& can_create_pseudo_p ()"
4315   [(const_int 0)]
4317   gcc_assert (INTVAL (operands[2]) > 0);
4319   if (INTVAL (operands[2]) > 1)
4320     {
4321       const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4322       rtx prev_set_t_insn = NULL_RTX;
4323       rtx tmp_t_reg = NULL_RTX;
4325       /* If we're going to emit a shift sequence that clobbers the T_REG,
4326          try to find the previous insn that sets the T_REG and emit the 
4327          shift insn before that insn, to remove the T_REG dependency.
4328          If the insn that sets the T_REG cannot be found, store the T_REG
4329          in a temporary reg and restore it after the shift.  */
4330       if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4331           && ! sh_dynamicalize_shift_p (shift_count))
4332         {
4333           prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4335           /* Skip the nott insn, which was probably inserted by the splitter
4336              of *rotcl_neg_t.  Don't use one of the recog functions
4337              here during insn splitting, since that causes problems in later
4338              passes.  */
4339           if (prev_set_t_insn != NULL_RTX)
4340             {
4341               rtx pat = PATTERN (prev_set_t_insn);
4342               if (GET_CODE (pat) == SET
4343                   && t_reg_operand (XEXP (pat, 0), SImode)
4344                   && negt_reg_operand (XEXP (pat, 1), SImode))
4345               prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4346             }
4348           if (! (prev_set_t_insn != NULL_RTX
4349                  && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4350                  && ! reg_referenced_p (get_t_reg_rtx (),
4351                                         PATTERN (prev_set_t_insn))))
4352             {
4353               prev_set_t_insn = NULL_RTX;
4354               tmp_t_reg = gen_reg_rtx (SImode);
4355               emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4356             } 
4357         }
4359       rtx shift_result = gen_reg_rtx (SImode);
4360       rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4361       operands[1] = shift_result;
4363       /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4364       if (prev_set_t_insn != NULL_RTX)
4365         emit_insn_before (shift_insn, prev_set_t_insn);
4366       else
4367         emit_insn (shift_insn);
4369       /* Restore T_REG if it has been saved before.  */
4370       if (tmp_t_reg != NULL_RTX)
4371         emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4372     }
4374   /* For the rotcl insn to work, operands[3] must be in T_REG.
4375      If it is not we can get it there by shifting it right one bit.
4376      In this case T_REG is not an input for this insn, thus we don't have to
4377      pay attention as of where to insert the shlr insn.  */
4378   if (! t_reg_operand (operands[3], SImode))
4379     {
4380       /* We don't care about the shifted result here, only the T_REG.  */
4381       emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4382       operands[3] = get_t_reg_rtx ();
4383     }
4385   emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4386   DONE;
4389 ;; rotcl combine pattern variations
4390 (define_insn_and_split "*rotcl"
4391   [(set (match_operand:SI 0 "arith_reg_dest")
4392         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4393                            (match_operand:SI 2 "const_int_operand"))
4394                 (match_operand:SI 3 "t_reg_operand")))
4395    (clobber (reg:SI T_REG))]
4396   "TARGET_SH1"
4397   "#"
4398   "&& can_create_pseudo_p ()"
4399   [(parallel [(set (match_dup 0)
4400                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4401                            (and:SI (match_dup 3) (const_int 1))))
4402               (clobber (reg:SI T_REG))])])
4404 (define_insn_and_split "*rotcl"
4405   [(set (match_operand:SI 0 "arith_reg_dest")
4406         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4407                         (const_int 1))
4408                 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4409                            (match_operand:SI 3 "const_int_operand"))))
4410    (clobber (reg:SI T_REG))]
4411   "TARGET_SH1"
4412   "#"
4413   "&& can_create_pseudo_p ()"
4414   [(parallel [(set (match_dup 0)
4415                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4416                            (and:SI (match_dup 1) (const_int 1))))
4417               (clobber (reg:SI T_REG))])])
4419 (define_insn_and_split "*rotcl"
4420   [(set (match_operand:SI 0 "arith_reg_dest")
4421         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4422                            (match_operand:SI 2 "const_int_operand"))
4423                 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4424                              (const_int 31))))
4425    (clobber (reg:SI T_REG))]
4426   "TARGET_SH1"
4427   "#"
4428   "&& can_create_pseudo_p ()"
4429   [(parallel [(set (match_dup 0)
4430                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4431                            (and:SI (reg:SI T_REG) (const_int 1))))
4432               (clobber (reg:SI T_REG))])]
4434   /* We don't care about the result of the left shift, only the T_REG.  */
4435   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4438 (define_insn_and_split "*rotcl"
4439   [(set (match_operand:SI 0 "arith_reg_dest")
4440         (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4441                              (const_int 31))
4442                 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4443                            (match_operand:SI 2 "const_int_operand"))))
4444    (clobber (reg:SI T_REG))]
4445   "TARGET_SH1"
4446   "#"
4447   "&& can_create_pseudo_p ()"
4448   [(parallel [(set (match_dup 0)
4449                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4450                            (and:SI (reg:SI T_REG) (const_int 1))))
4451               (clobber (reg:SI T_REG))])]
4453   /* We don't care about the result of the left shift, only the T_REG.  */
4454   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4457 ;; rotcr combine bridge pattern which will make combine try out more
4458 ;; complex patterns.
4459 (define_insn_and_split "*rotcr"
4460   [(set (match_operand:SI 0 "arith_reg_dest")
4461         (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4462   "TARGET_SH1"
4463   "#"
4464   "&& 1"
4465   [(set (match_dup 0) (match_dup 1))
4466    (parallel [(set (match_dup 0)
4467                    (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4468                            (ashift:SI (match_dup 1) (const_int 31))))
4469               (set (reg:SI T_REG)
4470                    (and:SI (match_dup 0) (const_int 1)))])])
4472 (define_insn_and_split "*rotcr"
4473   [(set (match_operand:SI 0 "arith_reg_dest")
4474         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4475                         (const_int -2147483648)) ;; 0xffffffff80000000
4476                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4477                              (const_int 1))))
4478    (clobber (reg:SI T_REG))]
4479   "TARGET_SH1"
4480   "#"
4481   "&& can_create_pseudo_p ()"
4482   [(const_int 0)]
4484   rtx tmp = gen_reg_rtx (SImode);
4485   emit_insn (gen_shll (tmp, operands[1]));
4486   emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4487   DONE;
4490 ;; rotcr combine patterns for rotating in the negated T_REG value.
4491 (define_insn_and_split "*rotcr_neg_t"
4492   [(set (match_operand:SI 0 "arith_reg_dest")
4493         (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4494                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4495                              (match_operand:SI 3 "const_int_operand"))))
4496    (clobber (reg:SI T_REG))]
4497   "TARGET_SH1"
4498   "#"
4499   "&& can_create_pseudo_p ()"
4500   [(parallel [(set (match_dup 0)
4501                    (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4502                            (ashift:SI (reg:SI T_REG) (const_int 31))))
4503               (clobber (reg:SI T_REG))])]
4505   emit_insn (gen_nott (get_t_reg_rtx ()));
4508 (define_insn_and_split "*rotcr_neg_t"
4509   [(set (match_operand:SI 0 "arith_reg_dest")
4510         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4511                              (match_operand:SI 2 "const_int_operand"))
4512                 (match_operand:SI 3 "negt_reg_shl31_operand")))
4513    (clobber (reg:SI T_REG))]
4514   "TARGET_SH1"
4515   "#"
4516   "&& can_create_pseudo_p ()"
4517   [(parallel [(set (match_dup 0)
4518                    (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4519                            (ashift:SI (reg:SI T_REG) (const_int 31))))
4520               (clobber (reg:SI T_REG))])]
4522   emit_insn (gen_nott (get_t_reg_rtx ()));
4525 ;; rotcl combine patterns for rotating in the negated T_REG value.
4526 ;; For some strange reason these have to be specified as splits which combine
4527 ;; will pick up.  If they are specified as insn_and_split like the
4528 ;; *rotcr_neg_t patterns above, combine would recognize them successfully
4529 ;; but not emit them on non-SH2A targets.
4530 (define_split
4531   [(set (match_operand:SI 0 "arith_reg_dest")
4532         (ior:SI (match_operand:SI 1 "negt_reg_operand")
4533                 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4534                            (match_operand:SI 3 "const_int_operand"))))]
4535   "TARGET_SH1"
4536   [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4537    (parallel [(set (match_dup 0)
4538                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4539                            (and:SI (reg:SI T_REG) (const_int 1))))
4540               (clobber (reg:SI T_REG))])])
4542 (define_split
4543   [(set (match_operand:SI 0 "arith_reg_dest")
4544         (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4545                            (match_operand:SI 3 "const_int_operand"))
4546                 (match_operand:SI 1 "negt_reg_operand")))]
4547   "TARGET_SH1"
4548   [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4549    (parallel [(set (match_dup 0)
4550                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4551                            (and:SI (reg:SI T_REG) (const_int 1))))
4552               (clobber (reg:SI T_REG))])])
4554 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4555 ;; SImode shift left
4557 (define_expand "ashlsi3"
4558   [(set (match_operand:SI 0 "arith_reg_operand" "")
4559         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4560                    (match_operand:SI 2 "shift_count_operand" "")))]
4561   ""
4563   if (TARGET_SHMEDIA)
4564     {
4565       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4566       DONE;
4567     }
4568   if (TARGET_DYNSHIFT
4569       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4570       operands[2] = force_reg (SImode, operands[2]);
4572   /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
4573       expanded here.  */
4574   if (CONST_INT_P (operands[2])
4575       && sh_ashlsi_clobbers_t_reg_p (operands[2])
4576       && ! sh_dynamicalize_shift_p (operands[2]))
4577     {
4578       emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4579                                            operands[2]));
4580       DONE;
4581     }
4583   /* Expand a library call for the dynamic shift.  */
4584   if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4585     {
4586       emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4587       rtx funcaddr = gen_reg_rtx (Pmode);
4588       function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4589       emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4591       DONE;
4592     }
4595 (define_insn "ashlsi3_k"
4596   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4597         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4598                    (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4599   "TARGET_SH1"
4600   "@
4601         add     %0,%0
4602         shll%O2 %0"
4603   [(set_attr "type" "arith")])
4605 (define_insn_and_split "ashlsi3_d"
4606   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4607         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4608                    (match_operand:SI 2 "shift_count_operand" "r")))]
4609   "TARGET_DYNSHIFT"
4610   "shld %2,%0"
4611   "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4612    && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4613   [(const_int 0)]
4615   if (satisfies_constraint_P27 (operands[2]))
4616     {
4617       emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4618       DONE;
4619     }
4620   else if (! satisfies_constraint_P27 (operands[2]))
4621     {
4622       /* This must happen before reload, otherwise the constant will be moved
4623          into a register due to the "r" constraint, after which this split
4624          cannot be done anymore.
4625          Unfortunately the move insn will not always be eliminated.
4626          Also, here we must not create a shift sequence that clobbers the
4627          T_REG.  */
4628       emit_move_insn (operands[0], operands[1]);
4629       gen_shifty_op (ASHIFT, operands);
4630       DONE;
4631     }
4633   FAIL;
4635   [(set_attr "type" "dyn_shift")])
4637 ;; If dynamic shifts are not available use a library function.
4638 ;; By specifying the pattern we reduce the number of call clobbered regs.
4639 ;; In order to make combine understand the truncation of the shift amount
4640 ;; operand we have to allow it to use pseudo regs for the shift operands.
4641 (define_insn "ashlsi3_d_call"
4642   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4643         (ashift:SI (reg:SI R4_REG)
4644                    (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4645                            (const_int 31))))
4646    (use (match_operand:SI 2 "arith_reg_operand" "r"))
4647    (clobber (reg:SI T_REG))
4648    (clobber (reg:SI PR_REG))]
4649   "TARGET_SH1 && !TARGET_DYNSHIFT"
4650   "jsr  @%2%#"
4651   [(set_attr "type" "sfunc")
4652    (set_attr "needs_delay_slot" "yes")])
4654 (define_insn_and_split "ashlsi3_n"
4655   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4656         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4657                    (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4658   "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4659   "#"
4660   "&& (reload_completed
4661        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4662   [(const_int 0)]
4664   if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4665     {
4666       /* If this pattern was picked and dynamic shifts are supported, switch
4667          to dynamic shift pattern before reload.  */
4668       operands[2] = force_reg (SImode, operands[2]);
4669       emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4670     }
4671   else
4672     gen_shifty_op (ASHIFT, operands);
4674   DONE;
4677 (define_insn_and_split "ashlsi3_n_clobbers_t"
4678   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4679         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4680                    (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4681    (clobber (reg:SI T_REG))]
4682   "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4683   "#"
4684   "&& (reload_completed || INTVAL (operands[2]) == 31
4685        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4686   [(const_int 0)]
4688   if (INTVAL (operands[2]) == 31)
4689     {
4690       /* If the shift amount is 31 we split into a different sequence before
4691          reload so that it gets a chance to allocate R0 for the sequence.
4692          If it fails to do so (due to pressure on R0), it will take one insn
4693          more for the and.  */
4694       emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4695       emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4696     }
4697   else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4698     {
4699       /* If this pattern was picked and dynamic shifts are supported, switch
4700          to dynamic shift pattern before reload.  */
4701       operands[2] = force_reg (SImode, operands[2]);
4702       emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4703     }
4704   else
4705     gen_shifty_op (ASHIFT, operands);
4707   DONE;
4710 (define_insn "shll"
4711   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4712         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4713    (set (reg:SI T_REG)
4714         (lt:SI (match_dup 1) (const_int 0)))]
4715   "TARGET_SH1"
4716   "shll %0"
4717   [(set_attr "type" "arith")])
4719 (define_insn "*ashlsi_c_void"
4720   [(set (reg:SI T_REG)
4721         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4722    (clobber (match_scratch:SI 1 "=0"))]
4723   "TARGET_SH1 && cse_not_expected"
4724   "shll %0"
4725   [(set_attr "type" "arith")])
4727 (define_peephole2
4728   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4729    (set (reg:SI T_REG)
4730         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4731   "TARGET_SH1
4732    && peep2_reg_dead_p (2, operands[0])
4733    && peep2_reg_dead_p (2, operands[1])"
4734   [(const_int 0)]
4736   emit_insn (gen_shll (operands[1], operands[1]));
4737   DONE;
4740 (define_insn "ashlsi3_media"
4741   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4742         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4743                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
4744   "TARGET_SHMEDIA"
4745   "@
4746         shlld.l %1, %2, %0
4747         shlli.l %1, %2, %0"
4748   [(set_attr "type" "arith_media")
4749    (set_attr "highpart" "ignore")])
4751 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4752 ;; HImode shift left
4754 (define_expand "ashlhi3"
4755   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4756                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4757                               (match_operand:SI 2 "nonmemory_operand" "")))
4758               (clobber (reg:SI T_REG))])]
4759   "TARGET_SH1"
4761   if (!CONST_INT_P (operands[2]))
4762     FAIL;
4763   /* It may be possible to call gen_ashlhi3 directly with more generic
4764      operands.  Make sure operands[1] is a HImode register here.  */
4765   if (!arith_reg_operand (operands[1], HImode))
4766     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4769 (define_insn "ashlhi3_k"
4770   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4771         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4772                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
4773   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4774   "@
4775         add     %0,%0
4776         shll%O2 %0"
4777   [(set_attr "type" "arith")])
4779 (define_insn_and_split "*ashlhi3_n"
4780   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4781         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4782                    (match_operand:HI 2 "const_int_operand" "n")))
4783    (clobber (reg:SI T_REG))]
4784   "TARGET_SH1"
4785   "#"
4786   "&& reload_completed"
4787   [(use (reg:SI R0_REG))]
4789   gen_shifty_hi_op (ASHIFT, operands);
4790   DONE;
4793 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4794 ;; DImode shift left
4796 (define_expand "ashldi3"
4797   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4798                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4799                               (match_operand:DI 2 "immediate_operand" "")))
4800               (clobber (reg:SI T_REG))])]
4801   ""
4803   if (TARGET_SHMEDIA)
4804     {
4805       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4806       DONE;
4807     }
4808   if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4809     {
4810       emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4811       DONE;
4812     }
4813   else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4814     {
4815       emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4816       DONE;
4817     }
4818   else
4819     FAIL;
4822 ;; Expander for DImode shift left with SImode operations.
4823 (define_expand "ashldi3_std"
4824   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4825         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4826                    (match_operand:DI 2 "const_int_operand" "n")))]
4827   "TARGET_SH1 && INTVAL (operands[2]) < 32"
4829   rtx low_src = gen_lowpart (SImode, operands[1]);
4830   rtx high_src = gen_highpart (SImode, operands[1]);
4831   rtx dst = gen_reg_rtx (DImode);
4832   rtx low_dst = gen_lowpart (SImode, dst);
4833   rtx high_dst = gen_highpart (SImode, dst);
4834   rtx tmp0 = gen_reg_rtx (SImode);
4835   rtx tmp1 = gen_reg_rtx (SImode);
4837   emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4838   emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
4839   emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
4840   emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4841   emit_move_insn (operands[0], dst);
4842   DONE;
4845 (define_insn_and_split "ashldi3_k"
4846   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4847         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4848                    (const_int 1)))
4849    (clobber (reg:SI T_REG))]
4850   "TARGET_SH1"
4851   "#"
4852   "&& reload_completed"
4853   [(const_int 0)]
4855   rtx high = gen_highpart (SImode, operands[0]);
4856   rtx low = gen_lowpart (SImode, operands[0]);
4857   emit_insn (gen_shll (low, low));
4858   emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4859   DONE;
4862 (define_insn "ashldi3_media"
4863   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4864         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4865                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
4866   "TARGET_SHMEDIA"
4867   "@
4868         shlld   %1, %2, %0
4869         shlli   %1, %2, %0"
4870   [(set_attr "type" "arith_media")])
4872 (define_insn "*ashldisi3_media"
4873   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4874         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4875                    (match_operand:DI 2 "const_int_operand" "n")))]
4876   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4877   "shlli.l      %1, %2, %0"
4878   [(set_attr "type" "arith_media")
4879    (set_attr "highpart" "ignore")])
4881 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4882 ;; SImode arithmetic shift right
4884 ;; We can't do HImode right shifts correctly unless we start out with an
4885 ;; explicit zero / sign extension; doing that would result in worse overall
4886 ;; code, so just let the machine independent code widen the mode.
4887 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4889 (define_expand "ashrsi3"
4890   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4891                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4892                                 (match_operand:SI 2 "nonmemory_operand" "")))
4893               (clobber (reg:SI T_REG))])]
4894   ""
4896   if (TARGET_SHMEDIA)
4897     {
4898       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4899       DONE;
4900     }
4901   if (expand_ashiftrt (operands))
4902     DONE;
4903   else
4904     FAIL;
4907 (define_insn "shar"
4908   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4909         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4910                      (const_int 1)))
4911    (set (reg:SI T_REG)
4912         (and:SI (match_dup 1) (const_int 1)))]
4913   "TARGET_SH1"
4914   "shar %0"
4915   [(set_attr "type" "arith")])
4917 (define_insn "ashrsi3_k"
4918   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4919         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4920                      (match_operand:SI 2 "const_int_operand" "M")))
4921    (clobber (reg:SI T_REG))]
4922   "TARGET_SH1 && INTVAL (operands[2]) == 1"
4923   "shar %0"
4924   [(set_attr "type" "arith")])
4926 (define_insn_and_split "ashrsi2_16"
4927   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4928         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4929                      (const_int 16)))]
4930   "TARGET_SH1"
4931   "#"
4932   "&& 1"
4933   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4934    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4936   operands[2] = gen_lowpart (HImode, operands[0]);
4939 (define_insn_and_split "ashrsi2_31"
4940   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4941         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4942                      (const_int 31)))
4943    (clobber (reg:SI T_REG))]
4944   "TARGET_SH1"
4945   "#"
4946   "&& 1"
4947   [(const_int 0)]
4949   emit_insn (gen_shll (operands[0], operands[1]));
4950   emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
4951   DONE;
4954 (define_insn "ashrsi3_d"
4955   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4956         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4957                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4958   "TARGET_DYNSHIFT"
4959   "shad %2,%0"
4960   [(set_attr "type" "dyn_shift")])
4962 (define_insn "ashrsi3_n"
4963   [(set (reg:SI R4_REG)
4964         (ashiftrt:SI (reg:SI R4_REG)
4965                      (match_operand:SI 0 "const_int_operand" "i")))
4966    (clobber (reg:SI T_REG))
4967    (clobber (reg:SI PR_REG))
4968    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
4969   "TARGET_SH1"
4970   "jsr  @%1%#"
4971   [(set_attr "type" "sfunc")
4972    (set_attr "needs_delay_slot" "yes")])
4974 (define_insn "ashrsi3_media"
4975   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4976         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4977                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
4978   "TARGET_SHMEDIA"
4979   "@
4980         shard.l %1, %2, %0
4981         shari.l %1, %2, %0"
4982   [(set_attr "type" "arith_media")
4983    (set_attr "highpart" "ignore")])
4985 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4986 ;; DImode arithmetic shift right
4988 (define_expand "ashrdi3"
4989   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4990                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4991                                 (match_operand:DI 2 "immediate_operand" "")))
4992               (clobber (reg:SI T_REG))])]
4993   ""
4995   if (TARGET_SHMEDIA)
4996     {
4997       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4998       DONE;
4999     }
5000   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5001     FAIL;
5004 (define_insn_and_split "ashrdi3_k"
5005   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5006         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5007                      (const_int 1)))
5008    (clobber (reg:SI T_REG))]
5009   "TARGET_SH1"
5010   "#"
5011   "&& reload_completed"
5012   [(const_int 0)]
5014   rtx high = gen_highpart (SImode, operands[0]);
5015   rtx low = gen_lowpart (SImode, operands[0]);
5016   emit_insn (gen_shar (high, high));
5017   emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5018   DONE;
5021 (define_insn "ashrdi3_media"
5022   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5023         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5024                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
5025   "TARGET_SHMEDIA
5026    && (arith_reg_dest (operands[0], DImode)
5027        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
5028   "@
5029         shard   %1, %2, %0
5030         shari   %1, %2, %0"
5031   [(set_attr "type" "arith_media")])
5033 (define_insn "*ashrdisi3_media"
5034   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5035         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5036                      (match_operand:DI 2 "const_int_operand" "n")))]
5037   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5038   "shari.l      %1, %2, %0"
5039   [(set_attr "type" "arith_media")
5040    (set_attr "highpart" "ignore")])
5042 (define_insn "ashrdisi3_media_high"
5043   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5044         (truncate:SI
5045            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5046                         (match_operand:DI 2 "const_int_operand" "n"))))]
5047   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
5048   "shari        %1, %2, %0"
5049   [(set_attr "type" "arith_media")])
5051 (define_insn "ashrdisi3_media_opaque"
5052   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5053         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
5054                     (match_operand:DI 2 "const_int_operand" "n")]
5055          UNSPEC_ASHIFTRT))]
5056   "TARGET_SHMEDIA"
5057   "shari        %1, %2, %0"
5058   [(set_attr "type" "arith_media")])
5060 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5061 ;; SImode logical shift right
5063 (define_expand "lshrsi3"
5064   [(set (match_operand:SI 0 "arith_reg_dest" "")
5065         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5066                      (match_operand:SI 2 "shift_count_operand" "")))]
5067   ""
5069   if (TARGET_SHMEDIA)
5070     {
5071       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5072       DONE;
5073     }
5075   /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5076      here, otherwise the pattern will never match due to the shift amount reg
5077      negation.  */
5078   if (TARGET_DYNSHIFT
5079       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5080     {
5081       rtx neg_count = force_reg (SImode,
5082                                  gen_int_mode (- INTVAL (operands[2]), SImode));
5083       emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5084       DONE;
5085     }
5087   if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5088     {
5089       rtx neg_count = gen_reg_rtx (SImode);
5090       emit_insn (gen_negsi2 (neg_count, operands[2]));
5091       emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5092       DONE;
5093     }
5095   /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5096      expanded here.  */
5097   if (CONST_INT_P (operands[2])
5098       && sh_lshrsi_clobbers_t_reg_p (operands[2])
5099       && ! sh_dynamicalize_shift_p (operands[2]))
5100     {
5101       emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5102                  operands[2]));
5103       DONE;
5104     }
5106   /* Expand a library call for the dynamic shift.  */
5107   if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5108     {
5109       emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5110       rtx funcaddr = gen_reg_rtx (Pmode);
5111       function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
5112       emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
5113       DONE;
5114     }
5117 (define_insn "lshrsi3_k"
5118   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5119         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5120                      (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5121   "TARGET_SH1"
5122   "shlr%O2      %0"
5123   [(set_attr "type" "arith")])
5125 (define_insn_and_split "lshrsi3_d"
5126   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5127         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5128                      (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5129   "TARGET_DYNSHIFT"
5130   "shld %2,%0"
5131   "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5132    && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5133   [(const_int 0)]
5135   if (satisfies_constraint_P27 (operands[2]))
5136     {
5137       /* This will not be done for a shift amount of 1, because it would
5138          clobber the T_REG.  */
5139       emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5140       DONE;
5141     }
5142   else if (! satisfies_constraint_P27 (operands[2]))
5143     {
5144       /* This must happen before reload, otherwise the constant will be moved
5145          into a register due to the "r" constraint, after which this split
5146          cannot be done anymore.
5147          Unfortunately the move insn will not always be eliminated.
5148          Also, here we must not create a shift sequence that clobbers the
5149          T_REG.  */
5150       emit_move_insn (operands[0], operands[1]);
5151       gen_shifty_op (LSHIFTRT, operands);
5152       DONE;
5153     }
5155   FAIL;
5157   [(set_attr "type" "dyn_shift")])
5159 ;; If dynamic shifts are not available use a library function.
5160 ;; By specifying the pattern we reduce the number of call clobbered regs.
5161 ;; In order to make combine understand the truncation of the shift amount
5162 ;; operand we have to allow it to use pseudo regs for the shift operands.
5163 (define_insn "lshrsi3_d_call"
5164   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5165         (lshiftrt:SI (reg:SI R4_REG)
5166                      (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5167                              (const_int 31))))
5168    (use (match_operand:SI 2 "arith_reg_operand" "r"))
5169    (clobber (reg:SI T_REG))
5170    (clobber (reg:SI PR_REG))]
5171   "TARGET_SH1 && !TARGET_DYNSHIFT"
5172   "jsr  @%2%#"
5173   [(set_attr "type" "sfunc")
5174    (set_attr "needs_delay_slot" "yes")])
5176 (define_insn_and_split "lshrsi3_n"
5177   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5178         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5179                      (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5180   "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5181   "#"
5182   "&& (reload_completed
5183        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5184   [(const_int 0)]
5186   if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5187     {
5188       /* If this pattern was picked and dynamic shifts are supported, switch
5189          to dynamic shift pattern before reload.  */
5190       operands[2] = force_reg (SImode,
5191                                gen_int_mode (- INTVAL (operands[2]), SImode));
5192       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5193     }
5194   else
5195     gen_shifty_op (LSHIFTRT, operands);
5197   DONE;
5200 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5201 ;; the shlr pattern.
5202 (define_insn_and_split "lshrsi3_n_clobbers_t"
5203   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5204         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5205                      (match_operand:SI 2 "not_p27_rshift_count_operand")))
5206    (clobber (reg:SI T_REG))]
5207   "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5208   "#"
5209   "&& (reload_completed || INTVAL (operands[2]) == 31
5210        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5211   [(const_int 0)]
5213   if (INTVAL (operands[2]) == 31)
5214     {
5215       emit_insn (gen_shll (operands[0], operands[1]));
5216       emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5217     }
5218   else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5219     {
5220       /* If this pattern was picked and dynamic shifts are supported, switch
5221          to dynamic shift pattern before reload.  */
5222       operands[2] = force_reg (SImode,
5223                                gen_int_mode (- INTVAL (operands[2]), SImode));
5224       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5225     }
5226   else
5227     gen_shifty_op (LSHIFTRT, operands);
5229   DONE;
5232 (define_insn "shlr"
5233   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5234         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5235                      (const_int 1)))
5236    (set (reg:SI T_REG)
5237         (and:SI (match_dup 1) (const_int 1)))]
5238   "TARGET_SH1"
5239   "shlr %0"
5240   [(set_attr "type" "arith")])
5242 (define_insn "lshrsi3_media"
5243   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5244         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5245                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
5246   "TARGET_SHMEDIA"
5247   "@
5248         shlrd.l %1, %2, %0
5249         shlri.l %1, %2, %0"
5250   [(set_attr "type" "arith_media")
5251    (set_attr "highpart" "ignore")])
5253 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5254 ;; DImode logical shift right
5256 (define_expand "lshrdi3"
5257   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5258                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5259                                (match_operand:DI 2 "immediate_operand" "")))
5260              (clobber (reg:SI T_REG))])]
5261   ""
5263   if (TARGET_SHMEDIA)
5264     {
5265       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5266       DONE;
5267     }
5268   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5269     FAIL;
5272 (define_insn_and_split "lshrdi3_k"
5273   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5274         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5275                      (const_int 1)))
5276    (clobber (reg:SI T_REG))]
5277   "TARGET_SH1"
5278   "#"
5279   "&& reload_completed"
5280   [(const_int 0)]
5282   rtx high = gen_highpart (SImode, operands[0]);
5283   rtx low = gen_lowpart (SImode, operands[0]);
5284   emit_insn (gen_shlr (high, high));
5285   emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5286   DONE;
5289 (define_insn "lshrdi3_media"
5290   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5291         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5292                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
5293   "TARGET_SHMEDIA
5294    && (arith_reg_dest (operands[0], DImode)
5295        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5296   "@
5297         shlrd   %1, %2, %0
5298         shlri   %1, %2, %0"
5299   [(set_attr "type" "arith_media")])
5301 (define_insn "*lshrdisi3_media"
5302   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5303         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5304                      (match_operand:DI 2 "const_int_operand" "n")))]
5305   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5306   "shlri.l      %1, %2, %0"
5307   [(set_attr "type" "arith_media")
5308    (set_attr "highpart" "ignore")])
5310 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5311 ;; Combined left/right shifts
5313 (define_split
5314   [(set (match_operand:SI 0 "register_operand" "")
5315         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5316                            (match_operand:SI 2 "const_int_operand" ""))
5317                 (match_operand:SI 3 "const_int_operand" "")))]
5318   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5319   [(use (reg:SI R0_REG))]
5321   if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5322     FAIL;
5323   DONE;
5326 (define_split
5327   [(set (match_operand:SI 0 "register_operand" "")
5328         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5329                            (match_operand:SI 2 "const_int_operand" ""))
5330                 (match_operand:SI 3 "const_int_operand" "")))
5331    (clobber (reg:SI T_REG))]
5332   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5333   [(use (reg:SI R0_REG))]
5335   if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5336     FAIL;
5337   DONE;
5340 (define_insn ""
5341   [(set (match_operand:SI 0 "register_operand" "=r")
5342         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5343                            (match_operand:SI 2 "const_int_operand" "n"))
5344                 (match_operand:SI 3 "const_int_operand" "n")))
5345    (clobber (reg:SI T_REG))]
5346   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5347   "#"
5348   [(set (attr "length")
5349         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5350                (const_string "4")
5351                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5352                (const_string "6")
5353                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5354                (const_string "8")
5355                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5356                (const_string "10")
5357                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5358                (const_string "12")
5359                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5360                (const_string "14")
5361                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5362                (const_string "16")]
5363               (const_string "18")))
5364    (set_attr "type" "arith")])
5366 (define_insn ""
5367   [(set (match_operand:SI 0 "register_operand" "=z")
5368         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5369                            (match_operand:SI 2 "const_int_operand" "n"))
5370                 (match_operand:SI 3 "const_int_operand" "n")))
5371    (clobber (reg:SI T_REG))]
5372   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5373   "#"
5374   [(set (attr "length")
5375         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5376                (const_string "4")
5377                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5378                (const_string "6")
5379                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5380                (const_string "8")]
5381               (const_string "10")))
5382    (set_attr "type" "arith")])
5384 ;; shift left / and combination with a scratch register: The combine pass
5385 ;; does not accept the individual instructions, even though they are
5386 ;; cheap.  But it needs a precise description so that it is usable after
5387 ;; reload.
5388 (define_insn "and_shl_scratch"
5389   [(set (match_operand:SI 0 "register_operand" "=r,&r")
5390         (lshiftrt:SI
5391          (ashift:SI
5392           (and:SI
5393            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5394                         (match_operand:SI 2 "const_int_operand" "N,n"))
5395            (match_operand:SI 3 "" "0,r"))
5396           (match_operand:SI 4 "const_int_operand" "n,n"))
5397          (match_operand:SI 5 "const_int_operand" "n,n")))
5398    (clobber (reg:SI T_REG))]
5399   "TARGET_SH1"
5400   "#"
5401   [(set (attr "length")
5402         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5403                (const_string "4")
5404                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5405                (const_string "6")
5406                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5407                (const_string "8")
5408                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5409                (const_string "10")]
5410               (const_string "12")))
5411    (set_attr "type" "arith")])
5413 (define_split
5414   [(set (match_operand:SI 0 "register_operand" "")
5415         (lshiftrt:SI
5416          (ashift:SI
5417           (and:SI
5418            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5419                         (match_operand:SI 2 "const_int_operand" ""))
5420            (match_operand:SI 3 "register_operand" ""))
5421           (match_operand:SI 4 "const_int_operand" ""))
5422          (match_operand:SI 5 "const_int_operand" "")))
5423    (clobber (reg:SI T_REG))]
5424   "TARGET_SH1"
5425   [(use (reg:SI R0_REG))]
5427   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5429   if (INTVAL (operands[2]))
5430     {
5431       gen_shifty_op (LSHIFTRT, operands);
5432     }
5433   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5434   operands[2] = operands[4];
5435   gen_shifty_op (ASHIFT, operands);
5436   if (INTVAL (operands[5]))
5437     {
5438       operands[2] = operands[5];
5439       gen_shifty_op (LSHIFTRT, operands);
5440     }
5441   DONE;
5444 ;; signed left/right shift combination.
5445 (define_split
5446   [(set (match_operand:SI 0 "register_operand" "")
5447         (sign_extract:SI
5448          (ashift:SI (match_operand:SI 1 "register_operand" "")
5449                     (match_operand:SI 2 "const_int_operand" ""))
5450          (match_operand:SI 3 "const_int_operand" "")
5451          (const_int 0)))
5452    (clobber (reg:SI T_REG))]
5453   "TARGET_SH1"
5454   [(use (reg:SI R0_REG))]
5456   if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5457     FAIL;
5458   DONE;
5461 (define_insn "shl_sext_ext"
5462   [(set (match_operand:SI 0 "register_operand" "=r")
5463         (sign_extract:SI
5464          (ashift:SI (match_operand:SI 1 "register_operand" "0")
5465                     (match_operand:SI 2 "const_int_operand" "n"))
5466          (match_operand:SI 3 "const_int_operand" "n")
5467          (const_int 0)))
5468    (clobber (reg:SI T_REG))]
5469   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5470   "#"
5471   [(set (attr "length")
5472         (cond [(match_test "shl_sext_length (insn)")
5473                (const_string "2")
5474                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5475                (const_string "4")
5476                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5477                (const_string "6")
5478                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5479                (const_string "8")
5480                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5481                (const_string "10")
5482                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5483                (const_string "12")
5484                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5485                (const_string "14")
5486                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5487                (const_string "16")]
5488               (const_string "18")))
5489     (set_attr "type" "arith")])
5491 (define_insn "shl_sext_sub"
5492   [(set (match_operand:SI 0 "register_operand" "=z")
5493         (sign_extract:SI
5494          (ashift:SI (match_operand:SI 1 "register_operand" "0")
5495                     (match_operand:SI 2 "const_int_operand" "n"))
5496          (match_operand:SI 3 "const_int_operand" "n")
5497          (const_int 0)))
5498    (clobber (reg:SI T_REG))]
5499   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5500   "#"
5501   [(set (attr "length")
5502         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5503                (const_string "6")
5504                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5505                (const_string "8")
5506                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5507                (const_string "10")
5508                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5509                (const_string "12")]
5510               (const_string "14")))
5511     (set_attr "type" "arith")])
5513 ;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5514 ;; shifts by 16, and allow the xtrct instruction to be generated from C
5515 ;; source.
5516 (define_insn "xtrct_left"
5517   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5518         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5519                            (const_int 16))
5520                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5521                              (const_int 16))))]
5522   "TARGET_SH1"
5523   "xtrct        %1,%0"
5524   [(set_attr "type" "arith")])
5526 (define_insn "xtrct_right"
5527   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5528         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5529                              (const_int 16))
5530                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5531                            (const_int 16))))]
5532   "TARGET_SH1"
5533   "xtrct        %2,%0"
5534   [(set_attr "type" "arith")])
5536 ;; -------------------------------------------------------------------------
5537 ;; Unary arithmetic
5538 ;; -------------------------------------------------------------------------
5540 (define_insn "negc"
5541   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5542         (neg:SI (plus:SI (reg:SI T_REG)
5543                          (match_operand:SI 1 "arith_reg_operand" "r"))))
5544    (set (reg:SI T_REG)
5545         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5546                (const_int 0)))]
5547   "TARGET_SH1"
5548   "negc %1,%0"
5549   [(set_attr "type" "arith")])
5551 ;; A simplified version of the negc insn, where the exact value of the
5552 ;; T bit doesn't matter.  This is easier for combine to pick up.
5553 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5554 ;; extra patterns for this case.
5555 (define_insn "*negc"
5556   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5557         (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5558                   (match_operand:SI 2 "t_reg_operand" "")))
5559    (clobber (reg:SI T_REG))]
5560   "TARGET_SH1"
5561   "negc %1,%0"
5562   [(set_attr "type" "arith")])
5564 (define_insn "*negdi_media"
5565   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5566         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5567   "TARGET_SHMEDIA"
5568   "sub  r63, %1, %0"
5569   [(set_attr "type" "arith_media")])
5571 ;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
5572 ;; can be combined.
5573 (define_expand "negdi2"
5574   [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5575                    (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5576               (clobber (reg:SI T_REG))])]
5577   "TARGET_SH1")
5579 (define_insn_and_split "*negdi2"
5580   [(set (match_operand:DI 0 "arith_reg_dest")
5581         (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5582    (clobber (reg:SI T_REG))]
5583   "TARGET_SH1"
5584   "#"
5585   "&& can_create_pseudo_p ()"
5586   [(const_int 0)]
5588   emit_insn (gen_clrt ());
5589   emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5590                        gen_lowpart (SImode, operands[1])));
5591   emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5592                        gen_highpart (SImode, operands[1])));
5593   DONE;
5596 (define_insn "negsi2"
5597   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5598         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5599   "TARGET_SH1"
5600   "neg  %1,%0"
5601   [(set_attr "type" "arith")])
5603 (define_insn_and_split "one_cmplsi2"
5604   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5605         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5606   "TARGET_SH1"
5607   "not  %1,%0"
5608   "&& can_create_pseudo_p ()"
5609   [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5610    (set (match_dup 0) (reg:SI T_REG))]
5612 /* PR 54685
5613    If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5614    sequence:
5616      (set (reg0) (not:SI (reg0) (reg1)))
5617      (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5618                 (clobber (reg:SI T_REG))])
5620    ... match and combine the sequence manually in the split pass after the
5621    combine pass.  Notice that combine does try the target pattern of this
5622    split, but if the pattern is added it interferes with other patterns, in
5623    particular with the div0s comparisons.
5624    This could also be done with a peephole but doing it here before register
5625    allocation can save one temporary.
5626    When we're here, the not:SI pattern obviously has been matched already
5627    and we only have to see whether the following insn is the left shift.  */
5629   rtx i = next_nonnote_insn_bb (curr_insn);
5630   if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5631     FAIL;
5633   rtx p = PATTERN (i);
5634   if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5635     FAIL;
5637   rtx p0 = XVECEXP (p, 0, 0);
5638   rtx p1 = XVECEXP (p, 0, 1);
5640   if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
5641       GET_CODE (p0) == SET
5642       && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5643       && REG_P (XEXP (XEXP (p0, 1), 0))
5644       && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5645       && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5646       && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5648       /* (clobber (reg:SI T_REG))  */
5649       && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5650       && REGNO (XEXP (p1, 0)) == T_REG)
5651     {
5652       operands[0] = XEXP (p0, 0);
5653       set_insn_deleted (i);
5654     }
5655   else
5656     FAIL;
5658   [(set_attr "type" "arith")])
5660 (define_expand "one_cmpldi2"
5661   [(set (match_operand:DI 0 "arith_reg_dest" "")
5662         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5663                 (const_int -1)))]
5664   "TARGET_SHMEDIA" "")
5666 (define_expand "abs<mode>2"
5667   [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5668                    (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5669               (clobber (reg:SI T_REG))])]
5670   "TARGET_SH1")
5672 (define_insn_and_split "*abs<mode>2"
5673   [(set (match_operand:SIDI 0 "arith_reg_dest")
5674         (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5675    (clobber (reg:SI T_REG))]
5676   "TARGET_SH1"
5677   "#"
5678   "&& can_create_pseudo_p ()"
5679   [(const_int 0)]
5681   if (<MODE>mode == SImode)
5682     emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5683   else
5684     {
5685       rtx high_src = gen_highpart (SImode, operands[1]);
5686       emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5687     }
5689   emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5690                                  const1_rtx));
5691   DONE;
5694 (define_insn_and_split "*negabs<mode>2"
5695   [(set (match_operand:SIDI 0 "arith_reg_dest")
5696         (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5697    (clobber (reg:SI T_REG))]
5698   "TARGET_SH1"
5699   "#"
5700   "&& can_create_pseudo_p ()"
5701   [(const_int 0)]
5703   if (<MODE>mode == SImode)
5704     emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5705   else
5706     {
5707       rtx high_src = gen_highpart (SImode, operands[1]);
5708       emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5709     }
5711   emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5712                                  const0_rtx));
5713   DONE;
5716 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
5717 ;; This can be used as some kind of conditional execution, which is useful
5718 ;; for abs.
5719 ;; Actually the instruction scheduling should decide whether to use a
5720 ;; zero-offset branch or not for any generic case involving a single
5721 ;; instruction on SH4 202.
5722 (define_insn_and_split "negsi_cond"
5723   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5724         (if_then_else
5725           (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5726           (match_operand:SI 1 "arith_reg_operand" "0,0")
5727           (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5728   "TARGET_SH1 && TARGET_ZDCBRANCH"
5730   static const char* alt[] =
5731   {
5732        "bt      0f"     "\n"
5733     "   neg     %2,%0"  "\n"
5734     "0:",
5736        "bf      0f"     "\n"
5737     "   neg     %2,%0"  "\n"
5738     "0:"
5739   };
5740   return alt[which_alternative];
5742   "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5743   [(const_int 0)]
5745   rtx skip_neg_label = gen_label_rtx ();
5747   emit_move_insn (operands[0], operands[1]);
5749   emit_jump_insn (INTVAL (operands[3])
5750                   ? gen_branch_true (skip_neg_label)
5751                   : gen_branch_false (skip_neg_label));
5753   emit_label_after (skip_neg_label,
5754                     emit_insn (gen_negsi2 (operands[0], operands[1])));
5755   DONE;
5757   [(set_attr "type" "arith") ;; poor approximation
5758    (set_attr "length" "4")])
5760 (define_insn_and_split "negdi_cond"
5761   [(set (match_operand:DI 0 "arith_reg_dest")
5762         (if_then_else
5763           (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5764           (match_operand:DI 1 "arith_reg_operand")
5765           (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5766    (clobber (reg:SI T_REG))]
5767   "TARGET_SH1"
5768   "#"
5769   "&& can_create_pseudo_p ()"
5770   [(const_int 0)]
5772   rtx skip_neg_label = gen_label_rtx ();
5774   emit_move_insn (operands[0], operands[1]);
5776   emit_jump_insn (INTVAL (operands[3]) 
5777                   ? gen_branch_true (skip_neg_label)
5778                   : gen_branch_false (skip_neg_label));
5780   if (!INTVAL (operands[3]))
5781     emit_insn (gen_clrt ());
5783   emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5784                        gen_lowpart (SImode, operands[1])));
5785   emit_label_after (skip_neg_label,
5786                     emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5787                                          gen_highpart (SImode, operands[1]))));
5788   DONE;
5791 (define_expand "bswapsi2"
5792   [(set (match_operand:SI 0 "arith_reg_dest" "")
5793         (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5794   "TARGET_SH1"
5796   if (! can_create_pseudo_p ())
5797     FAIL;
5798   else
5799     {
5800       rtx tmp0 = gen_reg_rtx (SImode);
5801       rtx tmp1 = gen_reg_rtx (SImode);
5803       emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5804       emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5805       emit_insn (gen_swapbsi2 (operands[0], tmp1));
5806       DONE;
5807     }
5810 (define_insn "swapbsi2"
5811   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5812         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5813                         (const_int 4294901760))
5814                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5815                                 (const_int 65280))
5816                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5817                                 (const_int 255)))))]
5818   "TARGET_SH1"
5819   "swap.b       %1,%0"
5820   [(set_attr "type" "arith")])
5822 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5823 ;; partial byte swap expressions such as...
5824 ;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5825 ;; ...which are currently not handled by the tree optimizers.
5826 ;; The combine pass will not initially try to combine the full expression,
5827 ;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
5828 ;; pattern acts as an intermediate pattern that will eventually lead combine
5829 ;; to the swapbsi2 pattern above.
5830 ;; As a side effect this also improves code that does (x & 0xFF) << 8
5831 ;; or (x << 8) & 0xFF00.
5832 (define_insn_and_split "*swapbisi2_and_shl8"
5833   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5834         (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5835                                    (const_int 8))
5836                         (const_int 65280))
5837                 (match_operand:SI 2 "arith_reg_operand" "r")))]
5838   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5839   "#"
5840   "&& can_create_pseudo_p ()"
5841   [(const_int 0)]
5843   rtx tmp0 = gen_reg_rtx (SImode);
5844   rtx tmp1 = gen_reg_rtx (SImode);
5846   emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5847   emit_insn (gen_swapbsi2 (tmp1, tmp0));
5848   emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5849   DONE;
5852 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5853 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5854 (define_insn_and_split "*swapbhisi2"
5855   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5856         (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5857                                    (const_int 8))
5858                         (const_int 65280))
5859                 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5860   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5861   "#"
5862   "&& can_create_pseudo_p ()"
5863   [(const_int 0)]
5865   rtx tmp = gen_reg_rtx (SImode);
5867   emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5868   emit_insn (gen_swapbsi2 (operands[0], tmp));
5869   DONE;
5872 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
5873 ;;   swap.b  r4,r4
5874 ;;   mov     r4,r0
5876 ;; which can be simplified to...
5877 ;;   swap.b  r4,r0
5878 (define_peephole2
5879   [(set (match_operand:SI 0 "arith_reg_dest" "")
5880         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5881                         (const_int 4294901760))
5882                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5883                                 (const_int 65280))
5884                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5885                                 (const_int 255)))))
5886    (set (match_operand:SI 2 "arith_reg_dest" "")
5887         (match_dup 0))]
5888   "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5889   [(set (match_dup 2)
5890         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5891                         (const_int 4294901760))
5892                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5893                                 (const_int 65280))
5894                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5895                                 (const_int 255)))))])
5897 ;; -------------------------------------------------------------------------
5898 ;; Zero extension instructions
5899 ;; -------------------------------------------------------------------------
5901 (define_insn "zero_extendsidi2"
5902   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5903         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5904   "TARGET_SHMEDIA"
5905   "addz.l       %1, r63, %0"
5906   [(set_attr "type" "arith_media")
5907    (set_attr "highpart" "extend")])
5909 (define_insn "zero_extendhidi2"
5910   [(set (match_operand:DI 0 "register_operand" "=r,r")
5911         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5912   "TARGET_SHMEDIA"
5913   "@
5914         #
5915         ld%M1.uw        %m1, %0"
5916   [(set_attr "type" "*,load_media")
5917    (set (attr "highpart")
5918         (cond [(match_test "sh_contains_memref_p (insn)")
5919                (const_string "user")]
5920               (const_string "ignore")))])
5922 (define_split
5923   [(set (match_operand:DI 0 "register_operand" "")
5924         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5925   "TARGET_SHMEDIA && reload_completed"
5926   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5927    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
5929   if (GET_CODE (operands[1]) == TRUNCATE)
5930     operands[1] = XEXP (operands[1], 0);
5933 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
5934 ;; reload the entire truncate expression.
5935 (define_insn_and_split "*loaddi_trunc"
5936   [(set (match_operand 0 "any_register_operand" "=r")
5937         (truncate (match_operand:DI 1 "memory_operand" "m")))]
5938   "TARGET_SHMEDIA && reload_completed"
5939   "#"
5940   "TARGET_SHMEDIA && reload_completed"
5941   [(set (match_dup 0) (match_dup 1))]
5943   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5946 (define_insn "zero_extendqidi2"
5947   [(set (match_operand:DI 0 "register_operand" "=r,r")
5948         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5949   "TARGET_SHMEDIA"
5950   "@
5951         andi    %1, 255, %0
5952         ld%M1.ub        %m1, %0"
5953   [(set_attr "type" "arith_media,load_media")
5954    (set (attr "highpart")
5955         (cond [(match_test "sh_contains_memref_p (insn)")
5956                (const_string "user")]
5957               (const_string "ignore")))])
5959 (define_expand "zero_extend<mode>si2"
5960   [(set (match_operand:SI 0 "arith_reg_dest")
5961         (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
5963 (define_insn_and_split "*zero_extend<mode>si2_compact"
5964   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5965         (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5966   "TARGET_SH1"
5967   "extu.<bw>    %1,%0"
5968   "&& can_create_pseudo_p ()"
5969   [(set (match_dup 0) (match_dup 2))]
5971   /* Sometimes combine fails to combine a T bit or negated T bit store to a
5972      reg with a following zero extension.  In the split pass after combine,
5973      try to figure out how the extended reg was set.  If it originated from
5974      the T bit we can replace the zero extension with a reg move, which will
5975      be eliminated.  Notice that this also helps the *cbranch_t splitter when
5976      it tries to post-combine tests and conditional branches, as it does not
5977      check for zero extensions.  */
5978   operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5979   if (operands[2] == NULL_RTX)
5980     FAIL;
5982   [(set_attr "type" "arith")])
5984 (define_insn "*zero_extendhisi2_media"
5985   [(set (match_operand:SI 0 "register_operand" "=r,r")
5986         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5987   "TARGET_SHMEDIA"
5988   "@
5989         #
5990         ld%M1.uw        %m1, %0"
5991   [(set_attr "type" "arith_media,load_media")
5992    (set (attr "highpart")
5993         (cond [(match_test "sh_contains_memref_p (insn)")
5994                (const_string "user")]
5995               (const_string "ignore")))])
5997 (define_split
5998   [(set (match_operand:SI 0 "register_operand" "")
5999         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6000   "TARGET_SHMEDIA && reload_completed"
6001   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6002    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
6004   rtx op1 = operands[1];
6006   if (GET_CODE (op1) == TRUNCATE)
6007     op1 = XEXP (op1, 0);
6008   operands[2]
6009     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6010                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6013 (define_insn "*zero_extendqisi2_media"
6014   [(set (match_operand:SI 0 "register_operand" "=r,r")
6015         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6016   "TARGET_SHMEDIA"
6017   "@
6018         andi    %1, 255, %0
6019         ld%M1.ub        %m1, %0"
6020   [(set_attr "type" "arith_media,load_media")
6021    (set (attr "highpart")
6022         (cond [(match_test "sh_contains_memref_p (insn)")
6023                (const_string "user")]
6024               (const_string "ignore")))])
6026 (define_insn "zero_extendqihi2"
6027   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6028         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6029   "TARGET_SH1"
6030   "extu.b       %1,%0"
6031   [(set_attr "type" "arith")])
6033 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
6034 ;; They could also be used for simple memory addresses like @Rn by setting
6035 ;; the displacement value to zero.  However, doing so too early results in
6036 ;; missed opportunities for other optimizations such as post-inc or index
6037 ;; addressing loads.
6038 ;; Although the 'zero_extend_movu_operand' predicate does not allow simple
6039 ;; register addresses (an address without a displacement, index, post-inc),
6040 ;; zero-displacement addresses might be generated during reload, wich are
6041 ;; simplified to simple register addresses in turn.  Thus, we have to
6042 ;; provide the Sdd and Sra alternatives in the patterns.
6043 (define_insn "*zero_extend<mode>si2_disp_mem"
6044   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6045         (zero_extend:SI
6046           (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
6047   "TARGET_SH2A"
6048   "@
6049         movu.<bw>       %1,%0
6050         movu.<bw>       @(0,%t1),%0"
6051   [(set_attr "type" "load")
6052    (set_attr "length" "4")])
6054 ;; Convert the zero extending loads in sequences such as:
6055 ;;      movu.b  @(1,r5),r0      movu.w  @(2,r5),r0
6056 ;;      mov.b   r0,@(1,r4)      mov.b   r0,@(1,r4)
6058 ;; back to sign extending loads like:
6059 ;;      mov.b   @(1,r5),r0      mov.w   @(2,r5),r0
6060 ;;      mov.b   r0,@(1,r4)      mov.b   r0,@(1,r4)
6062 ;; if the extension type is irrelevant.  The sign extending mov.{b|w} insn
6063 ;; is only 2 bytes in size if the displacement is {K04|K05}.
6064 ;; If the displacement is greater it doesn't matter, so we convert anyways.
6065 (define_peephole2
6066   [(set (match_operand:SI 0 "arith_reg_dest" "")
6067         (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6068    (set (match_operand 2 "general_operand" "")
6069         (match_operand 3 "arith_reg_operand" ""))]
6070   "TARGET_SH2A
6071    && REGNO (operands[0]) == REGNO (operands[3])
6072    && peep2_reg_dead_p (2, operands[0])
6073    && GET_MODE_SIZE (GET_MODE (operands[2]))
6074       <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6075   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6076    (set (match_dup 2) (match_dup 3))])
6078 ;; Fold sequences such as
6079 ;;      mov.b   @r3,r7
6080 ;;      extu.b  r7,r7
6081 ;; into
6082 ;;      movu.b  @(0,r3),r7
6083 ;; This does not reduce the code size but the number of instructions is
6084 ;; halved, which results in faster code.
6085 (define_peephole2
6086   [(set (match_operand:SI 0 "arith_reg_dest" "")
6087         (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6088    (set (match_operand:SI 2 "arith_reg_dest" "")
6089         (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6090   "TARGET_SH2A
6091    && GET_MODE (operands[1]) == GET_MODE (operands[3])
6092    && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6093    && REGNO (operands[0]) == REGNO (operands[3])
6094    && (REGNO (operands[2]) == REGNO (operands[0])
6095        || peep2_reg_dead_p (2, operands[0]))"
6096   [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6098   operands[4]
6099     = replace_equiv_address (operands[1],
6100                              gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6101                                            const0_rtx));
6104 ;; -------------------------------------------------------------------------
6105 ;; Sign extension instructions
6106 ;; -------------------------------------------------------------------------
6108 ;; ??? This should be a define expand.
6109 ;; ??? Or perhaps it should be dropped?
6111 ;; convert_move generates good code for SH[1-4].
6112 (define_insn "extendsidi2"
6113   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6114         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6115   "TARGET_SHMEDIA"
6116   "@
6117         add.l   %1, r63, %0
6118         ld%M1.l %m1, %0
6119         fmov.sl %1, %0"
6120   [(set_attr "type" "arith_media,load_media,fpconv_media")
6121    (set (attr "highpart")
6122         (cond [(match_test "sh_contains_memref_p (insn)")
6123                (const_string "user")]
6124               (const_string "extend")))])
6126 (define_insn "extendhidi2"
6127   [(set (match_operand:DI 0 "register_operand" "=r,r")
6128         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6129   "TARGET_SHMEDIA"
6130   "@
6131         #
6132         ld%M1.w %m1, %0"
6133   [(set_attr "type" "*,load_media")
6134    (set (attr "highpart")
6135         (cond [(match_test "sh_contains_memref_p (insn)")
6136                (const_string "user")]
6137               (const_string "ignore")))])
6139 (define_split
6140   [(set (match_operand:DI 0 "register_operand" "")
6141         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6142   "TARGET_SHMEDIA && reload_completed"
6143   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6144    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6146   if (GET_CODE (operands[1]) == TRUNCATE)
6147     operands[1] = XEXP (operands[1], 0);
6150 (define_insn "extendqidi2"
6151   [(set (match_operand:DI 0 "register_operand" "=r,r")
6152         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6153   "TARGET_SHMEDIA"
6154   "@
6155         #
6156         ld%M1.b %m1, %0"
6157   [(set_attr "type" "*,load_media")
6158    (set (attr "highpart")
6159         (cond [(match_test "sh_contains_memref_p (insn)")
6160                (const_string "user")]
6161               (const_string "ignore")))])
6163 (define_split
6164   [(set (match_operand:DI 0 "register_operand" "")
6165         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6166   "TARGET_SHMEDIA && reload_completed"
6167   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6168    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6170   if (GET_CODE (operands[1]) == TRUNCATE)
6171     operands[1] = XEXP (operands[1], 0);
6174 (define_expand "extend<mode>si2"
6175   [(set (match_operand:SI 0 "arith_reg_dest")
6176         (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6178 (define_insn "*extendhisi2_media"
6179   [(set (match_operand:SI 0 "register_operand" "=r,r")
6180         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6181   "TARGET_SHMEDIA"
6182   "@
6183         #
6184         ld%M1.w %m1, %0"
6185   [(set_attr "type" "arith_media,load_media")
6186    (set (attr "highpart")
6187         (cond [(match_test "sh_contains_memref_p (insn)")
6188                (const_string "user")]
6189               (const_string "ignore")))])
6191 (define_split
6192   [(set (match_operand:SI 0 "register_operand" "")
6193         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6194   "TARGET_SHMEDIA && reload_completed"
6195   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6196    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6198   rtx op1 = operands[1];
6199   if (GET_CODE (op1) == TRUNCATE)
6200     op1 = XEXP (op1, 0);
6201   operands[2]
6202     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6203                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6206 (define_insn_and_split "*extend<mode>si2_compact_reg"
6207   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6208         (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6209   "TARGET_SH1"
6210   "exts.<bw>    %1,%0"
6211   "&& can_create_pseudo_p ()"
6212   [(set (match_dup 0) (match_dup 2))]
6214   /* Sometimes combine fails to combine a T bit or negated T bit store to a
6215      reg with a following sign extension.  In the split pass after combine,
6216      try to figure the extended reg was set.  If it originated from the T
6217      bit we can replace the sign extension with a reg move, which will be
6218      eliminated.  */
6219   operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6220   if (operands[2] == NULL_RTX)
6221     FAIL;
6223   [(set_attr "type" "arith")])
6225 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6226 ;; See movqi insns.
6227 (define_insn "*extend<mode>si2_compact_mem_disp"
6228   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6229         (sign_extend:SI
6230           (mem:QIHI
6231             (plus:SI
6232               (match_operand:SI 1 "arith_reg_operand" "%r,r")
6233               (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6234   "TARGET_SH1 && ! TARGET_SH2A
6235    && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6236   "@
6237         mov.<bw>        @(%O2,%1),%0
6238         mov.<bw>        @%1,%0"
6239   [(set_attr "type" "load")])
6241 (define_insn "*extend<mode>si2_compact_mem_disp"
6242   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6243         (sign_extend:SI
6244           (mem:QIHI
6245             (plus:SI
6246               (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6247               (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6248   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6249   "@
6250         mov.<bw>        @(%O2,%1),%0
6251         mov.<bw>        @%1,%0
6252         mov.<bw>        @(%O2,%1),%0"
6253   [(set_attr "type" "load")
6254    (set_attr "length" "2,2,4")])
6256 ;; The *_snd patterns will take care of other QImode/HImode addressing
6257 ;; modes than displacement addressing.  They must be defined _after_ the
6258 ;; displacement addressing patterns.  Otherwise the displacement addressing
6259 ;; patterns will not be picked.
6260 (define_insn "*extend<mode>si2_compact_snd"
6261   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6262         (sign_extend:SI
6263           (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6264   "TARGET_SH1"
6265   "mov.<bw>     %1,%0"
6266   [(set_attr "type" "load")])
6268 (define_insn "*extendqisi2_media"
6269   [(set (match_operand:SI 0 "register_operand" "=r,r")
6270         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6271   "TARGET_SHMEDIA"
6272   "@
6273         #
6274         ld%M1.b %m1, %0"
6275   [(set_attr "type" "arith_media,load_media")
6276    (set (attr "highpart")
6277         (cond [(match_test "sh_contains_memref_p (insn)")
6278                (const_string "user")]
6279               (const_string "ignore")))])
6281 (define_split
6282   [(set (match_operand:SI 0 "register_operand" "")
6283         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6284   "TARGET_SHMEDIA && reload_completed"
6285   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6286    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6288   rtx op1 = operands[1];
6289   if (GET_CODE (op1) == TRUNCATE)
6290     op1 = XEXP (op1, 0);
6291   operands[2]
6292     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6293                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6296 (define_expand "extendqihi2"
6297   [(set (match_operand:HI 0 "arith_reg_dest" "")
6298         (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
6299   ""
6300   "")
6302 (define_insn "*extendqihi2_compact_reg"
6303   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6304         (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6305   "TARGET_SH1"
6306   "exts.b       %1,%0"
6307   [(set_attr "type" "arith")])
6309 ;; It would seem useful to combine the truncXi patterns into the movXi
6310 ;; patterns, but unary operators are ignored when matching constraints,
6311 ;; so we need separate patterns.
6312 (define_insn "truncdisi2"
6313   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6314         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6315   "TARGET_SHMEDIA"
6316   "@
6317         add.l   %1, r63, %0
6318         st%M0.l %m0, %1
6319         fst%M0.s        %m0, %T1
6320         fmov.ls %1, %0
6321         fmov.sl %T1, %0
6322         fmov.s  %T1, %0"
6323   [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6324                      fpconv_media,fmove_media")
6325    (set (attr "highpart")
6326         (cond [(match_test "sh_contains_memref_p (insn)")
6327                (const_string "user")]
6328               (const_string "extend")))])
6330 (define_insn "truncdihi2"
6331   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6332         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6333   "TARGET_SHMEDIA"
6335   static const char* alt[] =
6336   {
6337        "shlli   %1,48,%0"       "\n"
6338     "   shlri   %0,48,%0",
6340        "st%M0.w %m0, %1"
6341   };
6342   return alt[which_alternative];
6344   [(set_attr "type"   "arith_media,store_media")
6345    (set_attr "length" "8,4")
6346    (set (attr "highpart")
6347         (cond [(match_test "sh_contains_memref_p (insn)")
6348                (const_string "user")]
6349               (const_string "extend")))])
6351 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6352 ; Because we use zero extension, we can't provide signed QImode compares
6353 ; using a simple compare or conditional branch insn.
6354 (define_insn "truncdiqi2"
6355   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6356         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6357   "TARGET_SHMEDIA"
6358   "@
6359         andi    %1, 255, %0
6360         st%M0.b %m0, %1"
6361   [(set_attr "type"   "arith_media,store")
6362    (set (attr "highpart")
6363         (cond [(match_test "sh_contains_memref_p (insn)")
6364                (const_string "user")]
6365               (const_string "extend")))])
6367 ;; -------------------------------------------------------------------------
6368 ;; Move instructions
6369 ;; -------------------------------------------------------------------------
6371 ;; define push and pop so it is easy for sh.c
6372 ;; We can't use push and pop on SHcompact because the stack must always
6373 ;; be 8-byte aligned.
6374 (define_expand "push"
6375   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6376         (match_operand:SI 0 "register_operand" "r,l,x"))]
6377   "TARGET_SH1 && ! TARGET_SH5"
6378   "")
6380 (define_expand "pop"
6381   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6382         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6383   "TARGET_SH1 && ! TARGET_SH5"
6384   "")
6386 (define_expand "push_e"
6387   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6388                    (match_operand:SF 0 "" ""))
6389               (use (reg:PSI FPSCR_REG))
6390               (clobber (scratch:SI))])]
6391   "TARGET_SH1 && ! TARGET_SH5"
6392   "")
6394 (define_insn "push_fpul"
6395   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6396   "TARGET_SH2E && ! TARGET_SH5"
6397   "sts.l        fpul,@-r15"
6398   [(set_attr "type" "fstore")
6399    (set_attr "late_fp_use" "yes")
6400    (set_attr "hit_stack" "yes")])
6402 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6403 ;; so use that.
6404 (define_expand "push_4"
6405   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6406                    (match_operand:DF 0 "" ""))
6407               (use (reg:PSI FPSCR_REG))
6408               (clobber (scratch:SI))])]
6409   "TARGET_SH1 && ! TARGET_SH5"
6410   "")
6412 (define_expand "pop_e"
6413   [(parallel [(set (match_operand:SF 0 "" "")
6414               (mem:SF (post_inc:SI (reg:SI SP_REG))))
6415               (use (reg:PSI FPSCR_REG))
6416               (clobber (scratch:SI))])]
6417   "TARGET_SH1 && ! TARGET_SH5"
6418   "")
6420 (define_insn "pop_fpul"
6421   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6422   "TARGET_SH2E && ! TARGET_SH5"
6423   "lds.l        @r15+,fpul"
6424   [(set_attr "type" "load")
6425    (set_attr "hit_stack" "yes")])
6427 (define_expand "pop_4"
6428   [(parallel [(set (match_operand:DF 0 "" "")
6429                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
6430               (use (reg:PSI FPSCR_REG))
6431               (clobber (scratch:SI))])]
6432   "TARGET_SH1 && ! TARGET_SH5"
6433   "")
6435 (define_expand "push_fpscr"
6436   [(const_int 0)]
6437   "TARGET_SH2E"
6439   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
6440                                                  gen_rtx_PRE_DEC (Pmode,
6441                                                           stack_pointer_rtx)),
6442                                         get_fpscr_rtx ()));
6443   add_reg_note (insn, REG_INC, stack_pointer_rtx);
6444   DONE;
6447 (define_expand "pop_fpscr"
6448   [(const_int 0)]
6449   "TARGET_SH2E"
6451   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
6452                                         gen_frame_mem (PSImode,
6453                                                  gen_rtx_POST_INC (Pmode,
6454                                                           stack_pointer_rtx))));
6455   add_reg_note (insn, REG_INC, stack_pointer_rtx);
6456   DONE;
6459 ;; The clrt and sett patterns can happen as the result of optimization and
6460 ;; insn expansion.
6461 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6462 ;; In this case they might not disappear completely, because the T reg is
6463 ;; a fixed hard reg.
6464 ;; When DImode operations that use the T reg as carry/borrow are split into
6465 ;; individual SImode operations, the T reg is usually cleared before the
6466 ;; first SImode insn.
6467 (define_insn "clrt"
6468   [(set (reg:SI T_REG) (const_int 0))]
6469   "TARGET_SH1"
6470   "clrt"
6471   [(set_attr "type" "mt_group")])
6473 (define_insn "sett"
6474   [(set (reg:SI T_REG) (const_int 1))]
6475   "TARGET_SH1"
6476   "sett"
6477   [(set_attr "type" "mt_group")])
6479 ;; Use the combine pass to transform sequences such as
6480 ;;      mov     r5,r0
6481 ;;      add     #1,r0
6482 ;;      shll2   r0
6483 ;;      mov.l   @(r0,r4),r0
6484 ;; into
6485 ;;      shll2   r5
6486 ;;      add     r4,r5
6487 ;;      mov.l   @(4,r5),r0
6489 ;; See also PR 39423.
6490 ;; Notice that these patterns have a T_REG clobber, because the shift
6491 ;; sequence that will be split out might clobber the T_REG.  Ideally, the
6492 ;; clobber would be added conditionally, depending on the result of
6493 ;; sh_ashlsi_clobbers_t_reg_p.  When splitting out the shifts we must go
6494 ;; through the ashlsi3 expander in order to get the right shift insn --
6495 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6496 ;; FIXME: Combine never tries this kind of patterns for DImode.
6497 (define_insn_and_split "*movsi_index_disp_load"
6498   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6499         (match_operand:SI 1 "mem_index_disp_operand" "m"))
6500    (clobber (reg:SI T_REG))]
6501   "TARGET_SH1"
6502   "#"
6503   "&& can_create_pseudo_p ()"
6504   [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6505    (set (match_dup 0) (match_dup 7))]
6507   rtx mem = operands[1];
6508   rtx plus0_rtx = XEXP (mem, 0);
6509   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6510   rtx mult_rtx = XEXP (plus1_rtx, 0);
6512   operands[1] = XEXP (mult_rtx, 0);
6513   operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6514   operands[3] = XEXP (plus1_rtx, 1);
6515   operands[4] = XEXP (plus0_rtx, 1);
6516   operands[5] = gen_reg_rtx (SImode);
6517   operands[6] = gen_reg_rtx (SImode);
6518   operands[7] =
6519     replace_equiv_address (mem,
6520                            gen_rtx_PLUS (SImode, operands[6], operands[4]));
6522   emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6525 (define_insn_and_split "*movhi_index_disp_load"
6526   [(set (match_operand:SI 0 "arith_reg_dest")
6527         (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6528    (clobber (reg:SI T_REG))]
6529   "TARGET_SH1"
6530   "#"
6531   "&& can_create_pseudo_p ()"
6532   [(const_int 0)]
6534   rtx mem = operands[1];
6535   rtx plus0_rtx = XEXP (mem, 0);
6536   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6537   rtx mult_rtx = XEXP (plus1_rtx, 0);
6539   rtx op_1 = XEXP (mult_rtx, 0);
6540   rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6541   rtx op_3 = XEXP (plus1_rtx, 1);
6542   rtx op_4 = XEXP (plus0_rtx, 1);
6543   rtx op_5 = gen_reg_rtx (SImode);
6544   rtx op_6 = gen_reg_rtx (SImode);
6545   rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6547   emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6548   emit_insn (gen_addsi3 (op_6, op_5, op_3));
6550   if (<CODE> == SIGN_EXTEND)
6551     {
6552       emit_insn (gen_extendhisi2 (operands[0], op_7));
6553       DONE;
6554     }
6555   else if (<CODE> == ZERO_EXTEND)
6556     {
6557       /* On SH2A the movu.w insn can be used for zero extending loads.  */
6558       if (TARGET_SH2A)
6559         emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6560       else
6561         {
6562           emit_insn (gen_extendhisi2 (operands[0], op_7));
6563           emit_insn (gen_zero_extendhisi2 (operands[0],
6564                                            gen_lowpart (HImode, operands[0])));
6565         }
6566       DONE;
6567     }
6568   else
6569     FAIL;
6572 (define_insn_and_split "*mov<mode>_index_disp_store"
6573   [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6574         (match_operand:HISI 1 "arith_reg_operand" "r"))
6575    (clobber (reg:SI T_REG))]
6576   "TARGET_SH1"
6577   "#"
6578   "&& can_create_pseudo_p ()"
6579   [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6580    (set (match_dup 7) (match_dup 1))]
6582   rtx mem = operands[0];
6583   rtx plus0_rtx = XEXP (mem, 0);
6584   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6585   rtx mult_rtx = XEXP (plus1_rtx, 0);
6587   operands[0] = XEXP (mult_rtx, 0);
6588   operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6589   operands[3] = XEXP (plus1_rtx, 1);
6590   operands[4] = XEXP (plus0_rtx, 1);
6591   operands[5] = gen_reg_rtx (SImode);
6592   operands[6] = gen_reg_rtx (SImode);
6593   operands[7] =
6594     replace_equiv_address (mem,
6595                            gen_rtx_PLUS (SImode, operands[6], operands[4]));
6597   emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6600 ;; t/r must come after r/r, lest reload will try to reload stuff like
6601 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6602 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6603 (define_insn "movsi_i"
6604   [(set (match_operand:SI 0 "general_movdst_operand"
6605             "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6606         (match_operand:SI 1 "general_movsrc_operand"
6607          "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6608   "TARGET_SH1
6609    && ! TARGET_SH2E
6610    && ! TARGET_SH2A
6611    && (register_operand (operands[0], SImode)
6612        || register_operand (operands[1], SImode))"
6613   "@
6614         mov.l   %1,%0
6615         mov     %1,%0
6616         mov     %1,%0
6617         mov.l   %1,%0
6618         sts     %1,%0
6619         sts     %1,%0
6620         mov.l   %1,%0
6621         sts.l   %1,%0
6622         sts.l   %1,%0
6623         lds     %1,%0
6624         lds     %1,%0
6625         lds.l   %1,%0
6626         lds.l   %1,%0
6627         fake    %1,%0"
6628   [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
6629                      pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6630    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6632 ;; t/r must come after r/r, lest reload will try to reload stuff like
6633 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6634 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
6635 ;; will require a reload.
6636 ;; ??? We can't include f/f because we need the proper FPSCR setting when
6637 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6638 (define_insn "movsi_ie"
6639   [(set (match_operand:SI 0 "general_movdst_operand"
6640             "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6641         (match_operand:SI 1 "general_movsrc_operand"
6642          "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6643   "(TARGET_SH2E || TARGET_SH2A)
6644    && (register_operand (operands[0], SImode)
6645        || register_operand (operands[1], SImode))"
6646   "@
6647         mov.l   %1,%0
6648         mov     %1,%0
6649         mov     %1,%0
6650         movi20  %1,%0
6651         movi20s %1,%0
6652         mov.l   %1,%0
6653         sts     %1,%0
6654         sts     %1,%0
6655         mov.l   %1,%0
6656         sts.l   %1,%0
6657         sts.l   %1,%0
6658         lds     %1,%0
6659         lds     %1,%0
6660         lds.l   %1,%0
6661         lds.l   %1,%0
6662         lds.l   %1,%0
6663         sts.l   %1,%0
6664         fake    %1,%0
6665         lds     %1,%0
6666         sts     %1,%0
6667         fsts    fpul,%0
6668         flds    %1,fpul
6669         fmov    %1,%0
6670         ! move optimized away"
6671   [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
6672                      mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
6673                      pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6674    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6675    (set_attr_alternative "length"
6676      [(const_int 2)
6677       (const_int 2)
6678       (const_int 2)
6679       (const_int 4)
6680       (const_int 4)
6681       (if_then_else
6682         (match_test "TARGET_SH2A")
6683         (const_int 4) (const_int 2))
6684       (const_int 2)
6685       (const_int 2)
6686       (if_then_else
6687         (match_test "TARGET_SH2A")
6688         (const_int 4) (const_int 2))
6689       (const_int 2)
6690       (const_int 2)
6691       (const_int 2)
6692       (const_int 2)
6693       (const_int 2)
6694       (const_int 2)
6695       (const_int 2)
6696       (const_int 2)
6697       (const_int 2)
6698       (const_int 2)
6699       (const_int 2)
6700       (const_int 2)
6701       (const_int 2)
6702       (const_int 2)
6703       (const_int 0)])])
6705 (define_insn "movsi_i_lowpart"
6706   [(set (strict_low_part
6707           (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6708         (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6709    "TARGET_SH1
6710     && (register_operand (operands[0], SImode)
6711         || register_operand (operands[1], SImode))"
6712   "@
6713         mov.l   %1,%0
6714         mov     %1,%0
6715         mov     %1,%0
6716         mov.l   %1,%0
6717         sts     %1,%0
6718         sts     %1,%0
6719         mov.l   %1,%0
6720         fake    %1,%0"
6721   [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6723 (define_insn_and_split "load_ra"
6724   [(set (match_operand:SI 0 "general_movdst_operand" "")
6725         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6726   "TARGET_SH1"
6727   "#"
6728   "&& ! currently_expanding_to_rtl"
6729   [(set (match_dup 0) (match_dup 1))]
6731   if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6732     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6735 ;; The '?'s in the following constraints may not reflect the time taken
6736 ;; to perform the move. They are there to discourage the use of floating-
6737 ;; point registers for storing integer values.
6738 (define_insn "*movsi_media"
6739   [(set (match_operand:SI 0 "general_movdst_operand"
6740                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6741         (match_operand:SI 1 "general_movsrc_operand"
6742          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6743   "TARGET_SHMEDIA_FPU
6744    && (register_operand (operands[0], SImode)
6745        || sh_register_operand (operands[1], SImode)
6746        || GET_CODE (operands[1]) == TRUNCATE)"
6747   "@
6748         add.l   %1, r63, %0
6749         movi    %1, %0
6750         #
6751         ld%M1.l %m1, %0
6752         st%M0.l %m0, %N1
6753         fld%M1.s        %m1, %0
6754         fst%M0.s        %m0, %1
6755         fmov.ls %N1, %0
6756         fmov.sl %1, %0
6757         fmov.s  %1, %0
6758         ptabs   %1, %0
6759         gettr   %1, %0
6760         pt      %1, %0"
6761   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,
6762                        fload_media,fstore_media,fload_media,fpconv_media,
6763                        fmove_media,ptabs_media,gettr_media,pt_media")
6764    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6765    (set (attr "highpart")
6766         (cond [(match_test "sh_contains_memref_p (insn)")
6767                (const_string "user")]
6768               (const_string "ignore")))])
6770 (define_insn "*movsi_media_nofpu"
6771   [(set (match_operand:SI 0 "general_movdst_operand"
6772                 "=r,r,r,r,m,*b,r,*b")
6773         (match_operand:SI 1 "general_movsrc_operand"
6774          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6775   "TARGET_SHMEDIA
6776    && (register_operand (operands[0], SImode)
6777        || sh_register_operand (operands[1], SImode)
6778        || GET_CODE (operands[1]) == TRUNCATE)"
6779   "@
6780         add.l   %1, r63, %0
6781         movi    %1, %0
6782         #
6783         ld%M1.l %m1, %0
6784         st%M0.l %m0, %N1
6785         ptabs   %1, %0
6786         gettr   %1, %0
6787         pt      %1, %0"
6788   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6789                      ptabs_media,gettr_media,pt_media")
6790    (set_attr "length" "4,4,8,4,4,4,4,12")
6791    (set (attr "highpart")
6792         (cond [(match_test "sh_contains_memref_p (insn)")
6793                (const_string "user")]
6794               (const_string "ignore")))])
6796 (define_expand "movsi_const"
6797   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6798         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6799                               (const_int 16)] UNSPEC_EXTRACT_S16)))
6800    (set (match_dup 0)
6801         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
6802                 (const:SI (unspec:SI [(match_dup 1)
6803                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
6804   "TARGET_SHMEDIA && reload_completed
6805    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6807   if (GET_CODE (operands[1]) == LABEL_REF
6808       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6809     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6810   else if (GOTOFF_P (operands[1]))
6811     {
6812       rtx unspec = XEXP (operands[1], 0);
6814       if (! UNSPEC_GOTOFF_P (unspec))
6815         {
6816           unspec = XEXP (unspec, 0);
6817           if (! UNSPEC_GOTOFF_P (unspec))
6818             abort ();
6819         }
6820       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6821           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6822         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6823     }
6826 (define_expand "movsi_const_16bit"
6827   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6828         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6829                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
6830   "TARGET_SHMEDIA && flag_pic && reload_completed
6831    && GET_CODE (operands[1]) == SYMBOL_REF"
6832   "")
6834 (define_split
6835   [(set (match_operand:SI 0 "arith_reg_dest" "")
6836         (match_operand:SI 1 "immediate_operand" ""))]
6837   "TARGET_SHMEDIA && reload_completed
6838    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6839   [(const_int 0)]
6841   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6843   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6845   DONE;
6848 (define_split
6849   [(set (match_operand:SI 0 "register_operand" "")
6850         (match_operand:SI 1 "immediate_operand" ""))]
6851   "TARGET_SHMEDIA && reload_completed
6852    && ((CONST_INT_P (operands[1])
6853         && ! satisfies_constraint_I16 (operands[1]))
6854        || GET_CODE (operands[1]) == CONST_DOUBLE)"
6855   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6857 (define_expand "movsi"
6858   [(set (match_operand:SI 0 "general_movdst_operand" "")
6859         (match_operand:SI 1 "general_movsrc_operand" ""))]
6860   ""
6862   prepare_move_operands (operands, SImode);
6865 (define_expand "ic_invalidate_line"
6866   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6867                                 (match_dup 1)] UNSPEC_ICACHE)
6868               (clobber (scratch:SI))])]
6869   "TARGET_HARD_SH4 || TARGET_SH5"
6871   if (TARGET_SHMEDIA)
6872     {
6873       emit_insn (gen_ic_invalidate_line_media (operands[0]));
6874       DONE;
6875     }
6876   else if (TARGET_SHCOMPACT)
6877     {
6878       operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6879       operands[1] = force_reg (Pmode, operands[1]);
6880       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6881       DONE;
6882     }
6883   else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
6884     {
6885       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6886       DONE;
6887     }
6888   operands[0] = force_reg (Pmode, operands[0]);
6889   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6890                                                                Pmode)));
6893 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
6894 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6895 ;; the requirement *1*00 for associative address writes.  The alignment of
6896 ;; %0 implies that its least significant bit is cleared,
6897 ;; thus we clear the V bit of a matching entry if there is one.
6898 (define_insn "ic_invalidate_line_i"
6899   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6900                      (match_operand:SI 1 "register_operand" "r")]
6901                      UNSPEC_ICACHE)
6902    (clobber (match_scratch:SI 2 "=&r"))]
6903   "TARGET_HARD_SH4"
6905   return       "ocbwb   @%0"    "\n"
6906          "      extu.w  %0,%2"  "\n"
6907          "      or      %1,%2"  "\n"
6908          "      mov.l   %0,@%2";
6910   [(set_attr "length" "8")
6911    (set_attr "type" "cwb")])
6913 (define_insn "ic_invalidate_line_sh4a"
6914   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6915                     UNSPEC_ICACHE)]
6916   "TARGET_SH4A_ARCH || TARGET_SH4_300"
6918   return       "ocbwb   @%0"    "\n"
6919          "      synco"          "\n"
6920          "      icbi    @%0";
6922   [(set_attr "length" "16")     ;; FIXME: Why 16 and not 6?  Looks like typo.
6923    (set_attr "type" "cwb")])
6925 ;; ??? could make arg 0 an offsettable memory operand to allow to save
6926 ;; an add in the code that calculates the address.
6927 (define_insn "ic_invalidate_line_media"
6928   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
6929                     UNSPEC_ICACHE)]
6930   "TARGET_SHMEDIA"
6932   return       "ocbwb   %0,0"   "\n"
6933          "      synco"          "\n"
6934          "      icbi    %0,0"   "\n"
6935          "      synci";
6937   [(set_attr "length" "16")
6938    (set_attr "type" "invalidate_line_media")])
6940 (define_insn "ic_invalidate_line_compact"
6941   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6942                      (match_operand:SI 1 "register_operand" "r")]
6943                     UNSPEC_ICACHE)
6944    (clobber (reg:SI PR_REG))]
6945   "TARGET_SHCOMPACT"
6946   "jsr @%1%#"
6947   [(set_attr "type" "sfunc")
6948    (set_attr "needs_delay_slot" "yes")])
6950 (define_expand "initialize_trampoline"
6951   [(match_operand:SI 0 "" "")
6952    (match_operand:SI 1 "" "")
6953    (match_operand:SI 2 "" "")]
6954   "TARGET_SHCOMPACT"
6956   rtx sfun, tramp;
6958   tramp = force_reg (Pmode, operands[0]);
6959   sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
6960                                             SFUNC_STATIC));
6961   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6962   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6964   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6965   DONE;
6968 (define_insn "initialize_trampoline_compact"
6969   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6970                      (match_operand:SI 1 "register_operand" "r")
6971                      (reg:SI R2_REG) (reg:SI R3_REG)]
6972                     UNSPEC_INIT_TRAMP)
6974    (clobber (reg:SI PR_REG))]
6975   "TARGET_SHCOMPACT"
6976   "jsr @%1%#"
6977   [(set_attr "type" "sfunc")
6978    (set_attr "needs_delay_slot" "yes")])
6980 (define_expand "movhi"
6981   [(set (match_operand:HI 0 "general_movdst_operand" "")
6982         (match_operand:HI 1 "general_movsrc_operand" ""))]
6983   ""
6985   prepare_move_operands (operands, HImode);
6988 (define_expand "movqi"
6989   [(set (match_operand:QI 0 "general_operand" "")
6990         (match_operand:QI 1 "general_operand" ""))]
6991   ""
6993   prepare_move_operands (operands, QImode);
6996 ;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
6997 ;; selected to copy QImode regs.  If one of them happens to be allocated
6998 ;; on the stack, reload will stick to movqi insn and generate wrong
6999 ;; displacement addressing because of the generic m alternatives.
7000 ;; With the movqi_reg_reg being specified before movqi it will be initially
7001 ;; picked to load/store regs.  If the regs regs are on the stack reload
7002 ;; try other insns and not stick to movqi_reg_reg, unless there were spilled
7003 ;; pseudos in which case 'm' constraints pertain.
7004 ;; The same applies to the movhi variants.
7006 ;; Notice, that T bit is not allowed as a mov src operand here.  This is to
7007 ;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which
7008 ;; introduces zero extensions after T bit stores and redundant reg copies.
7010 ;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a
7011 ;; predicate for the mov src operand because reload will have trouble
7012 ;; reloading MAC subregs otherwise.  For that probably special patterns
7013 ;; would be required.
7014 (define_insn "*mov<mode>_reg_reg"
7015   [(set (match_operand:QIHI 0 "arith_reg_dest" "=r,m,*z")
7016         (match_operand:QIHI 1 "register_operand" "r,*z,m"))]
7017   "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)"
7018   "@
7019         mov     %1,%0
7020         mov.<bw>        %1,%0
7021         mov.<bw>        %1,%0"
7022   [(set_attr "type" "move,store,load")])
7024 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
7025 ;; "enabled" attribute as it is done in other targets.
7026 (define_insn "*mov<mode>_store_mem_disp04"
7027   [(set (mem:QIHI
7028           (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
7029                    (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
7030         (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
7031   "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
7032   "@
7033         mov.<bw>        %2,@(%O1,%0)
7034         mov.<bw>        %2,@%0"
7035   [(set_attr "type" "store")])
7037 (define_insn "*mov<mode>_store_mem_disp12"
7038   [(set (mem:QIHI
7039           (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
7040                    (match_operand:SI 1 "const_int_operand" "<disp12>")))
7041         (match_operand:QIHI 2 "arith_reg_operand" "r"))]
7042   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
7043   "mov.<bw>     %2,@(%O1,%0)"
7044   [(set_attr "type" "store")
7045    (set_attr "length" "4")])
7047 (define_insn "*mov<mode>_load_mem_disp04"
7048   [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
7049         (mem:QIHI
7050           (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
7051                    (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
7052   "TARGET_SH1 && ! TARGET_SH2A
7053    && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
7054   "@
7055         mov.<bw>        @(%O2,%1),%0
7056         mov.<bw>        @%1,%0"
7057   [(set_attr "type" "load")])
7059 (define_insn "*mov<mode>_load_mem_disp12"
7060   [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
7061         (mem:QIHI
7062           (plus:SI
7063             (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
7064             (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
7065   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
7066   "@
7067         mov.<bw>        @(%O2,%1),%0
7068         mov.<bw>        @%1,%0
7069         mov.<bw>        @(%O2,%1),%0"
7070   [(set_attr "type" "load")
7071    (set_attr "length" "2,2,4")])
7073 ;; The m constraints basically allow any kind of addresses to be used with any
7074 ;; source/target register as the other operand.  This is not true for 
7075 ;; displacement addressing modes on anything but SH2A.  That's why the
7076 ;; specialized load/store insns are specified above.
7077 (define_insn "*movqi"
7078   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
7079         (match_operand:QI 1 "general_movsrc_operand"  "i,m,r,l,r"))]
7080   "TARGET_SH1
7081    && (arith_reg_operand (operands[0], QImode)
7082        || arith_reg_operand (operands[1], QImode))"
7083   "@
7084         mov     %1,%0
7085         mov.b   %1,%0
7086         mov.b   %1,%0
7087         sts     %1,%0
7088         lds     %1,%0"
7089  [(set_attr "type" "movi8,load,store,prget,prset")])
7091 (define_insn "*movhi"
7092   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
7093         (match_operand:HI 1 "general_movsrc_operand"  "Q,i,m,r,l,r"))]
7094   "TARGET_SH1
7095    && (arith_reg_operand (operands[0], HImode)
7096        || arith_reg_operand (operands[1], HImode))"
7097   "@
7098         mov.w   %1,%0
7099         mov     %1,%0
7100         mov.w   %1,%0
7101         mov.w   %1,%0
7102         sts     %1,%0
7103         lds     %1,%0"
7104  [(set_attr "type" "pcload,movi8,load,store,prget,prset")])
7106 (define_insn "*movqi_media"
7107   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7108         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7109   "TARGET_SHMEDIA
7110    && (arith_reg_operand (operands[0], QImode)
7111        || extend_reg_or_0_operand (operands[1], QImode))"
7112   "@
7113         add.l   %1, r63, %0
7114         movi    %1, %0
7115         ld%M1.ub        %m1, %0
7116         st%M0.b %m0, %N1"
7117   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7118    (set (attr "highpart")
7119         (cond [(match_test "sh_contains_memref_p (insn)")
7120                (const_string "user")]
7121               (const_string "ignore")))])
7123 (define_expand "reload_inqi"
7124   [(set (match_operand:SI 2 "" "=&r")
7125         (match_operand:QI 1 "inqhi_operand" ""))
7126    (set (match_operand:QI 0 "arith_reg_operand" "=r")
7127         (truncate:QI (match_dup 3)))]
7128   "TARGET_SHMEDIA"
7130   rtx inner = XEXP (operands[1], 0);
7131   int regno = REGNO (inner);
7133   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7134   operands[1] = gen_rtx_REG (SImode, regno);
7135   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7138 (define_insn "*movhi_media"
7139   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
7140         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7141   "TARGET_SHMEDIA
7142    && (arith_reg_operand (operands[0], HImode)
7143        || arith_reg_or_0_operand (operands[1], HImode))"
7144   "@
7145         add.l   %1, r63, %0
7146         movi    %1, %0
7147         #
7148         ld%M1.w %m1, %0
7149         st%M0.w %m0, %N1"
7150   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7151    (set (attr "highpart")
7152         (cond [(match_test "sh_contains_memref_p (insn)")
7153                (const_string "user")]
7154               (const_string "ignore")))])
7156 (define_split
7157   [(set (match_operand:HI 0 "register_operand" "")
7158         (match_operand:HI 1 "immediate_operand" ""))]
7159   "TARGET_SHMEDIA && reload_completed
7160    && ! satisfies_constraint_I16 (operands[1])"
7161   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7163 (define_expand "reload_inhi"
7164   [(set (match_operand:SI 2 "" "=&r")
7165         (match_operand:HI 1 "inqhi_operand" ""))
7166    (set (match_operand:HI 0 "arith_reg_operand" "=r")
7167         (truncate:HI (match_dup 3)))]
7168   "TARGET_SHMEDIA"
7170   rtx inner = XEXP (operands[1], 0);
7171   int regno = REGNO (inner);
7173   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7174   operands[1] = gen_rtx_REG (SImode, regno);
7175   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7178 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7179 ;; compiled with -m2 -ml -O3 -funroll-loops
7180 (define_insn "*movdi_i"
7181   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7182         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7183   "TARGET_SH1
7184    && (arith_reg_operand (operands[0], DImode)
7185        || arith_reg_operand (operands[1], DImode))"
7187   return output_movedouble (insn, operands, DImode);
7189   [(set_attr "length" "4")
7190    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7192 ;; If the output is a register and the input is memory or a register, we have
7193 ;; to be careful and see which word needs to be loaded first.
7194 (define_split
7195   [(set (match_operand:DI 0 "general_movdst_operand" "")
7196         (match_operand:DI 1 "general_movsrc_operand" ""))]
7197   "TARGET_SH1 && reload_completed"
7198   [(set (match_dup 2) (match_dup 3))
7199    (set (match_dup 4) (match_dup 5))]
7201   int regno;
7203   if ((MEM_P (operands[0])
7204        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7205       || (MEM_P (operands[1])
7206           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7207     FAIL;
7209   switch (GET_CODE (operands[0]))
7210     {
7211     case REG:
7212       regno = REGNO (operands[0]);
7213       break;
7214     case SUBREG:
7215       regno = subreg_regno (operands[0]);
7216       break;
7217     case MEM:
7218       regno = -1;
7219       break;
7220     default:
7221       gcc_unreachable ();
7222     }
7224   if (regno == -1
7225       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7226     {
7227       operands[2] = operand_subword (operands[0], 0, 0, DImode);
7228       operands[3] = operand_subword (operands[1], 0, 0, DImode);
7229       operands[4] = operand_subword (operands[0], 1, 0, DImode);
7230       operands[5] = operand_subword (operands[1], 1, 0, DImode);
7231     }
7232   else
7233     {
7234       operands[2] = operand_subword (operands[0], 1, 0, DImode);
7235       operands[3] = operand_subword (operands[1], 1, 0, DImode);
7236       operands[4] = operand_subword (operands[0], 0, 0, DImode);
7237       operands[5] = operand_subword (operands[1], 0, 0, DImode);
7238     }
7240   if (operands[2] == 0 || operands[3] == 0
7241       || operands[4] == 0 || operands[5] == 0)
7242     FAIL;
7245 ;; The '?'s in the following constraints may not reflect the time taken
7246 ;; to perform the move. They are there to discourage the use of floating-
7247 ;; point registers for storing integer values.
7248 (define_insn "*movdi_media"
7249   [(set (match_operand:DI 0 "general_movdst_operand"
7250                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7251         (match_operand:DI 1 "general_movsrc_operand"
7252          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7253   "TARGET_SHMEDIA_FPU
7254    && (register_operand (operands[0], DImode)
7255        || sh_register_operand (operands[1], DImode))"
7256   "@
7257         add     %1, r63, %0
7258         movi    %1, %0
7259         #
7260         ld%M1.q %m1, %0
7261         st%M0.q %m0, %N1
7262         fld%M1.d        %m1, %0
7263         fst%M0.d        %m0, %1
7264         fmov.qd %N1, %0
7265         fmov.dq %1, %0
7266         fmov.d  %1, %0
7267         ptabs   %1, %0
7268         gettr   %1, %0
7269         pt      %1, %0"
7270   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7271                      fload_media,fstore_media,fload_media,dfpconv_media,
7272                      fmove_media,ptabs_media,gettr_media,pt_media")
7273    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7275 (define_insn "*movdi_media_nofpu"
7276   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7277         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7278   "TARGET_SHMEDIA
7279    && (register_operand (operands[0], DImode)
7280        || sh_register_operand (operands[1], DImode))"
7281   "@
7282         add     %1, r63, %0
7283         movi    %1, %0
7284         #
7285         ld%M1.q %m1, %0
7286         st%M0.q %m0, %N1
7287         ptabs   %1, %0
7288         gettr   %1, %0
7289         pt      %1, %0"
7290   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7291                      ptabs_media,gettr_media,pt_media")
7292    (set_attr "length" "4,4,16,4,4,4,4,*")])
7294 (define_insn "*movdi_media_I16"
7295   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7296         (match_operand:DI 1 "const_int_operand" "I16"))]
7297   "TARGET_SHMEDIA && reload_completed"
7298   "movi %1, %0"
7299   [(set_attr "type" "arith_media")
7300    (set_attr "length" "4")])
7302 (define_split
7303   [(set (match_operand:DI 0 "arith_reg_dest" "")
7304         (match_operand:DI 1 "immediate_operand" ""))]
7305   "TARGET_SHMEDIA && reload_completed
7306    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7307   [(set (match_dup 0) (match_dup 1))]
7309   rtx insn;
7311   if (TARGET_SHMEDIA64)
7312     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7313   else
7314     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7316   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7318   DONE;
7321 (define_expand "movdi_const"
7322   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7323         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7324                               (const_int 48)] UNSPEC_EXTRACT_S16)))
7325    (set (match_dup 0)
7326         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7327                 (const:DI (unspec:DI [(match_dup 1)
7328                                       (const_int 32)] UNSPEC_EXTRACT_U16))))
7329    (set (match_dup 0)
7330         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7331                 (const:DI (unspec:DI [(match_dup 1)
7332                                       (const_int 16)] UNSPEC_EXTRACT_U16))))
7333    (set (match_dup 0)
7334         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7335                 (const:DI (unspec:DI [(match_dup 1)
7336                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
7337   "TARGET_SHMEDIA64 && reload_completed
7338    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7340   sh_mark_label (operands[1], 4);
7343 (define_expand "movdi_const_32bit"
7344   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7345         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7346                               (const_int 16)] UNSPEC_EXTRACT_S16)))
7347    (set (match_dup 0)
7348         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7349                 (const:DI (unspec:DI [(match_dup 1)
7350                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
7351   "TARGET_SHMEDIA32 && reload_completed
7352    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7354   sh_mark_label (operands[1], 2);
7357 (define_expand "movdi_const_16bit"
7358   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7359         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7360                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
7361   "TARGET_SHMEDIA && flag_pic && reload_completed
7362    && GET_CODE (operands[1]) == SYMBOL_REF"
7363   "")
7365 (define_split
7366   [(set (match_operand:DI 0 "ext_dest_operand" "")
7367         (match_operand:DI 1 "immediate_operand" ""))]
7368   "TARGET_SHMEDIA && reload_completed
7369    && CONST_INT_P (operands[1])
7370    && ! satisfies_constraint_I16 (operands[1])"
7371   [(set (match_dup 0) (match_dup 2))
7372    (match_dup 1)]
7374   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7375   unsigned HOST_WIDE_INT low = val;
7376   unsigned HOST_WIDE_INT high = val;
7377   unsigned HOST_WIDE_INT sign;
7378   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7380   /* Zero-extend the 16 least-significant bits.  */
7381   low &= 0xffff;
7383   /* Arithmetic shift right the word by 16 bits.  */
7384   high >>= 16;
7385   if (GET_CODE (operands[0]) == SUBREG
7386       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7387     {
7388       high &= 0xffff;
7389       high ^= 0x8000;
7390       high -= 0x8000;
7391     }
7392   else
7393     {
7394       sign = 1;
7395       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7396       high ^= sign;
7397       high -= sign;
7398     }
7399   do
7400     {
7401       /* If we can't generate the constant with a two-insn movi / shori
7402          sequence, try some other strategies.  */
7403       if (! CONST_OK_FOR_I16 (high))
7404         {
7405           /* Try constant load / left shift.  We know VAL != 0.  */
7406           val2 = val ^ (val-1);
7407           if (val2 > 0x1ffff)
7408             {
7409               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7411               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7412                   || (! CONST_OK_FOR_I16 (high >> 16)
7413                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7414                 {
7415                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7416                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
7417                                                    GEN_INT (trailing_zeroes));
7418                   break;
7419                 }
7420             }
7421           /* Try constant load / right shift.  */
7422           val2 = (val >> 15) + 1;
7423           if (val2 == (val2 & -val2))
7424             {
7425               int shift = 49 - exact_log2 (val2);
7427               val2 = trunc_int_for_mode (val << shift, DImode);
7428               if (CONST_OK_FOR_I16 (val2))
7429                 {
7430                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7431                                                    GEN_INT (shift));
7432                   break;
7433                 }
7434             }
7435           /* Try mperm.w .  */
7436           val2 = val & 0xffff;
7437           if ((val >> 16 & 0xffff) == val2
7438               && (val >> 32 & 0xffff) == val2
7439               && (val >> 48 & 0xffff) == val2)
7440             {
7441               val2 = (HOST_WIDE_INT) val >> 48;
7442               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7443               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7444               break;
7445             }
7446           /* Try movi / mshflo.l  */
7447           val2 = (HOST_WIDE_INT) val >> 32;
7448           if (val2 == ((unsigned HOST_WIDE_INT)
7449                         trunc_int_for_mode (val, SImode)))
7450             {
7451               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7452                                              operands[0]);
7453               break;
7454             }
7455           /* Try movi / mshflo.l w/ r63.  */
7456           val2 = val + ((HOST_WIDE_INT) -1 << 32);
7457           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7458             {
7459               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7460                                              const0_rtx);
7461               break;
7462             }
7463         }
7464       val2 = high;
7465       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7466     }
7467   while (0);
7468   operands[2] = GEN_INT (val2);
7471 (define_split
7472   [(set (match_operand:DI 0 "ext_dest_operand" "")
7473         (match_operand:DI 1 "immediate_operand" ""))]
7474   "TARGET_SHMEDIA && reload_completed
7475    && GET_CODE (operands[1]) == CONST_DOUBLE"
7476   [(set (match_dup 0) (match_dup 2))
7477   (set (match_dup 0)
7478        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7480   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7481   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7482   unsigned HOST_WIDE_INT val = low;
7483   unsigned HOST_WIDE_INT sign;
7485   /* Zero-extend the 16 least-significant bits.  */
7486   val &= 0xffff;
7487   operands[1] = GEN_INT (val);
7489   /* Arithmetic shift right the double-word by 16 bits.  */
7490   low >>= 16;
7491   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7492   high >>= 16;
7493   sign = 1;
7494   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7495   high ^= sign;
7496   high -= sign;
7498   /* This will only be true if high is a sign-extension of low, i.e.,
7499      it must be either 0 or (unsigned)-1, and be zero iff the
7500      most-significant bit of low is set.  */
7501   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7502     operands[2] = GEN_INT (low);
7503   else
7504     operands[2] = immed_double_const (low, high, DImode);
7507 (define_insn "shori_media"
7508   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7509         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7510                            (const_int 16))
7511                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7512   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7513   "@
7514         shori   %u2, %0
7515         #"
7516   [(set_attr "type" "arith_media,*")])
7518 (define_insn "*shori_media_si"
7519   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7520         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7521                            (const_int 16))
7522                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7523   "TARGET_SHMEDIA"
7524   "shori        %u2, %0")
7526 (define_expand "movdi"
7527   [(set (match_operand:DI 0 "general_movdst_operand" "")
7528         (match_operand:DI 1 "general_movsrc_operand" ""))]
7529   ""
7531   prepare_move_operands (operands, DImode);
7534 (define_insn "movdf_media"
7535   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7536         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7537   "TARGET_SHMEDIA_FPU
7538    && (register_operand (operands[0], DFmode)
7539        || sh_register_operand (operands[1], DFmode))"
7540   "@
7541         fmov.d  %1, %0
7542         fmov.qd %N1, %0
7543         fmov.dq %1, %0
7544         add     %1, r63, %0
7545         #
7546         fld%M1.d        %m1, %0
7547         fst%M0.d        %m0, %1
7548         ld%M1.q %m1, %0
7549         st%M0.q %m0, %N1"
7550   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7551                      fload_media,fstore_media,load_media,store_media")])
7553 (define_insn "movdf_media_nofpu"
7554   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7555         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7556   "TARGET_SHMEDIA
7557    && (register_operand (operands[0], DFmode)
7558        || sh_register_operand (operands[1], DFmode))"
7559   "@
7560         add     %1, r63, %0
7561         #
7562         ld%M1.q %m1, %0
7563         st%M0.q %m0, %N1"
7564   [(set_attr "type" "arith_media,*,load_media,store_media")])
7566 (define_split
7567   [(set (match_operand:DF 0 "arith_reg_dest" "")
7568         (match_operand:DF 1 "immediate_operand" ""))]
7569   "TARGET_SHMEDIA && reload_completed"
7570   [(set (match_dup 3) (match_dup 2))]
7572   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7573   long values[2];
7574   REAL_VALUE_TYPE value;
7576   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7577   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7579   if (HOST_BITS_PER_WIDE_INT >= 64)
7580     operands[2] = immed_double_const ((unsigned long) values[endian]
7581                                       | ((HOST_WIDE_INT) values[1 - endian]
7582                                          << 32), 0, DImode);
7583   else
7584     {
7585       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7586       operands[2] = immed_double_const (values[endian], values[1 - endian],
7587                                         DImode);
7588     }
7590   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7593 ;; FIXME: This should be a define_insn_and_split.
7594 (define_insn "movdf_k"
7595   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7596         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7597   "TARGET_SH1
7598    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7599        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7600        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7601        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7602    && (arith_reg_operand (operands[0], DFmode)
7603        || arith_reg_operand (operands[1], DFmode))"
7605   return output_movedouble (insn, operands, DFmode);
7607   [(set_attr "length" "4")
7608    (set_attr "type" "move,pcload,load,store")])
7610 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7611 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
7612 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
7613 ;; the d/m/c/X alternative, which is split later into single-precision
7614 ;; instructions.  And when not optimizing, no splits are done before fixing
7615 ;; up pcloads, so we need usable length information for that.
7616 (define_insn "movdf_i4"
7617   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7618         (match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
7619    (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
7620    (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
7621   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7622    && (arith_reg_operand (operands[0], DFmode)
7623        || arith_reg_operand (operands[1], DFmode))"
7624   {
7625     switch (which_alternative)
7626     {
7627     case 0:
7628       if (TARGET_FMOVD)
7629         return "fmov    %1,%0";
7630       else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7631         return         "fmov    %R1,%R0"        "\n"
7632                "        fmov    %S1,%S0";
7633       else
7634         return         "fmov    %S1,%S0"        "\n"
7635                "        fmov    %R1,%R0";
7636     case 3:
7637     case 4:
7638       return "fmov.d    %1,%0";
7639     default:
7640       return "#";
7641     }
7642   }
7643   [(set_attr_alternative "length"
7644      [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7645       (const_int 4)
7646       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7647       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7648       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7649       (const_int 4)
7650       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7651       ;; We can't use 4-byte push/pop on SHcompact, so we have to
7652       ;; increment or decrement r15 explicitly.
7653       (if_then_else
7654        (match_test "TARGET_SHCOMPACT")
7655        (const_int 10) (const_int 8))
7656       (if_then_else
7657        (match_test "TARGET_SHCOMPACT")
7658        (const_int 10) (const_int 8))])
7659    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7660    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7661    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7662                                            (const_string "double")
7663                                            (const_string "none")))])
7665 ;; Moving DFmode between fp/general registers through memory
7666 ;; (the top of the stack) is faster than moving through fpul even for
7667 ;; little endian.  Because the type of an instruction is important for its
7668 ;; scheduling,  it is beneficial to split these operations, rather than
7669 ;; emitting them in one single chunk, even if this will expose a stack
7670 ;; use that will prevent scheduling of other stack accesses beyond this
7671 ;; instruction.
7672 (define_split
7673   [(set (match_operand:DF 0 "register_operand" "")
7674         (match_operand:DF 1 "register_operand" ""))
7675    (use (match_operand:PSI 2 "fpscr_operand" ""))
7676    (clobber (match_scratch:SI 3 "=X"))]
7677   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7678    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7679   [(const_int 0)]
7681   rtx insn, tos;
7683   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7684     {
7685       emit_move_insn (stack_pointer_rtx,
7686                       plus_constant (Pmode, stack_pointer_rtx, -8));
7687       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7688     }
7689   else
7690     tos = gen_tmp_stack_mem (DFmode,
7691                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7692   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
7693   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7694     add_reg_note (insn, REG_INC, stack_pointer_rtx);
7695   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7696     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7697   else
7698     tos = gen_tmp_stack_mem (DFmode,
7699                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7700   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
7701   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7702     emit_move_insn (stack_pointer_rtx,
7703                     plus_constant (Pmode, stack_pointer_rtx, 8));
7704   else
7705     add_reg_note (insn, REG_INC, stack_pointer_rtx);
7706   DONE;
7709 ;; local-alloc sometimes allocates scratch registers even when not required,
7710 ;; so we must be prepared to handle these.
7712 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7713 (define_split
7714   [(set (match_operand:DF 0 "general_movdst_operand" "")
7715         (match_operand:DF 1 "general_movsrc_operand"  ""))
7716    (use (match_operand:PSI 2 "fpscr_operand" ""))
7717    (clobber (match_scratch:SI 3 ""))]
7718   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7719    && reload_completed
7720    && true_regnum (operands[0]) < 16
7721    && true_regnum (operands[1]) < 16"
7722   [(set (match_dup 0) (match_dup 1))]
7724   /* If this was a reg <-> mem operation with base + index reg addressing,
7725      we have to handle this in a special way.  */
7726   rtx mem = operands[0];
7727   int store_p = 1;
7728   if (! memory_operand (mem, DFmode))
7729     {
7730       mem = operands[1];
7731       store_p = 0;
7732     }
7733   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7734     mem = SUBREG_REG (mem);
7735   if (MEM_P (mem))
7736     {
7737       rtx addr = XEXP (mem, 0);
7738       if (GET_CODE (addr) == PLUS
7739           && REG_P (XEXP (addr, 0))
7740           && REG_P (XEXP (addr, 1)))
7741         {
7742           int offset;
7743           rtx reg0 = gen_rtx_REG (Pmode, 0);
7744           rtx regop = operands[store_p], word0 ,word1;
7746           if (GET_CODE (regop) == SUBREG)
7747             alter_subreg (&regop, true);
7748           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7749             offset = 2;
7750           else
7751             offset = 4;
7752           mem = copy_rtx (mem);
7753           PUT_MODE (mem, SImode);
7754           word0 = gen_rtx_SUBREG (SImode, regop, 0);
7755           alter_subreg (&word0, true);
7756           word1 = gen_rtx_SUBREG (SImode, regop, 4);
7757           alter_subreg (&word1, true);
7758           if (store_p || ! refers_to_regno_p (REGNO (word0),
7759                                               REGNO (word0) + 1, addr, 0))
7760             {
7761               emit_insn (store_p
7762                          ? gen_movsi_ie (mem, word0)
7763                          : gen_movsi_ie (word0, mem));
7764               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7765               mem = copy_rtx (mem);
7766               emit_insn (store_p
7767                          ? gen_movsi_ie (mem, word1)
7768                          : gen_movsi_ie (word1, mem));
7769               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7770             }
7771           else
7772             {
7773               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7774               emit_insn (gen_movsi_ie (word1, mem));
7775               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7776               mem = copy_rtx (mem);
7777               emit_insn (gen_movsi_ie (word0, mem));
7778             }
7779           DONE;
7780         }
7781     }
7784 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7785 (define_split
7786   [(set (match_operand:DF 0 "register_operand" "")
7787         (match_operand:DF 1 "memory_operand"  ""))
7788    (use (match_operand:PSI 2 "fpscr_operand" ""))
7789    (clobber (reg:SI R0_REG))]
7790   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7791   [(parallel [(set (match_dup 0) (match_dup 1))
7792               (use (match_dup 2))
7793               (clobber (scratch:SI))])]
7794   "")
7796 (define_expand "reload_indf__frn"
7797   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7798                    (match_operand:DF 1 "immediate_operand" "FQ"))
7799               (use (reg:PSI FPSCR_REG))
7800               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7801   "TARGET_SH1"
7802   "")
7804 (define_expand "reload_outdf__RnFRm"
7805   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7806                    (match_operand:DF 1 "register_operand" "af,r"))
7807               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7808   "TARGET_SH1"
7809   "")
7811 ;; Simplify no-op moves.
7812 (define_split
7813   [(set (match_operand:SF 0 "register_operand" "")
7814         (match_operand:SF 1 "register_operand" ""))
7815    (use (match_operand:PSI 2 "fpscr_operand" ""))
7816    (clobber (match_scratch:SI 3 ""))]
7817   "TARGET_SH2E && reload_completed
7818    && true_regnum (operands[0]) == true_regnum (operands[1])"
7819   [(set (match_dup 0) (match_dup 0))]
7820   "")
7822 ;; fmovd substitute post-reload splits
7823 (define_split
7824   [(set (match_operand:DF 0 "register_operand" "")
7825         (match_operand:DF 1 "register_operand" ""))
7826    (use (match_operand:PSI 2 "fpscr_operand" ""))
7827    (clobber (match_scratch:SI 3 ""))]
7828   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7829    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7830    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7831   [(const_int 0)]
7833   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7834   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7835                            gen_rtx_REG (SFmode, src), operands[2]));
7836   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7837                            gen_rtx_REG (SFmode, src + 1), operands[2]));
7838   DONE;
7841 (define_split
7842   [(set (match_operand:DF 0 "register_operand" "")
7843         (mem:DF (match_operand:SI 1 "register_operand" "")))
7844    (use (match_operand:PSI 2 "fpscr_operand" ""))
7845    (clobber (match_scratch:SI 3 ""))]
7846   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7847    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7848    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7849   [(const_int 0)]
7851   int regno = true_regnum (operands[0]);
7852   rtx insn;
7853   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7854   rtx mem2
7855     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7856   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7857                                                regno + SH_REG_MSW_OFFSET),
7858                                   mem2, operands[2]));
7859   add_reg_note (insn, REG_INC, operands[1]);
7860   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7861                                                regno + SH_REG_LSW_OFFSET),
7862                                   change_address (mem, SFmode, NULL_RTX),
7863                                   operands[2]));
7864   DONE;
7867 (define_split
7868   [(set (match_operand:DF 0 "register_operand" "")
7869         (match_operand:DF 1 "memory_operand" ""))
7870    (use (match_operand:PSI 2 "fpscr_operand" ""))
7871    (clobber (match_scratch:SI 3 ""))]
7872   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7873    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7874   [(const_int 0)]
7876   int regno = true_regnum (operands[0]);
7877   rtx addr, insn;
7878   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7879   rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7880   rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7882   operands[1] = copy_rtx (mem2);
7883   addr = XEXP (mem2, 0);
7885   switch (GET_CODE (addr))
7886     {
7887     case REG:
7888       /* This is complicated.  If the register is an arithmetic register
7889          we can just fall through to the REG+DISP case below.  Otherwise
7890          we have to use a combination of POST_INC and REG addressing...  */
7891       if (! arith_reg_operand (operands[1], SFmode))
7892         {
7893           XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7894           insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7895           add_reg_note (insn, REG_INC, XEXP (addr, 0));
7896           
7897           emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7899           /* If we have modified the stack pointer, the value that we have
7900              read with post-increment might be modified by an interrupt,
7901              so write it back.  */
7902           if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7903             emit_insn (gen_push_e (reg0));
7904           else
7905             emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
7906                                    GEN_INT (-4)));
7907           break;
7908         }
7909       /* Fall through.  */
7911     case PLUS:
7912       emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7913       operands[1] = copy_rtx (operands[1]);
7914       XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7915       emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7916       break;
7918     case POST_INC:
7919       insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7920       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7922       insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7923       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7924       break;
7926     default:
7927       debug_rtx (addr);
7928       gcc_unreachable ();
7929     }
7931   DONE;
7934 (define_split
7935   [(set (match_operand:DF 0 "memory_operand" "")
7936         (match_operand:DF 1 "register_operand" ""))
7937    (use (match_operand:PSI 2 "fpscr_operand" ""))
7938    (clobber (match_scratch:SI 3 ""))]
7939   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7940    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7941   [(const_int 0)]
7943   int regno = true_regnum (operands[1]);
7944   rtx insn, addr;
7945   rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7946   rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7948   operands[0] = copy_rtx (operands[0]);
7949   PUT_MODE (operands[0], SFmode);
7950   addr = XEXP (operands[0], 0);
7952   switch (GET_CODE (addr))
7953     {
7954     case REG:
7955       /* This is complicated.  If the register is an arithmetic register
7956          we can just fall through to the REG+DISP case below.  Otherwise
7957          we have to use a combination of REG and PRE_DEC addressing...  */
7958       if (! arith_reg_operand (operands[0], SFmode))
7959         {
7960           emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7961           emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7963           operands[0] = copy_rtx (operands[0]);
7964           XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7965           
7966           insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7967           add_reg_note (insn, REG_INC, XEXP (addr, 0));
7968           break;
7969         }
7970       /* Fall through.  */
7972     case PLUS:
7973       /* Since REG+DISP addressing has already been decided upon by gcc
7974          we can rely upon it having chosen an arithmetic register as the
7975          register component of the address.  Just emit the lower numbered
7976          register first, to the lower address, then the higher numbered
7977          register to the higher address.  */
7978       emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7980       operands[0] = copy_rtx (operands[0]);
7981       XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7983       emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7984       break;
7986     case PRE_DEC:
7987       /* This is easy.  Output the word to go to the higher address
7988          first (ie the word in the higher numbered register) then the
7989          word to go to the lower address.  */
7991       insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7992       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7994       insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7995       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7996       break;
7998     default:
7999       /* FAIL; */
8000       debug_rtx (addr);
8001       gcc_unreachable ();
8002     }
8004   DONE;
8007 ;; If the output is a register and the input is memory or a register, we have
8008 ;; to be careful and see which word needs to be loaded first.
8009 (define_split
8010   [(set (match_operand:DF 0 "general_movdst_operand" "")
8011         (match_operand:DF 1 "general_movsrc_operand" ""))]
8012   "TARGET_SH1 && reload_completed"
8013   [(set (match_dup 2) (match_dup 3))
8014    (set (match_dup 4) (match_dup 5))]
8016   int regno;
8018   if ((MEM_P (operands[0])
8019        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
8020       || (MEM_P (operands[1])
8021           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
8022     FAIL;
8024   switch (GET_CODE (operands[0]))
8025     {
8026     case REG:
8027       regno = REGNO (operands[0]);
8028       break;
8029     case SUBREG:
8030       regno = subreg_regno (operands[0]);
8031       break;
8032     case MEM:
8033       regno = -1;
8034       break;
8035     default:
8036       gcc_unreachable ();
8037     }
8039   if (regno == -1
8040       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
8041     {
8042       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
8043       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
8044       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
8045       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
8046     }
8047   else
8048     {
8049       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
8050       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
8051       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
8052       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
8053     }
8055   if (operands[2] == 0 || operands[3] == 0
8056       || operands[4] == 0 || operands[5] == 0)
8057     FAIL;
8060 (define_expand "movdf"
8061   [(set (match_operand:DF 0 "general_movdst_operand" "")
8062         (match_operand:DF 1 "general_movsrc_operand" ""))]
8063   ""
8065   prepare_move_operands (operands, DFmode);
8066   if (TARGET_SHMEDIA)
8067     {
8068       if (TARGET_SHMEDIA_FPU)
8069         emit_insn (gen_movdf_media (operands[0], operands[1]));
8070       else
8071         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
8072       DONE;
8073     }
8074   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8075     {
8076       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8077       DONE;
8078     }
8081 ;;This is incompatible with the way gcc uses subregs.
8082 ;;(define_insn "movv2sf_i"
8083 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8084 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8085 ;;  "TARGET_SHMEDIA_FPU
8086 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
8087 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
8088 ;;  "@
8089 ;;      #
8090 ;;      fld%M1.p        %m1, %0
8091 ;;      fst%M0.p        %m0, %1"
8092 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
8093 (define_insn_and_split "movv2sf_i"
8094   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8095         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8096   "TARGET_SHMEDIA_FPU"
8097   "#"
8098   "TARGET_SHMEDIA_FPU && reload_completed"
8099   [(set (match_dup 0) (match_dup 1))]
8101   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8102   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8105 (define_expand "movv2sf"
8106   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8107         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
8108   "TARGET_SHMEDIA_FPU"
8110   prepare_move_operands (operands, V2SFmode);
8113 (define_expand "addv2sf3"
8114   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8115    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8116    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8117   "TARGET_SHMEDIA_FPU"
8119   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8120   DONE;
8123 (define_expand "subv2sf3"
8124   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8125    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8126    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8127   "TARGET_SHMEDIA_FPU"
8129   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8130   DONE;
8133 (define_expand "mulv2sf3"
8134   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8135    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8136    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8137   "TARGET_SHMEDIA_FPU"
8139   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8140   DONE;
8143 (define_expand "divv2sf3"
8144   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8145    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8146    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8147   "TARGET_SHMEDIA_FPU"
8149   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8150   DONE;
8153 (define_insn_and_split "*movv4sf_i"
8154   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8155         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8156   "TARGET_SHMEDIA_FPU"
8157   "#"
8158   "&& reload_completed"
8159   [(const_int 0)]
8161   for (int i = 0; i < 4/2; i++)
8162     {
8163       rtx x, y;
8165       if (MEM_P (operands[0]))
8166         x = adjust_address (operands[0], V2SFmode,
8167                             i * GET_MODE_SIZE (V2SFmode));
8168       else
8169         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8171       if (MEM_P (operands[1]))
8172         y = adjust_address (operands[1], V2SFmode,
8173                             i * GET_MODE_SIZE (V2SFmode));
8174       else
8175         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8177       emit_insn (gen_movv2sf_i (x, y));
8178     }
8180   DONE;
8182   [(set_attr "length" "8")])
8184 (define_expand "movv4sf"
8185   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8186         (match_operand:V4SF 1 "general_operand" ""))]
8187   "TARGET_SHMEDIA_FPU"
8189   prepare_move_operands (operands, V4SFmode);
8192 (define_insn_and_split "*movv16sf_i"
8193   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8194         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8195   "TARGET_SHMEDIA_FPU"
8196   "#"
8197   "&& reload_completed"
8198   [(const_int 0)]
8200   for (int i = 0; i < 16/2; i++)
8201     {
8202       rtx x, y;
8204       if (MEM_P (operands[0]))
8205         x = adjust_address (operands[0], V2SFmode,
8206                             i * GET_MODE_SIZE (V2SFmode));
8207       else
8208         {
8209           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8210           alter_subreg (&x, true);
8211         }
8213       if (MEM_P (operands[1]))
8214         y = adjust_address (operands[1], V2SFmode,
8215                             i * GET_MODE_SIZE (V2SFmode));
8216       else
8217         {
8218           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8219           alter_subreg (&y, true);
8220         }
8222       emit_insn (gen_movv2sf_i (x, y));
8223     }
8225   DONE;
8227   [(set_attr "length" "32")])
8229 (define_expand "movv16sf"
8230   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8231         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8232   "TARGET_SHMEDIA_FPU"
8234   prepare_move_operands (operands, V16SFmode);
8237 (define_insn "movsf_media"
8238   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8239         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8240   "TARGET_SHMEDIA_FPU
8241    && (register_operand (operands[0], SFmode)
8242        || sh_register_operand (operands[1], SFmode))"
8243   "@
8244         fmov.s  %1, %0
8245         fmov.ls %N1, %0
8246         fmov.sl %1, %0
8247         add.l   %1, r63, %0
8248         #
8249         fld%M1.s        %m1, %0
8250         fst%M0.s        %m0, %1
8251         ld%M1.l %m1, %0
8252         st%M0.l %m0, %N1"
8253   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8254    (set (attr "highpart")
8255         (cond [(match_test "sh_contains_memref_p (insn)")
8256                (const_string "user")]
8257               (const_string "ignore")))])
8259 (define_insn "movsf_media_nofpu"
8260   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8261         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8262   "TARGET_SHMEDIA
8263    && (register_operand (operands[0], SFmode)
8264        || sh_register_operand (operands[1], SFmode))"
8265   "@
8266         add.l   %1, r63, %0
8267         #
8268         ld%M1.l %m1, %0
8269         st%M0.l %m0, %N1"
8270   [(set_attr "type" "arith_media,*,load_media,store_media")
8271    (set (attr "highpart")
8272         (cond [(match_test "sh_contains_memref_p (insn)")
8273                (const_string "user")]
8274               (const_string "ignore")))])
8276 (define_split
8277   [(set (match_operand:SF 0 "arith_reg_dest" "")
8278         (match_operand:SF 1 "immediate_operand" ""))]
8279   "TARGET_SHMEDIA && reload_completed
8280    && ! FP_REGISTER_P (true_regnum (operands[0]))"
8281   [(set (match_dup 3) (match_dup 2))]
8283   long values;
8284   REAL_VALUE_TYPE value;
8286   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8287   REAL_VALUE_TO_TARGET_SINGLE (value, values);
8288   operands[2] = GEN_INT (values);
8290   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8293 (define_insn "movsf_i"
8294   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8295         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
8296   "TARGET_SH1
8297    && (! TARGET_SH2E
8298        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8299        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8300        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8301    && (arith_reg_operand (operands[0], SFmode)
8302        || arith_reg_operand (operands[1], SFmode))"
8303   "@
8304         mov     %1,%0
8305         mov     #0,%0
8306         mov.l   %1,%0
8307         mov.l   %1,%0
8308         mov.l   %1,%0
8309         lds     %1,%0
8310         sts     %1,%0"
8311   [(set_attr "type" "move,move,pcload,load,store,move,move")])
8313 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8314 ;; update_flow_info would not know where to put REG_EQUAL notes
8315 ;; when the destination changes mode.
8316 (define_insn "movsf_ie"
8317   [(set (match_operand:SF 0 "general_movdst_operand"
8318          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8319         (match_operand:SF 1 "general_movsrc_operand"
8320           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8321    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
8322    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8323   "TARGET_SH2E
8324    && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8325        || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8326        || arith_reg_operand (operands[3], SImode))"
8327   "@
8328         fmov    %1,%0
8329         mov     %1,%0
8330         fldi0   %0
8331         fldi1   %0
8332         #
8333         fmov.s  %1,%0
8334         fmov.s  %1,%0
8335         mov.l   %1,%0
8336         mov.l   %1,%0
8337         mov.l   %1,%0
8338         fsts    fpul,%0
8339         flds    %1,fpul
8340         lds.l   %1,%0
8341         #
8342         sts     %1,%0
8343         lds     %1,%0
8344         sts.l   %1,%0
8345         lds.l   %1,%0
8346         ! move optimized away"
8347   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8348                      store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8349    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8350    (set_attr_alternative "length"
8351      [(const_int 2)
8352       (const_int 2)
8353       (const_int 2)
8354       (const_int 2)
8355       (const_int 4)
8356       (if_then_else
8357         (match_test "TARGET_SH2A")
8358         (const_int 4) (const_int 2))
8359       (if_then_else
8360         (match_test "TARGET_SH2A")
8361         (const_int 4) (const_int 2))
8362       (const_int 2)
8363       (if_then_else
8364         (match_test "TARGET_SH2A")
8365         (const_int 4) (const_int 2))
8366       (if_then_else
8367         (match_test "TARGET_SH2A")
8368         (const_int 4) (const_int 2))
8369       (const_int 2)
8370       (const_int 2)
8371       (const_int 2)
8372       (const_int 4)
8373       (const_int 2)
8374       (const_int 2)
8375       (const_int 2)
8376       (const_int 2)
8377       (const_int 0)])
8378    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8379                                            (const_string "single")
8380                                            (const_string "single")))])
8382 (define_split
8383   [(set (match_operand:SF 0 "register_operand" "")
8384         (match_operand:SF 1 "register_operand" ""))
8385    (use (match_operand:PSI 2 "fpscr_operand" ""))
8386    (clobber (reg:SI FPUL_REG))]
8387   "TARGET_SH1"
8388   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8389               (use (match_dup 2))
8390               (clobber (scratch:SI))])
8391    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8392               (use (match_dup 2))
8393               (clobber (scratch:SI))])]
8394   "")
8396 (define_expand "movsf"
8397   [(set (match_operand:SF 0 "general_movdst_operand" "")
8398         (match_operand:SF 1 "general_movsrc_operand" ""))]
8399   ""
8401   prepare_move_operands (operands, SFmode);
8402   if (TARGET_SHMEDIA)
8403     {
8404       if (TARGET_SHMEDIA_FPU)
8405         emit_insn (gen_movsf_media (operands[0], operands[1]));
8406       else
8407         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8408       DONE;
8409     }
8410   if (TARGET_SH2E)
8411     {
8412       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
8413       DONE;
8414     }
8417 (define_insn "mov_nop"
8418   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8419   "TARGET_SH2E"
8420   ""
8421   [(set_attr "length" "0")
8422    (set_attr "type" "nil")])
8424 (define_expand "reload_insf__frn"
8425   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8426                    (match_operand:SF 1 "immediate_operand" "FQ"))
8427               (use (reg:PSI FPSCR_REG))
8428               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8429   "TARGET_SH1"
8430   "")
8432 (define_expand "reload_insi__i_fpul"
8433   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8434                    (match_operand:SI 1 "immediate_operand" "i"))
8435               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8436   "TARGET_SH1"
8437   "")
8439 (define_expand "ptabs"
8440   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8441   "TARGET_SHMEDIA"
8443   if (!TARGET_PT_FIXED)
8444     {
8445       rtx eq = operands[1];
8447       /* ??? For canonical RTL we really should remove any CONST from EQ
8448          before wrapping it in the AND, and finally wrap the EQ into a
8449          const if is constant.  However, for reload we must expose the
8450          input register or symbolic constant, and we can't have
8451          different insn structures outside of the operands for different
8452          alternatives of the same pattern.  */
8453       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8454                        GEN_INT (3));
8455       operands[1]
8456         = (gen_rtx_IF_THEN_ELSE
8457             (PDImode,
8458              eq,
8459              gen_rtx_MEM (PDImode, operands[1]),
8460              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8461                             PDImode, operands[1])));
8462     }
8465 ;; expanded by ptabs expander.
8466 (define_insn "*extendsipdi_media"
8467   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8468         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8469                                                           "r,Csy")
8470                                       (const_int 3))
8471                               (const_int 3))
8472                           (mem:PDI (match_dup 1))
8473                           (sign_extend:PDI (match_dup 1))))]
8474   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8475   "@
8476         ptabs   %1, %0
8477         pt      %1, %0"
8478   [(set_attr "type"   "ptabs_media,pt_media")
8479    (set_attr "length" "4,*")])
8481 (define_insn "*truncdipdi_media"
8482   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8483         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8484                                                           "r,Csy")
8485                                       (const_int 3))
8486                               (const_int 3))
8487                           (mem:PDI (match_dup 1))
8488                           (truncate:PDI (match_dup 1))))]
8489   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8490   "@
8491         ptabs   %1, %0
8492         pt      %1, %0"
8493   [(set_attr "type"   "ptabs_media,pt_media")
8494    (set_attr "length" "4,*")])
8496 (define_insn "*movsi_y"
8497   [(set (match_operand:SI 0 "register_operand" "=y,y")
8498         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
8499    (clobber (match_scratch:SI 2 "=&z,r"))]
8500   "TARGET_SH2E
8501    && (reload_in_progress || reload_completed)"
8502   "#"
8503   [(set_attr "length" "4")
8504    (set_attr "type" "pcload,move")])
8506 (define_split
8507   [(set (match_operand:SI 0 "register_operand" "")
8508         (match_operand:SI 1 "immediate_operand" ""))
8509    (clobber (match_operand:SI 2 "register_operand" ""))]
8510   "TARGET_SH1"
8511   [(set (match_dup 2) (match_dup 1))
8512    (set (match_dup 0) (match_dup 2))]
8513   "")
8515 ;; ------------------------------------------------------------------------
8516 ;; Define the real conditional branch instructions.
8517 ;; ------------------------------------------------------------------------
8519 (define_expand "branch_true"
8520   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8521                            (label_ref (match_operand 0))
8522                            (pc)))]
8523   "TARGET_SH1")
8525 (define_expand "branch_false"
8526   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8527                            (label_ref (match_operand 0))
8528                            (pc)))]
8529   "TARGET_SH1")
8531 (define_insn_and_split "*cbranch_t"
8532   [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8533                            (label_ref (match_operand 0))
8534                            (pc)))]
8535   "TARGET_SH1"
8537   return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8539   "&& 1"
8540   [(const_int 0)]
8542   /* Try to canonicalize the branch condition if it is not one of:
8543         (ne (reg:SI T_REG) (const_int 0))
8544         (eq (reg:SI T_REG) (const_int 0))
8546      Instead of splitting out a new insn, we modify the current insn's
8547      operands as needed.  This preserves things such as REG_DEAD notes.  */
8549   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
8550       && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
8551       && XEXP (operands[1], 1) == const0_rtx)
8552     DONE;
8554   int branch_cond = sh_eval_treg_value (operands[1]);
8555   rtx new_cond_rtx = NULL_RTX;
8557   if (branch_cond == 0)
8558     new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
8559   else if (branch_cond == 1)
8560     new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
8562   if (new_cond_rtx != NULL_RTX)
8563     validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
8564                      new_cond_rtx, false);
8565   DONE;
8567   [(set_attr "type" "cbranch")])
8569 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
8570 ;; which destination is too far away.
8571 ;; The const_int_operand is distinct for each branch target; it avoids
8572 ;; unwanted matches with redundant_insn.
8573 (define_insn "block_branch_redirect"
8574   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8575   "TARGET_SH1"
8576   ""
8577   [(set_attr "length" "0")])
8579 ;; This one has the additional purpose to record a possible scratch register
8580 ;; for the following branch.
8581 ;; ??? Unfortunately, just setting the scratch register is not good enough,
8582 ;; because the insn then might be deemed dead and deleted.  And we can't
8583 ;; make the use in the jump insn explicit because that would disable
8584 ;; delay slot scheduling from the target.
8585 (define_insn "indirect_jump_scratch"
8586   [(set (match_operand:SI 0 "register_operand" "=r")
8587         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8588    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8589   "TARGET_SH1"
8590   ""
8591   [(set_attr "length" "0")])
8593 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
8594 ;; being pulled into the delay slot of a condbranch that has been made to
8595 ;; jump around the unconditional jump because it was out of range.
8596 (define_insn "stuff_delay_slot"
8597   [(set (pc)
8598         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8599                  (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8600   "TARGET_SH1"
8601   ""
8602   [(set_attr "length" "0")
8603    (set_attr "cond_delay_slot" "yes")])
8605 ;; Conditional branch insns
8607 (define_expand "cbranchint4_media"
8608   [(set (pc)
8609         (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8610                        [(match_operand 1 "" "")
8611                         (match_operand 2 "" "")])
8612                       (match_operand 3 "" "")
8613                       (pc)))]
8614   "TARGET_SHMEDIA"
8616   enum machine_mode mode = GET_MODE (operands[1]);
8617   if (mode == VOIDmode)
8618     mode = GET_MODE (operands[2]);
8619   if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8620     {
8621       operands[1] = force_reg (mode, operands[1]);
8622       if (CONSTANT_P (operands[2])
8623           && (! satisfies_constraint_I06 (operands[2])))
8624         operands[2] = force_reg (mode, operands[2]);
8625     }
8626   else
8627     {
8628       if (operands[1] != const0_rtx)
8629         operands[1] = force_reg (mode, operands[1]);
8630       if (operands[2] != const0_rtx)
8631         operands[2] = force_reg (mode, operands[2]);
8632     }
8633   switch (GET_CODE (operands[0]))
8634     {
8635     case LEU:
8636     case LE:
8637     case LTU:
8638     case LT:
8639       operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8640                                     VOIDmode, operands[2], operands[1]);
8641       operands[1] = XEXP (operands[0], 0);
8642       operands[2] = XEXP (operands[0], 1);
8643       break;
8644     default:
8645       operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8646                                     VOIDmode, operands[1], operands[2]);
8647       break;
8648     }
8649   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8652 (define_expand "cbranchfp4_media"
8653   [(set (pc)
8654         (if_then_else (match_operator 0 "sh_float_comparison_operator"
8655                        [(match_operand 1 "" "")
8656                         (match_operand 2 "" "")])
8657                       (match_operand 3 "" "")
8658                       (pc)))]
8659   "TARGET_SHMEDIA"
8661   rtx tmp = gen_reg_rtx (SImode);
8662   rtx cmp;
8663   if (GET_CODE (operands[0]) == NE)
8664     cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8665   else
8666     cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8667                           operands[1], operands[2]);
8669   emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8671   if (GET_CODE (cmp) == GET_CODE (operands[0]))
8672     operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8673   else
8674     operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8675   operands[1] = tmp;
8676   operands[2] = const0_rtx;
8677   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8680 (define_insn "*beq_media_i"
8681   [(set (pc)
8682         (if_then_else (match_operator 3 "equality_comparison_operator"
8683                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
8684                          (match_operand:DI 2 "arith_operand" "r,I06")])
8685                       (match_operand 0 "target_operand" "b,b")
8686                       (pc)))]
8687   "TARGET_SHMEDIA"
8688   "@
8689         b%o3%'  %1, %2, %0%>
8690         b%o3i%' %1, %2, %0%>"
8691   [(set_attr "type" "cbranch_media")])
8693 (define_insn "*beq_media_i32"
8694   [(set (pc)
8695         (if_then_else (match_operator 3 "equality_comparison_operator"
8696                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
8697                          (match_operand:SI 2 "arith_operand" "r,I06")])
8698                       (match_operand 0 "target_operand" "b,b")
8699                       (pc)))]
8700   "TARGET_SHMEDIA"
8701   "@
8702         b%o3%'  %1, %2, %0%>
8703         b%o3i%' %1, %2, %0%>"
8704   [(set_attr "type" "cbranch_media")])
8706 (define_insn "*bgt_media_i"
8707   [(set (pc)
8708         (if_then_else (match_operator 3 "greater_comparison_operator"
8709                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8710                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8711                       (match_operand 0 "target_operand" "b")
8712                       (pc)))]
8713   "TARGET_SHMEDIA"
8714   "b%o3%'       %N1, %N2, %0%>"
8715   [(set_attr "type" "cbranch_media")])
8717 (define_insn "*bgt_media_i32"
8718   [(set (pc)
8719         (if_then_else (match_operator 3 "greater_comparison_operator"
8720                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8721                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8722                       (match_operand 0 "target_operand" "b")
8723                       (pc)))]
8724   "TARGET_SHMEDIA"
8725   "b%o3%'       %N1, %N2, %0%>"
8726   [(set_attr "type" "cbranch_media")])
8728 ;; These are only needed to make invert_jump() happy - otherwise, jump
8729 ;; optimization will be silently disabled.
8730 (define_insn "*blt_media_i"
8731   [(set (pc)
8732         (if_then_else (match_operator 3 "less_comparison_operator"
8733                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8734                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8735                       (match_operand 0 "target_operand" "b")
8736                       (pc)))]
8737   "TARGET_SHMEDIA"
8738   "b%o3%'       %N2, %N1, %0%>"
8739   [(set_attr "type" "cbranch_media")])
8741 (define_insn "*blt_media_i32"
8742   [(set (pc)
8743         (if_then_else (match_operator 3 "less_comparison_operator"
8744                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8745                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8746                       (match_operand 0 "target_operand" "b")
8747                       (pc)))]
8748   "TARGET_SHMEDIA"
8749   "b%o3%'       %N2, %N1, %0%>"
8750   [(set_attr "type" "cbranch_media")])
8752 ;; combiner splitter for test-and-branch on single bit in register.  This
8753 ;; is endian dependent because the non-paradoxical subreg looks different
8754 ;; on big endian.
8755 (define_split
8756   [(set (pc)
8757         (if_then_else
8758           (match_operator 3 "equality_comparison_operator"
8759             [(subreg:SI
8760                (zero_extract:DI
8761                  (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
8762                  (const_int 1)
8763                  (match_operand 2 "const_int_operand" "")) 0)
8764              (const_int 0)])
8765           (match_operand 0 "target_operand" "")
8766           (pc)))
8767    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8768   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8769   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8770    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8772   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8773   operands[6] = (GET_CODE (operands[3]) == EQ
8774                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8775                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8778 ; operand 0 is the loop count pseudo register
8779 ; operand 1 is the label to jump to at the top of the loop
8780 (define_expand "doloop_end"
8781   [(parallel [(set (pc)
8782                    (if_then_else (ne:SI (match_operand:SI 0 "" "")
8783                                         (const_int 1))
8784                                  (label_ref (match_operand 1 "" ""))
8785                                  (pc)))
8786               (set (match_dup 0)
8787                    (plus:SI (match_dup 0) (const_int -1)))
8788               (clobber (reg:SI T_REG))])]
8789   "TARGET_SH2"
8791   if (GET_MODE (operands[0]) != SImode)
8792     FAIL;
8793   emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
8794   DONE;
8797 (define_insn_and_split "doloop_end_split"
8798   [(set (pc)
8799         (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
8800                              (const_int 1))
8801                       (label_ref (match_operand 1 "" ""))
8802                       (pc)))
8803    (set (match_operand:SI 0 "arith_reg_dest" "=r")
8804         (plus (match_dup 2) (const_int -1)))
8805    (clobber (reg:SI T_REG))]
8806   "TARGET_SH2"
8807   "#"
8808   ""
8809   [(parallel [(set (reg:SI T_REG)
8810                    (eq:SI (match_dup 2) (const_int 1)))
8811               (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8812    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8813                            (label_ref (match_dup 1))
8814                            (pc)))]
8815   ""
8816   [(set_attr "type" "cbranch")])
8818 ;; ------------------------------------------------------------------------
8819 ;; Jump and linkage insns
8820 ;; ------------------------------------------------------------------------
8822 (define_insn "jump_compact"
8823   [(set (pc)
8824         (label_ref (match_operand 0 "" "")))]
8825   "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
8827   /* The length is 16 if the delay slot is unfilled.  */
8828   if (get_attr_length(insn) > 4)
8829     return output_far_jump(insn, operands[0]);
8830   else
8831     return "bra %l0%#";
8833   [(set_attr "type" "jump")
8834    (set_attr "needs_delay_slot" "yes")])
8836 ;; ??? It would be much saner to explicitly use the scratch register
8837 ;; in the jump insn, and have indirect_jump_scratch only set it,
8838 ;; but fill_simple_delay_slots would refuse to do delay slot filling
8839 ;; from the target then, as it uses simplejump_p.
8840 ;;(define_insn "jump_compact_far"
8841 ;;  [(set (pc)
8842 ;;      (label_ref (match_operand 0 "" "")))
8843 ;;   (use (match_operand 1 "register_operand" "r")]
8844 ;;  "TARGET_SH1"
8845 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
8846 ;;  [(set_attr "type" "jump")
8847 ;;   (set_attr "needs_delay_slot" "yes")])
8849 (define_insn "jump_media"
8850   [(set (pc)
8851         (match_operand 0 "target_operand" "b"))]
8852   "TARGET_SHMEDIA"
8853   "blink        %0, r63%>"
8854   [(set_attr "type" "jump_media")])
8856 (define_expand "jump"
8857   [(set (pc)
8858         (label_ref (match_operand 0 "" "")))]
8859   ""
8861   if (TARGET_SH1)
8862     emit_jump_insn (gen_jump_compact (operands[0]));
8863   else if (TARGET_SHMEDIA)
8864     {
8865       if (reload_in_progress || reload_completed)
8866         FAIL;
8867       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
8868     }
8869   DONE;
8872 (define_insn "force_mode_for_call"
8873   [(use (reg:PSI FPSCR_REG))]
8874   "TARGET_SHCOMPACT"
8875   ""
8876   [(set_attr "length" "0")
8877    (set (attr "fp_mode")
8878         (if_then_else (eq_attr "fpu_single" "yes")
8879                       (const_string "single") (const_string "double")))])
8881 (define_insn "calli"
8882   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8883          (match_operand 1 "" ""))
8884    (use (reg:PSI FPSCR_REG))
8885    (clobber (reg:SI PR_REG))]
8886   "TARGET_SH1"
8888   if (TARGET_SH2A && (dbr_sequence_length () == 0))
8889     return "jsr/n       @%0";
8890   else
8891     return "jsr @%0%#";
8893   [(set_attr "type" "call")
8894    (set (attr "fp_mode")
8895         (if_then_else (eq_attr "fpu_single" "yes")
8896                       (const_string "single") (const_string "double")))
8897    (set_attr "needs_delay_slot" "yes")
8898    (set_attr "fp_set" "unknown")])
8900 ;; This is TBR relative jump instruction for SH2A architecture.
8901 ;; Its use is enabled by assigning an attribute "function_vector"
8902 ;; and the vector number to a function during its declaration.
8903 (define_insn "calli_tbr_rel"
8904   [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8905          (match_operand 1 "" ""))
8906    (use (reg:PSI FPSCR_REG))
8907    (clobber (reg:SI PR_REG))]
8908   "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8910   unsigned HOST_WIDE_INT vect_num;
8911   vect_num = sh2a_get_function_vector_number (operands[0]);
8912   operands[2] = GEN_INT (vect_num * 4);
8914   return "jsr/n @@(%O2,tbr)";
8916   [(set_attr "type" "call")
8917    (set (attr "fp_mode")
8918         (if_then_else (eq_attr "fpu_single" "yes")
8919                       (const_string "single") (const_string "double")))
8920    (set_attr "needs_delay_slot" "no")
8921    (set_attr "fp_set" "unknown")])
8923 ;; This is a pc-rel call, using bsrf, for use with PIC.
8924 (define_insn "calli_pcrel"
8925   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8926          (match_operand 1 "" ""))
8927    (use (reg:PSI FPSCR_REG))
8928    (use (reg:SI PIC_REG))
8929    (use (match_operand 2 "" ""))
8930    (clobber (reg:SI PR_REG))]
8931   "TARGET_SH2"
8933   return       "bsrf    %0"     "\n"
8934          "%O2:%#";
8936   [(set_attr "type" "call")
8937    (set (attr "fp_mode")
8938         (if_then_else (eq_attr "fpu_single" "yes")
8939                       (const_string "single") (const_string "double")))
8940    (set_attr "needs_delay_slot" "yes")
8941    (set_attr "fp_set" "unknown")])
8943 (define_insn_and_split "call_pcrel"
8944   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8945          (match_operand 1 "" ""))
8946    (use (reg:PSI FPSCR_REG))
8947    (use (reg:SI PIC_REG))
8948    (clobber (reg:SI PR_REG))
8949    (clobber (match_scratch:SI 2 "=r"))]
8950   "TARGET_SH2"
8951   "#"
8952   "reload_completed"
8953   [(const_int 0)]
8955   rtx lab = PATTERN (gen_call_site ());
8957   if (SYMBOL_REF_LOCAL_P (operands[0]))
8958     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8959   else
8960     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
8961   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
8962   DONE;
8964   [(set_attr "type" "call")
8965    (set (attr "fp_mode")
8966         (if_then_else (eq_attr "fpu_single" "yes")
8967                       (const_string "single") (const_string "double")))
8968    (set_attr "needs_delay_slot" "yes")
8969    (set_attr "fp_set" "unknown")])
8971 (define_insn "call_compact"
8972   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8973          (match_operand 1 "" ""))
8974    (match_operand 2 "immediate_operand" "n")
8975    (use (reg:SI R0_REG))
8976    (use (reg:SI R1_REG))
8977    (use (reg:PSI FPSCR_REG))
8978    (clobber (reg:SI PR_REG))]
8979   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8980   "jsr  @%0%#"
8981   [(set_attr "type" "call")
8982    (set (attr "fp_mode")
8983         (if_then_else (eq_attr "fpu_single" "yes")
8984                       (const_string "single") (const_string "double")))
8985    (set_attr "needs_delay_slot" "yes")])
8987 (define_insn "call_compact_rettramp"
8988   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8989          (match_operand 1 "" ""))
8990    (match_operand 2 "immediate_operand" "n")
8991    (use (reg:SI R0_REG))
8992    (use (reg:SI R1_REG))
8993    (use (reg:PSI FPSCR_REG))
8994    (clobber (reg:SI R10_REG))
8995    (clobber (reg:SI PR_REG))]
8996   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8997   "jsr  @%0%#"
8998   [(set_attr "type" "call")
8999    (set (attr "fp_mode")
9000         (if_then_else (eq_attr "fpu_single" "yes")
9001                       (const_string "single") (const_string "double")))
9002    (set_attr "needs_delay_slot" "yes")])
9004 (define_insn "call_media"
9005   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
9006          (match_operand 1 "" ""))
9007    (clobber (reg:DI PR_MEDIA_REG))]
9008   "TARGET_SHMEDIA"
9009   "blink        %0, r18"
9010   [(set_attr "type" "jump_media")])
9012 (define_insn "call_valuei"
9013   [(set (match_operand 0 "" "=rf")
9014         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9015               (match_operand 2 "" "")))
9016    (use (reg:PSI FPSCR_REG))
9017    (clobber (reg:SI PR_REG))]
9018   "TARGET_SH1"
9020   if (TARGET_SH2A && (dbr_sequence_length () == 0))
9021     return "jsr/n       @%1";
9022   else
9023     return "jsr @%1%#";
9025   [(set_attr "type" "call")
9026    (set (attr "fp_mode")
9027         (if_then_else (eq_attr "fpu_single" "yes")
9028                       (const_string "single") (const_string "double")))
9029    (set_attr "needs_delay_slot" "yes")
9030    (set_attr "fp_set" "unknown")])
9032 ;; This is TBR relative jump instruction for SH2A architecture.
9033 ;; Its use is enabled by assigning an attribute "function_vector"
9034 ;; and the vector number to a function during its declaration.
9035 (define_insn "call_valuei_tbr_rel"
9036   [(set (match_operand 0 "" "=rf")
9037         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9038               (match_operand 2 "" "")))
9039    (use (reg:PSI FPSCR_REG))
9040    (clobber (reg:SI PR_REG))]
9041   "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
9043   unsigned HOST_WIDE_INT vect_num;
9044   vect_num = sh2a_get_function_vector_number (operands[1]);
9045   operands[3] = GEN_INT (vect_num * 4);
9047   return "jsr/n @@(%O3,tbr)";
9049   [(set_attr "type" "call")
9050    (set (attr "fp_mode")
9051         (if_then_else (eq_attr "fpu_single" "yes")
9052                       (const_string "single") (const_string "double")))
9053    (set_attr "needs_delay_slot" "no")
9054    (set_attr "fp_set" "unknown")])
9056 (define_insn "call_valuei_pcrel"
9057   [(set (match_operand 0 "" "=rf")
9058         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9059               (match_operand 2 "" "")))
9060    (use (reg:PSI FPSCR_REG))
9061    (use (reg:SI PIC_REG))
9062    (use (match_operand 3 "" ""))
9063    (clobber (reg:SI PR_REG))]
9064   "TARGET_SH2"
9066   return       "bsrf    %1"     "\n"
9067          "%O3:%#";
9069   [(set_attr "type" "call")
9070    (set (attr "fp_mode")
9071         (if_then_else (eq_attr "fpu_single" "yes")
9072                       (const_string "single") (const_string "double")))
9073    (set_attr "needs_delay_slot" "yes")
9074    (set_attr "fp_set" "unknown")])
9076 (define_insn_and_split "call_value_pcrel"
9077   [(set (match_operand 0 "" "=rf")
9078         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9079               (match_operand 2 "" "")))
9080    (use (reg:PSI FPSCR_REG))
9081    (use (reg:SI PIC_REG))
9082    (clobber (reg:SI PR_REG))
9083    (clobber (match_scratch:SI 3 "=r"))]
9084   "TARGET_SH2"
9085   "#"
9086   "reload_completed"
9087   [(const_int 0)]
9089   rtx lab = PATTERN (gen_call_site ());
9091   if (SYMBOL_REF_LOCAL_P (operands[1]))
9092     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9093   else
9094     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
9095   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9096                                          operands[2], copy_rtx (lab)));
9097   DONE;
9099   [(set_attr "type" "call")
9100    (set (attr "fp_mode")
9101         (if_then_else (eq_attr "fpu_single" "yes")
9102                       (const_string "single") (const_string "double")))
9103    (set_attr "needs_delay_slot" "yes")
9104    (set_attr "fp_set" "unknown")])
9106 (define_insn "call_value_compact"
9107   [(set (match_operand 0 "" "=rf")
9108         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9109               (match_operand 2 "" "")))
9110    (match_operand 3 "immediate_operand" "n")
9111    (use (reg:SI R0_REG))
9112    (use (reg:SI R1_REG))
9113    (use (reg:PSI FPSCR_REG))
9114    (clobber (reg:SI PR_REG))]
9115   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9116   "jsr  @%1%#"
9117   [(set_attr "type" "call")
9118    (set (attr "fp_mode")
9119         (if_then_else (eq_attr "fpu_single" "yes")
9120                       (const_string "single") (const_string "double")))
9121    (set_attr "needs_delay_slot" "yes")])
9123 (define_insn "call_value_compact_rettramp"
9124   [(set (match_operand 0 "" "=rf")
9125         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9126               (match_operand 2 "" "")))
9127    (match_operand 3 "immediate_operand" "n")
9128    (use (reg:SI R0_REG))
9129    (use (reg:SI R1_REG))
9130    (use (reg:PSI FPSCR_REG))
9131    (clobber (reg:SI R10_REG))
9132    (clobber (reg:SI PR_REG))]
9133   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9134   "jsr  @%1%#"
9135   [(set_attr "type" "call")
9136    (set (attr "fp_mode")
9137         (if_then_else (eq_attr "fpu_single" "yes")
9138                       (const_string "single") (const_string "double")))
9139    (set_attr "needs_delay_slot" "yes")])
9141 (define_insn "call_value_media"
9142   [(set (match_operand 0 "" "=rf")
9143         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9144               (match_operand 2 "" "")))
9145    (clobber (reg:DI PR_MEDIA_REG))]
9146   "TARGET_SHMEDIA"
9147   "blink        %1, r18"
9148   [(set_attr "type" "jump_media")])
9150 (define_expand "call"
9151   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9152                             (match_operand 1 "" ""))
9153               (match_operand 2 "" "")
9154               (use (reg:PSI FPSCR_REG))
9155               (clobber (reg:SI PR_REG))])]
9156   ""
9158   if (TARGET_SHMEDIA)
9159     {
9160       operands[0] = shmedia_prepare_call_address (operands[0], 0);
9161       emit_call_insn (gen_call_media (operands[0], operands[1]));
9162       DONE;
9163     }
9164   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9165     {
9166       rtx cookie_rtx = operands[2];
9167       long cookie = INTVAL (cookie_rtx);
9168       rtx func = XEXP (operands[0], 0);
9169       rtx r0, r1;
9171       if (flag_pic)
9172         {
9173           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9174             {
9175               rtx reg = gen_reg_rtx (Pmode);
9177               emit_insn (gen_symGOTPLT2reg (reg, func));
9178               func = reg;
9179             }
9180           else
9181             func = legitimize_pic_address (func, Pmode, 0);
9182         }
9184       r0 = gen_rtx_REG (SImode, R0_REG);
9185       r1 = gen_rtx_REG (SImode, R1_REG);
9187       /* Since such a call function may use all call-clobbered
9188          registers, we force a mode switch earlier, so that we don't
9189          run out of registers when adjusting fpscr for the call.  */
9190       emit_insn (gen_force_mode_for_call ());
9192       operands[0]
9193         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9194       operands[0] = force_reg (SImode, operands[0]);
9196       emit_move_insn (r0, func);
9197       emit_move_insn (r1, cookie_rtx);
9199       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9200         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9201                                                    operands[2]));
9202       else
9203         emit_call_insn (gen_call_compact (operands[0], operands[1],
9204                                           operands[2]));
9206       DONE;
9207     }
9208   else if (TARGET_SHCOMPACT && flag_pic
9209            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9210            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9211     {
9212       rtx reg = gen_reg_rtx (Pmode);
9214       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9215       XEXP (operands[0], 0) = reg;
9216     }
9217   if (!flag_pic && TARGET_SH2A
9218       && MEM_P (operands[0])
9219       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9220     {
9221       if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9222         {
9223           emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9224                                              operands[1]));
9225           DONE;
9226         }
9227     }
9228   if (flag_pic && TARGET_SH2
9229       && MEM_P (operands[0])
9230       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9231     {
9232       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9233       DONE;
9234     }
9235   else
9236   {
9237     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9238     operands[1] = operands[2];
9239   }
9241   emit_call_insn (gen_calli (operands[0], operands[1]));
9242   DONE;
9245 (define_insn "call_pop_compact"
9246   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9247          (match_operand 1 "" ""))
9248    (match_operand 2 "immediate_operand" "n")
9249    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9250                                  (match_operand 3 "immediate_operand" "n")))
9251    (use (reg:SI R0_REG))
9252    (use (reg:SI R1_REG))
9253    (use (reg:PSI FPSCR_REG))
9254    (clobber (reg:SI PR_REG))]
9255   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9256   "jsr  @%0%#"
9257   [(set_attr "type" "call")
9258    (set (attr "fp_mode")
9259         (if_then_else (eq_attr "fpu_single" "yes")
9260                       (const_string "single") (const_string "double")))
9261    (set_attr "needs_delay_slot" "yes")])
9263 (define_insn "call_pop_compact_rettramp"
9264   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9265          (match_operand 1 "" ""))
9266    (match_operand 2 "immediate_operand" "n")
9267    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9268                                  (match_operand 3 "immediate_operand" "n")))
9269    (use (reg:SI R0_REG))
9270    (use (reg:SI R1_REG))
9271    (use (reg:PSI FPSCR_REG))
9272    (clobber (reg:SI R10_REG))
9273    (clobber (reg:SI PR_REG))]
9274   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9275   "jsr  @%0%#"
9276   [(set_attr "type" "call")
9277    (set (attr "fp_mode")
9278         (if_then_else (eq_attr "fpu_single" "yes")
9279                       (const_string "single") (const_string "double")))
9280    (set_attr "needs_delay_slot" "yes")])
9282 (define_expand "call_pop"
9283   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9284                     (match_operand 1 "" ""))
9285              (match_operand 2 "" "")
9286              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9287                                            (match_operand 3 "" "")))])]
9288   "TARGET_SHCOMPACT"
9290   rtx cookie_rtx;
9291   long cookie;
9292   rtx func;
9293   rtx r0, r1;
9295   gcc_assert (operands[2] && INTVAL (operands[2]));
9296   cookie_rtx = operands[2];
9297   cookie = INTVAL (cookie_rtx);
9298   func = XEXP (operands[0], 0);
9300   if (flag_pic)
9301     {
9302       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9303         {
9304           rtx reg = gen_reg_rtx (Pmode);
9305           emit_insn (gen_symGOTPLT2reg (reg, func));
9306           func = reg;
9307         }
9308       else
9309         func = legitimize_pic_address (func, Pmode, 0);
9310     }
9312   r0 = gen_rtx_REG (SImode, R0_REG);
9313   r1 = gen_rtx_REG (SImode, R1_REG);
9315   /* Since such a call function may use all call-clobbered
9316      registers, we force a mode switch earlier, so that we don't
9317      run out of registers when adjusting fpscr for the call.  */
9318   emit_insn (gen_force_mode_for_call ());
9320   operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9321                                  SFUNC_GOT);
9322   operands[0] = force_reg (SImode, operands[0]);
9324   emit_move_insn (r0, func);
9325   emit_move_insn (r1, cookie_rtx);
9327   if (cookie & CALL_COOKIE_RET_TRAMP (1))
9328     emit_call_insn (gen_call_pop_compact_rettramp
9329                      (operands[0], operands[1], operands[2], operands[3]));
9330   else
9331     emit_call_insn (gen_call_pop_compact
9332                      (operands[0], operands[1], operands[2], operands[3]));
9334   DONE;
9337 (define_expand "call_value"
9338   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9339                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9340                                  (match_operand 2 "" "")))
9341               (match_operand 3 "" "")
9342               (use (reg:PSI FPSCR_REG))
9343               (clobber (reg:SI PR_REG))])]
9344   ""
9346   if (TARGET_SHMEDIA)
9347     {
9348       operands[1] = shmedia_prepare_call_address (operands[1], 0);
9349       emit_call_insn (gen_call_value_media (operands[0], operands[1],
9350                                             operands[2]));
9351       DONE;
9352     }
9353   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9354     {
9355       rtx cookie_rtx = operands[3];
9356       long cookie = INTVAL (cookie_rtx);
9357       rtx func = XEXP (operands[1], 0);
9358       rtx r0, r1;
9360       if (flag_pic)
9361         {
9362           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9363             {
9364               rtx reg = gen_reg_rtx (Pmode);
9366               emit_insn (gen_symGOTPLT2reg (reg, func));
9367               func = reg;
9368             }
9369           else
9370             func = legitimize_pic_address (func, Pmode, 0);
9371         }
9373       r0 = gen_rtx_REG (SImode, R0_REG);
9374       r1 = gen_rtx_REG (SImode, R1_REG);
9376       /* Since such a call function may use all call-clobbered
9377          registers, we force a mode switch earlier, so that we don't
9378          run out of registers when adjusting fpscr for the call.  */
9379       emit_insn (gen_force_mode_for_call ());
9381       operands[1]
9382         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9383       operands[1] = force_reg (SImode, operands[1]);
9385       emit_move_insn (r0, func);
9386       emit_move_insn (r1, cookie_rtx);
9388       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9389         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9390                                                          operands[1],
9391                                                          operands[2],
9392                                                          operands[3]));
9393       else
9394         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9395                                                 operands[2], operands[3]));
9397       DONE;
9398     }
9399   else if (TARGET_SHCOMPACT && flag_pic
9400            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9401            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9402     {
9403       rtx reg = gen_reg_rtx (Pmode);
9405       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9406       XEXP (operands[1], 0) = reg;
9407     }
9408   if (!flag_pic && TARGET_SH2A
9409       && MEM_P (operands[1])
9410       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9411     {
9412       if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9413         {
9414           emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9415                                  XEXP (operands[1], 0), operands[2]));
9416           DONE;
9417         }
9418     }
9419   if (flag_pic && TARGET_SH2
9420       && MEM_P (operands[1])
9421       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9422     {
9423       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9424                                             operands[2]));
9425       DONE;
9426     }
9427   else
9428     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9430   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9431   DONE;
9434 (define_insn "sibcalli"
9435   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9436          (match_operand 1 "" ""))
9437    (use (reg:PSI FPSCR_REG))
9438    (return)]
9439   "TARGET_SH1"
9440   "jmp  @%0%#"
9441   [(set_attr "needs_delay_slot" "yes")
9442    (set (attr "fp_mode")
9443         (if_then_else (eq_attr "fpu_single" "yes")
9444                       (const_string "single") (const_string "double")))
9445    (set_attr "type" "jump_ind")])
9447 (define_insn "sibcalli_pcrel"
9448   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9449          (match_operand 1 "" ""))
9450    (use (match_operand 2 "" ""))
9451    (use (reg:PSI FPSCR_REG))
9452    (return)]
9453   "TARGET_SH2"
9455   return       "braf    %0"     "\n"
9456          "%O2:%#";
9458   [(set_attr "needs_delay_slot" "yes")
9459    (set (attr "fp_mode")
9460         (if_then_else (eq_attr "fpu_single" "yes")
9461                       (const_string "single") (const_string "double")))
9462    (set_attr "type" "jump_ind")])
9464 ;; This uses an unspec to describe that the symbol_ref is very close.
9465 (define_insn "sibcalli_thunk"
9466   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9467                              UNSPEC_THUNK))
9468          (match_operand 1 "" ""))
9469    (use (reg:PSI FPSCR_REG))
9470    (return)]
9471   "TARGET_SH1"
9472   "bra  %O0"
9473   [(set_attr "needs_delay_slot" "yes")
9474    (set (attr "fp_mode")
9475         (if_then_else (eq_attr "fpu_single" "yes")
9476                       (const_string "single") (const_string "double")))
9477    (set_attr "type" "jump")
9478    (set_attr "length" "2")])
9480 (define_insn_and_split "sibcall_pcrel"
9481   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9482          (match_operand 1 "" ""))
9483    (use (reg:PSI FPSCR_REG))
9484    (clobber (match_scratch:SI 2 "=k"))
9485    (return)]
9486   "TARGET_SH2"
9487   "#"
9488   "reload_completed"
9489   [(const_int 0)]
9491   rtx lab = PATTERN (gen_call_site ());
9492   rtx call_insn;
9494   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9495   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9496                                                   copy_rtx (lab)));
9497   SIBLING_CALL_P (call_insn) = 1;
9498   DONE;
9500   [(set_attr "needs_delay_slot" "yes")
9501    (set (attr "fp_mode")
9502         (if_then_else (eq_attr "fpu_single" "yes")
9503                       (const_string "single") (const_string "double")))
9504    (set_attr "type" "jump_ind")])
9506 (define_insn "sibcall_compact"
9507   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9508          (match_operand 1 "" ""))
9509    (return)
9510    (use (match_operand:SI 2 "register_operand" "z,x"))
9511    (use (reg:SI R1_REG))
9512    (use (reg:PSI FPSCR_REG))
9513    ;; We want to make sure the `x' above will only match MACH_REG
9514    ;; because sibcall_epilogue may clobber MACL_REG.
9515    (clobber (reg:SI MACL_REG))]
9516   "TARGET_SHCOMPACT"
9518   static const char* alt[] =
9519   {
9520        "jmp     @%0%#",
9522        "jmp     @%0"    "\n"
9523     "   sts     %2,r0"
9524   };
9525   return alt[which_alternative];
9527   [(set_attr "needs_delay_slot" "yes,no")
9528    (set_attr "length" "2,4")
9529    (set (attr "fp_mode") (const_string "single"))
9530    (set_attr "type" "jump_ind")])
9532 (define_insn "sibcall_media"
9533   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9534          (match_operand 1 "" ""))
9535    (use (reg:SI PR_MEDIA_REG))
9536    (return)]
9537   "TARGET_SHMEDIA"
9538   "blink        %0, r63"
9539   [(set_attr "type" "jump_media")])
9541 (define_expand "sibcall"
9542   [(parallel
9543     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9544            (match_operand 1 "" ""))
9545      (match_operand 2 "" "")
9546      (use (reg:PSI FPSCR_REG))
9547      (return)])]
9548   ""
9550   if (TARGET_SHMEDIA)
9551     {
9552       operands[0] = shmedia_prepare_call_address (operands[0], 1);
9553       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9554       DONE;
9555     }
9556   else if (TARGET_SHCOMPACT && operands[2]
9557            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9558     {
9559       rtx cookie_rtx = operands[2];
9560       long cookie = INTVAL (cookie_rtx);
9561       rtx func = XEXP (operands[0], 0);
9562       rtx mach, r1;
9564       if (flag_pic)
9565         {
9566           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9567             {
9568               rtx reg = gen_reg_rtx (Pmode);
9570               emit_insn (gen_symGOT2reg (reg, func));
9571               func = reg;
9572             }
9573           else
9574             func = legitimize_pic_address (func, Pmode, 0);
9575         }
9577       /* FIXME: if we could tell whether all argument registers are
9578          already taken, we could decide whether to force the use of
9579          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9580          simple way to tell.  We could use the CALL_COOKIE, but we
9581          can't currently tell a register used for regular argument
9582          passing from one that is unused.  If we leave it up to reload
9583          to decide which register to use, it seems to always choose
9584          R0_REG, which leaves no available registers in SIBCALL_REGS
9585          to hold the address of the trampoline.  */
9586       mach = gen_rtx_REG (SImode, MACH_REG);
9587       r1 = gen_rtx_REG (SImode, R1_REG);
9589       /* Since such a call function may use all call-clobbered
9590          registers, we force a mode switch earlier, so that we don't
9591          run out of registers when adjusting fpscr for the call.  */
9592       emit_insn (gen_force_mode_for_call ());
9594       operands[0]
9595         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9596       operands[0] = force_reg (SImode, operands[0]);
9598       /* We don't need a return trampoline, since the callee will
9599          return directly to the upper caller.  */
9600       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9601         {
9602           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9603           cookie_rtx = GEN_INT (cookie);
9604         }
9606       emit_move_insn (mach, func);
9607       emit_move_insn (r1, cookie_rtx);
9609       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9610       DONE;
9611     }
9612   else if (TARGET_SHCOMPACT && flag_pic
9613            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9614            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9615     {
9616       rtx reg = gen_reg_rtx (Pmode);
9618       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9619       XEXP (operands[0], 0) = reg;
9620     }
9621   if (flag_pic && TARGET_SH2
9622       && MEM_P (operands[0])
9623       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9624       /* The PLT needs the PIC register, but the epilogue would have
9625          to restore it, so we can only use PC-relative PIC calls for
9626          static functions.  */
9627       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9628     {
9629       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9630       DONE;
9631     }
9632   else
9633     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9635   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9636   DONE;
9639 (define_insn "sibcall_valuei"
9640   [(set (match_operand 0 "" "=rf")
9641         (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9642               (match_operand 2 "" "")))
9643    (use (reg:PSI FPSCR_REG))
9644    (return)]
9645   "TARGET_SH1"
9646   "jmp  @%1%#"
9647   [(set_attr "needs_delay_slot" "yes")
9648    (set (attr "fp_mode")
9649         (if_then_else (eq_attr "fpu_single" "yes")
9650                       (const_string "single") (const_string "double")))
9651    (set_attr "type" "jump_ind")])
9653 (define_insn "sibcall_valuei_pcrel"
9654   [(set (match_operand 0 "" "=rf")
9655         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9656               (match_operand 2 "" "")))
9657    (use (match_operand 3 "" ""))
9658    (use (reg:PSI FPSCR_REG))
9659    (return)]
9660   "TARGET_SH2"
9662   return       "braf    %1"     "\n"
9663          "%O3:%#";
9665   [(set_attr "needs_delay_slot" "yes")
9666    (set (attr "fp_mode")
9667         (if_then_else (eq_attr "fpu_single" "yes")
9668                       (const_string "single") (const_string "double")))
9669    (set_attr "type" "jump_ind")])
9671 (define_insn_and_split "sibcall_value_pcrel"
9672   [(set (match_operand 0 "" "=rf")
9673         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9674               (match_operand 2 "" "")))
9675    (use (reg:PSI FPSCR_REG))
9676    (clobber (match_scratch:SI 3 "=k"))
9677    (return)]
9678   "TARGET_SH2"
9679   "#"
9680   "reload_completed"
9681   [(const_int 0)]
9683   rtx lab = PATTERN (gen_call_site ());
9684   rtx call_insn;
9686   emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9687   call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9688                                                         operands[3],
9689                                                         operands[2],
9690                                                         copy_rtx (lab)));
9691   SIBLING_CALL_P (call_insn) = 1;
9692   DONE;
9694   [(set_attr "needs_delay_slot" "yes")
9695    (set (attr "fp_mode")
9696         (if_then_else (eq_attr "fpu_single" "yes")
9697                       (const_string "single") (const_string "double")))
9698    (set_attr "type" "jump_ind")])
9700 (define_insn "sibcall_value_compact"
9701   [(set (match_operand 0 "" "=rf,rf")
9702         (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9703               (match_operand 2 "" "")))
9704    (return)
9705    (use (match_operand:SI 3 "register_operand" "z,x"))
9706    (use (reg:SI R1_REG))
9707    (use (reg:PSI FPSCR_REG))
9708    ;; We want to make sure the `x' above will only match MACH_REG
9709    ;; because sibcall_epilogue may clobber MACL_REG.
9710    (clobber (reg:SI MACL_REG))]
9711   "TARGET_SHCOMPACT"
9713   static const char* alt[] =
9714   {
9715        "jmp     @%1%#",
9717        "jmp     @%1"    "\n"
9718     "   sts     %3,r0"
9719   };
9720   return alt[which_alternative];
9722   [(set_attr "needs_delay_slot" "yes,no")
9723    (set_attr "length" "2,4")
9724    (set (attr "fp_mode") (const_string "single"))
9725    (set_attr "type" "jump_ind")])
9727 (define_insn "sibcall_value_media"
9728   [(set (match_operand 0 "" "=rf")
9729         (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9730               (match_operand 2 "" "")))
9731    (use (reg:SI PR_MEDIA_REG))
9732    (return)]
9733   "TARGET_SHMEDIA"
9734   "blink        %1, r63"
9735   [(set_attr "type" "jump_media")])
9737 (define_expand "sibcall_value"
9738   [(parallel
9739     [(set (match_operand 0 "arith_reg_operand" "")
9740           (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9741                 (match_operand 2 "" "")))
9742      (match_operand 3 "" "")
9743      (use (reg:PSI FPSCR_REG))
9744      (return)])]
9745   ""
9747   if (TARGET_SHMEDIA)
9748     {
9749       operands[1] = shmedia_prepare_call_address (operands[1], 1);
9750       emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9751                                                operands[2]));
9752       DONE;
9753     }
9754   else if (TARGET_SHCOMPACT && operands[3]
9755            && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9756     {
9757       rtx cookie_rtx = operands[3];
9758       long cookie = INTVAL (cookie_rtx);
9759       rtx func = XEXP (operands[1], 0);
9760       rtx mach, r1;
9762       if (flag_pic)
9763         {
9764           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9765             {
9766               rtx reg = gen_reg_rtx (Pmode);
9768               emit_insn (gen_symGOT2reg (reg, func));
9769               func = reg;
9770             }
9771           else
9772             func = legitimize_pic_address (func, Pmode, 0);
9773         }
9775       /* FIXME: if we could tell whether all argument registers are
9776          already taken, we could decide whether to force the use of
9777          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9778          simple way to tell.  We could use the CALL_COOKIE, but we
9779          can't currently tell a register used for regular argument
9780          passing from one that is unused.  If we leave it up to reload
9781          to decide which register to use, it seems to always choose
9782          R0_REG, which leaves no available registers in SIBCALL_REGS
9783          to hold the address of the trampoline.  */
9784       mach = gen_rtx_REG (SImode, MACH_REG);
9785       r1 = gen_rtx_REG (SImode, R1_REG);
9787       /* Since such a call function may use all call-clobbered
9788          registers, we force a mode switch earlier, so that we don't
9789          run out of registers when adjusting fpscr for the call.  */
9790       emit_insn (gen_force_mode_for_call ());
9792       operands[1]
9793         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9794       operands[1] = force_reg (SImode, operands[1]);
9796       /* We don't need a return trampoline, since the callee will
9797          return directly to the upper caller.  */
9798       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9799         {
9800           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9801           cookie_rtx = GEN_INT (cookie);
9802         }
9804       emit_move_insn (mach, func);
9805       emit_move_insn (r1, cookie_rtx);
9807       emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9808                                                  operands[2], mach));
9809       DONE;
9810     }
9811   else if (TARGET_SHCOMPACT && flag_pic
9812            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9813            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9814     {
9815       rtx reg = gen_reg_rtx (Pmode);
9817       emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9818       XEXP (operands[1], 0) = reg;
9819     }
9820   if (flag_pic && TARGET_SH2
9821       && MEM_P (operands[1])
9822       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9823       /* The PLT needs the PIC register, but the epilogue would have
9824          to restore it, so we can only use PC-relative PIC calls for
9825          static functions.  */
9826       && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9827     {
9828       emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9829                                                XEXP (operands[1], 0),
9830                                                operands[2]));
9831       DONE;
9832     }
9833   else
9834     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9836   emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9837   DONE;
9840 (define_insn "call_value_pop_compact"
9841   [(set (match_operand 0 "" "=rf")
9842         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9843               (match_operand 2 "" "")))
9844    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9845                                  (match_operand 4 "immediate_operand" "n")))
9846    (match_operand 3 "immediate_operand" "n")
9847    (use (reg:SI R0_REG))
9848    (use (reg:SI R1_REG))
9849    (use (reg:PSI FPSCR_REG))
9850    (clobber (reg:SI PR_REG))]
9851   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9852   "jsr  @%1%#"
9853   [(set_attr "type" "call")
9854    (set (attr "fp_mode")
9855         (if_then_else (eq_attr "fpu_single" "yes")
9856                       (const_string "single") (const_string "double")))
9857    (set_attr "needs_delay_slot" "yes")])
9859 (define_insn "call_value_pop_compact_rettramp"
9860   [(set (match_operand 0 "" "=rf")
9861         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9862               (match_operand 2 "" "")))
9863    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9864                                  (match_operand 4 "immediate_operand" "n")))
9865    (match_operand 3 "immediate_operand" "n")
9866    (use (reg:SI R0_REG))
9867    (use (reg:SI R1_REG))
9868    (use (reg:PSI FPSCR_REG))
9869    (clobber (reg:SI R10_REG))
9870    (clobber (reg:SI PR_REG))]
9871   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9872   "jsr  @%1%#"
9873   [(set_attr "type" "call")
9874    (set (attr "fp_mode")
9875         (if_then_else (eq_attr "fpu_single" "yes")
9876                       (const_string "single") (const_string "double")))
9877    (set_attr "needs_delay_slot" "yes")])
9879 (define_expand "call_value_pop"
9880   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9881                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9882                                  (match_operand 2 "" "")))
9883               (match_operand 3 "" "")
9884               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9885                                             (match_operand 4 "" "")))])]
9886   "TARGET_SHCOMPACT"
9888   rtx cookie_rtx;
9889   long cookie;
9890   rtx func;
9891   rtx r0, r1;
9893   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9894   cookie_rtx = operands[3];
9895   cookie = INTVAL (cookie_rtx);
9896   func = XEXP (operands[1], 0);
9898   if (flag_pic)
9899     {
9900       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9901         {
9902           rtx reg = gen_reg_rtx (Pmode);
9904           emit_insn (gen_symGOTPLT2reg (reg, func));
9905           func = reg;
9906         }
9907       else
9908         func = legitimize_pic_address (func, Pmode, 0);
9909     }
9911   r0 = gen_rtx_REG (SImode, R0_REG);
9912   r1 = gen_rtx_REG (SImode, R1_REG);
9914   /* Since such a call function may use all call-clobbered
9915      registers, we force a mode switch earlier, so that we don't
9916      run out of registers when adjusting fpscr for the call.  */
9917   emit_insn (gen_force_mode_for_call ());
9919   operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9920                                  SFUNC_GOT);
9921   operands[1] = force_reg (SImode, operands[1]);
9923   emit_move_insn (r0, func);
9924   emit_move_insn (r1, cookie_rtx);
9926   if (cookie & CALL_COOKIE_RET_TRAMP (1))
9927     emit_call_insn (gen_call_value_pop_compact_rettramp
9928                         (operands[0], operands[1], operands[2],
9929                          operands[3], operands[4]));
9930   else
9931     emit_call_insn (gen_call_value_pop_compact
9932                         (operands[0], operands[1], operands[2],
9933                          operands[3], operands[4]));
9935   DONE;
9938 (define_expand "sibcall_epilogue"
9939   [(return)]
9940   ""
9942   sh_expand_epilogue (true);
9943   if (TARGET_SHCOMPACT)
9944     {
9945       rtx insn, set;
9947       /* If epilogue clobbers r0, preserve it in macl.  */
9948       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9949         if ((set = single_set (insn))
9950             && REG_P (SET_DEST (set))
9951             && REGNO (SET_DEST (set)) == R0_REG)
9952           {
9953             rtx r0 = gen_rtx_REG (SImode, R0_REG);
9954             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
9956             /* We can't tell at this point whether the sibcall is a
9957                sibcall_compact and, if it is, whether it uses r0 or
9958                mach as operand 2, so let the instructions that
9959                preserve r0 be optimized away if r0 turns out to be
9960                dead.  */
9961             emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9962             emit_move_insn (r0, tmp);
9963             break;
9964           }
9965     }
9966   DONE;
9969 (define_insn "indirect_jump_compact"
9970   [(set (pc)
9971         (match_operand:SI 0 "arith_reg_operand" "r"))]
9972   "TARGET_SH1"
9973   "jmp  @%0%#"
9974   [(set_attr "needs_delay_slot" "yes")
9975    (set_attr "type" "jump_ind")])
9977 (define_expand "indirect_jump"
9978   [(set (pc)
9979         (match_operand 0 "register_operand" ""))]
9980   ""
9982   if (GET_MODE (operands[0]) != Pmode)
9983     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
9986 ;; The use of operand 1 / 2 helps us distinguish case table jumps
9987 ;; which can be present in structured code from indirect jumps which can not
9988 ;; be present in structured code.  This allows -fprofile-arcs to work.
9990 ;; For SH1 processors.
9991 (define_insn "casesi_jump_1"
9992   [(set (pc)
9993         (match_operand:SI 0 "register_operand" "r"))
9994    (use (label_ref (match_operand 1 "" "")))]
9995   "TARGET_SH1"
9996   "jmp  @%0%#"
9997   [(set_attr "needs_delay_slot" "yes")
9998    (set_attr "type" "jump_ind")])
10000 ;; For all later processors.
10001 (define_insn "casesi_jump_2"
10002   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
10003                       (label_ref (match_operand 1 "" ""))))
10004    (use (label_ref (match_operand 2 "" "")))]
10005   "TARGET_SH2
10006    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
10007   "braf %0%#"
10008   [(set_attr "needs_delay_slot" "yes")
10009    (set_attr "type" "jump_ind")])
10011 (define_insn "casesi_jump_media"
10012   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
10013    (use (label_ref (match_operand 1 "" "")))]
10014   "TARGET_SHMEDIA"
10015   "blink        %0, r63"
10016   [(set_attr "type" "jump_media")])
10018 ;; Call subroutine returning any type.
10019 ;; ??? This probably doesn't work.
10020 (define_expand "untyped_call"
10021   [(parallel [(call (match_operand 0 "" "")
10022                     (const_int 0))
10023               (match_operand 1 "" "")
10024               (match_operand 2 "" "")])]
10025   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
10027   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
10029   for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10030     {
10031       rtx set = XVECEXP (operands[2], 0, i);
10032       emit_move_insn (SET_DEST (set), SET_SRC (set));
10033     }
10035   /* The optimizer does not know that the call sets the function value
10036      registers we stored in the result block.  We avoid problems by
10037      claiming that all hard registers are used and clobbered at this
10038      point.  */
10039   emit_insn (gen_blockage ());
10041   DONE;
10044 ;; ------------------------------------------------------------------------
10045 ;; Misc insns
10046 ;; ------------------------------------------------------------------------
10048 (define_insn "dect"
10049   [(set (reg:SI T_REG)
10050         (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
10051    (set (match_operand:SI 0 "arith_reg_dest" "=r")
10052         (plus:SI (match_dup 1) (const_int -1)))]
10053   "TARGET_SH2"
10054   "dt   %0"
10055   [(set_attr "type" "arith")])
10057 (define_insn "nop"
10058   [(const_int 0)]
10059   ""
10060   "nop")
10062 ;; Load address of a label. This is only generated by the casesi expand,
10063 ;; and by machine_dependent_reorg (fixing up fp moves).
10064 ;; This must use unspec, because this only works for labels that are
10065 ;; within range.
10066 (define_insn "mova"
10067   [(set (reg:SI R0_REG)
10068         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
10069   "TARGET_SH1"
10070   "mova %O0,r0"
10071   [(set_attr "in_delay_slot" "no")
10072    (set_attr "type" "arith")])
10074 ;; machine_dependent_reorg will make this a `mova'.
10075 (define_insn "mova_const"
10076   [(set (reg:SI R0_REG)
10077         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
10078   "TARGET_SH1"
10079   "#"
10080   [(set_attr "in_delay_slot" "no")
10081    (set_attr "type" "arith")])
10083 (define_expand "GOTaddr2picreg"
10084   [(set (reg:SI R0_REG)
10085         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
10086                    UNSPEC_MOVA))
10087    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
10088    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10089   ""
10091   if (TARGET_VXWORKS_RTP)
10092     {
10093       rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10094       rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10095       emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10096       DONE;
10097     }
10099   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
10100   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10102   if (TARGET_SHMEDIA)
10103     {
10104       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10105       rtx pic = operands[0];
10106       rtx lab = PATTERN (gen_call_site ());
10107       rtx insn, equiv;
10109       equiv = operands[1];
10110       operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
10111                                     UNSPEC_PCREL_SYMOFF);
10112       operands[1] = gen_rtx_CONST (Pmode, operands[1]);
10114       if (Pmode == SImode)
10115         {
10116           emit_insn (gen_movsi_const (pic, operands[1]));
10117           emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10118         }
10119       else
10120         {
10121           emit_insn (gen_movdi_const (pic, operands[1]));
10122           emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10123         }
10125       insn = emit_move_insn (operands[0], tr);
10127       set_unique_reg_note (insn, REG_EQUAL, equiv);
10129       DONE;
10130     }
10133 ;; A helper for GOTaddr2picreg to finish up the initialization of the
10134 ;; PIC register.
10135 (define_expand "vxworks_picreg"
10136   [(set (reg:SI PIC_REG)
10137         (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10138    (set (reg:SI R0_REG)
10139         (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10140    (set (reg:SI PIC_REG)
10141         (mem:SI (reg:SI PIC_REG)))
10142    (set (reg:SI PIC_REG)
10143         (mem:SI (plus:SI (reg:SI PIC_REG)
10144                          (reg:SI R0_REG))))]
10145   "TARGET_VXWORKS_RTP")
10147 (define_insn "*ptb"
10148   [(set (match_operand 0 "target_reg_operand" "=b")
10149         (const (unspec [(match_operand 1 "" "Csy")]
10150                              UNSPEC_DATALABEL)))]
10151   "TARGET_SHMEDIA && flag_pic
10152    && satisfies_constraint_Csy (operands[1])"
10153   "ptb/u        datalabel %1, %0"
10154   [(set_attr "type" "ptabs_media")
10155    (set_attr "length" "*")])
10157 (define_insn "ptrel_si"
10158   [(set (match_operand:SI 0 "target_reg_operand" "=b")
10159         (plus:SI (match_operand:SI 1 "register_operand" "r")
10160               (pc)))
10161    (match_operand:SI 2 "" "")]
10162   "TARGET_SHMEDIA"
10163   "%O2: ptrel/u %1, %0"
10164   [(set_attr "type" "ptabs_media")])
10166 (define_insn "ptrel_di"
10167   [(set (match_operand:DI 0 "target_reg_operand" "=b")
10168         (plus:DI (match_operand:DI 1 "register_operand" "r")
10169               (pc)))
10170    (match_operand:DI 2 "" "")]
10171   "TARGET_SHMEDIA"
10172   "%O2: ptrel/u %1, %0"
10173   [(set_attr "type" "ptabs_media")])
10175 (define_expand "builtin_setjmp_receiver"
10176   [(match_operand 0 "" "")]
10177   "flag_pic"
10179   emit_insn (gen_GOTaddr2picreg ());
10180   DONE;
10183 (define_expand "call_site"
10184   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10185   "TARGET_SH1"
10187   static HOST_WIDE_INT i = 0;
10188   operands[0] = GEN_INT (i);
10189   i++;
10192 ;; op0 = op1 + r12 but hide it before reload completed.  See the comment
10193 ;; in symGOT_load expand.
10194 (define_insn_and_split "chk_guard_add"
10195   [(set (match_operand:SI 0 "register_operand" "=&r")
10196         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10197                     (reg:SI PIC_REG)]
10198                    UNSPEC_CHKADD))]
10199   "TARGET_SH1"
10200   "#"
10201   "TARGET_SH1 && reload_completed"
10202   [(set (match_dup 0) (reg:SI PIC_REG))
10203    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10204   ""
10205   [(set_attr "type" "arith")])
10207 (define_expand "sym_label2reg"
10208   [(set (match_operand:SI 0 "" "")
10209         (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10210                               (const (plus:SI (match_operand:SI 2 "" "")
10211                                               (const_int 2)))]
10212                              UNSPEC_SYMOFF)))]
10213   "TARGET_SH1" "")
10215 (define_expand "symGOT_load"
10216   [(set (match_dup 2) (match_operand 1 "" ""))
10217    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10218    (set (match_operand 0 "" "") (mem (match_dup 3)))]
10219   ""
10221   rtx mem;
10223   operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10224   operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10226   if (TARGET_SHMEDIA)
10227     {
10228       rtx reg = operands[2];
10230       if (Pmode == DImode)
10231         {      
10232           if (flag_pic > 1)
10233             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10234           else
10235             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10236         }
10237       else
10238         {
10239           if (flag_pic > 1)
10240             emit_insn (gen_movsi_const (reg, operands[1]));
10241           else
10242             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10243         }
10244     }
10245   else
10246     emit_move_insn (operands[2], operands[1]);
10248   /* When stack protector inserts codes after the result is set to
10249      R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
10250      insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10251      when rX is a GOT address for the guard symbol.  Ugly but doesn't
10252      matter because this is a rare situation.  */
10253   if (!TARGET_SHMEDIA
10254       && flag_stack_protect
10255       && GET_CODE (operands[1]) == CONST
10256       && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10257       && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10258       && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10259                  "__stack_chk_guard") == 0)
10260     emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10261   else
10262     emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10263                                                gen_rtx_REG (Pmode, PIC_REG)));
10265   /* N.B. This is not constant for a GOTPLT relocation.  */
10266   mem = gen_rtx_MEM (Pmode, operands[3]);
10267   MEM_NOTRAP_P (mem) = 1;
10268   /* ??? Should we have a special alias set for the GOT?  */
10269   emit_move_insn (operands[0], mem);
10271   DONE;
10274 (define_expand "sym2GOT"
10275   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10276   ""
10277   "")
10279 (define_expand "symGOT2reg"
10280   [(match_operand 0 "" "") (match_operand 1 "" "")]
10281   ""
10283   rtx gotsym, insn;
10285   gotsym = gen_sym2GOT (operands[1]);
10286   PUT_MODE (gotsym, Pmode);
10287   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10289   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10291   DONE;
10294 (define_expand "symGOTPLT2reg"
10295   [(match_operand 0 "" "") (match_operand 1 "" "")]
10296   ""
10298   rtx pltsym = gen_rtx_CONST (Pmode,
10299                               gen_rtx_UNSPEC (Pmode,
10300                                               gen_rtvec (1, operands[1]),
10301                                               UNSPEC_GOTPLT));
10302   emit_insn (gen_symGOT_load (operands[0], pltsym));
10303   DONE;
10306 (define_expand "sym2GOTOFF"
10307   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10308   ""
10309   "")
10311 (define_expand "symGOTOFF2reg"
10312   [(match_operand 0 "" "") (match_operand 1 "" "")]
10313   ""
10315   rtx gotoffsym, insn;
10316   rtx t = (!can_create_pseudo_p ()
10317            ? operands[0]
10318            : gen_reg_rtx (GET_MODE (operands[0])));
10320   gotoffsym = gen_sym2GOTOFF (operands[1]);
10321   PUT_MODE (gotoffsym, Pmode);
10322   emit_move_insn (t, gotoffsym);
10323   insn = emit_move_insn (operands[0],
10324                          gen_rtx_PLUS (Pmode, t,
10325                                        gen_rtx_REG (Pmode, PIC_REG)));
10327   set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10329   DONE;
10332 (define_expand "symPLT_label2reg"
10333   [(set (match_operand:SI 0 "" "")
10334         (const:SI
10335          (unspec:SI
10336           [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10337            (const:SI (plus:SI (match_operand:SI 2 "" "")
10338                               (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10339    ;; Even though the PIC register is not really used by the call
10340    ;; sequence in which this is expanded, the PLT code assumes the PIC
10341    ;; register is set, so we must not skip its initialization.  Since
10342    ;; we only use this expand as part of calling sequences, and never
10343    ;; to take the address of a function, this is the best point to
10344    ;; insert the (use).  Using the PLT to take the address of a
10345    ;; function would be wrong, not only because the PLT entry could
10346    ;; then be called from a function that doesn't initialize the PIC
10347    ;; register to the proper GOT, but also because pointers to the
10348    ;; same function might not compare equal, should they be set by
10349    ;; different shared libraries.
10350    (use (reg:SI PIC_REG))]
10351   "TARGET_SH1"
10352   "")
10354 (define_expand "sym2PIC"
10355   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10356   ""
10357   "")
10359 ;; -------------------------------------------------------------------------
10360 ;; TLS code generation.
10362 ;; FIXME: The multi-insn asm blocks should be converted to use
10363 ;; define_insn_and_split.
10364 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10365 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10366 ;; for details.
10368 (define_insn "tls_global_dynamic"
10369   [(set (match_operand:SI 0 "register_operand" "=&z")
10370         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10371                                   UNSPEC_TLSGD))
10372               (const_int 0)))
10373    (use (reg:PSI FPSCR_REG))
10374    (use (reg:SI PIC_REG))
10375    (clobber (reg:SI PR_REG))
10376    (clobber (scratch:SI))]
10377   "TARGET_SH1"
10379   return       "mov.l   1f,r4"                  "\n"
10380          "      mova    2f,r0"                  "\n"
10381          "      mov.l   2f,r1"                  "\n"
10382          "      add     r0,r1"                  "\n"
10383          "      jsr     @r1"                    "\n"
10384          "      add     r12,r4"                 "\n"
10385          "      bra     3f"                     "\n"
10386          "      nop"                            "\n"
10387          "      .align  2"                      "\n"
10388          "1:    .long   %a1@TLSGD"              "\n"
10389          "2:    .long   __tls_get_addr@PLT"     "\n"
10390          "3:";
10392   [(set_attr "type" "tls_load")
10393    (set_attr "length" "26")])
10395 (define_insn "tls_local_dynamic"
10396   [(set (match_operand:SI 0 "register_operand" "=&z")
10397         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10398                                   UNSPEC_TLSLDM))
10399               (const_int 0)))
10400    (use (reg:PSI FPSCR_REG))
10401    (use (reg:SI PIC_REG))
10402    (clobber (reg:SI PR_REG))
10403    (clobber (scratch:SI))]
10404   "TARGET_SH1"
10406   return       "mov.l   1f,r4"                  "\n"
10407          "      mova    2f,r0"                  "\n"
10408          "      mov.l   2f,r1"                  "\n"
10409          "      add     r0,r1"                  "\n"
10410          "      jsr     @r1"                    "\n"
10411          "      add     r12,r4"                 "\n"
10412          "      bra     3f"                     "\n"
10413          "      nop"                            "\n"
10414          "      .align  2"                      "\n"
10415          "1:    .long   %a1@TLSLDM"             "\n"
10416          "2:    .long   __tls_get_addr@PLT"     "\n"
10417          "3:";
10419   [(set_attr "type" "tls_load")
10420    (set_attr "length" "26")])
10422 (define_expand "sym2DTPOFF"
10423   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10424   ""
10425   "")
10427 (define_expand "symDTPOFF2reg"
10428   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10429   ""
10431   rtx dtpoffsym;
10432   rtx t = (!can_create_pseudo_p ()
10433            ? operands[0]
10434            : gen_reg_rtx (GET_MODE (operands[0])));
10436   dtpoffsym = gen_sym2DTPOFF (operands[1]);
10437   PUT_MODE (dtpoffsym, Pmode);
10438   emit_move_insn (t, dtpoffsym);
10439   emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10440   DONE;
10443 (define_expand "sym2GOTTPOFF"
10444   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10445   ""
10446   "")
10448 (define_insn "tls_initial_exec"
10449   [(set (match_operand:SI 0 "register_operand" "=&r")
10450         (unspec:SI [(match_operand:SI 1 "" "")]
10451                     UNSPEC_TLSIE))
10452    (use (reg:SI GBR_REG))
10453    (use (reg:SI PIC_REG))
10454    (clobber (reg:SI R0_REG))]
10455   ""
10457   return       "mov.l   1f,r0"          "\n"
10458          "      stc     gbr,%0"         "\n"
10459          "      mov.l   @(r0,r12),r0"   "\n"
10460          "      bra     2f"             "\n"
10461          "      add     r0,%0"          "\n"
10462          "      .align  2"              "\n"
10463          "1:    .long   %a1"            "\n"
10464          "2:";
10466   [(set_attr "type" "tls_load")
10467    (set_attr "length" "16")])
10469 (define_expand "sym2TPOFF"
10470   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10471   ""
10472   "")
10474 (define_expand "symTPOFF2reg"
10475   [(match_operand 0 "" "") (match_operand 1 "" "")]
10476   ""
10478   rtx tpoffsym;
10480   tpoffsym = gen_sym2TPOFF (operands[1]);
10481   PUT_MODE (tpoffsym, Pmode);
10482   emit_move_insn (operands[0], tpoffsym);
10483   DONE;
10486 ;;------------------------------------------------------------------------------
10487 ;; Thread pointer getter and setter.
10489 ;; On SH the thread pointer is kept in the GBR.
10490 ;; These patterns are usually expanded from the respective built-in functions.
10491 (define_expand "get_thread_pointersi"
10492   [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10493   "TARGET_SH1")
10495 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10496 (define_insn "store_gbr"
10497   [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10498   ""
10499   "stc  gbr,%0"
10500   [(set_attr "type" "tls_load")])
10502 (define_expand "set_thread_pointersi"
10503   [(set (reg:SI GBR_REG)
10504         (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10505          UNSPECV_GBR))]
10506   "TARGET_SH1")
10508 (define_insn "load_gbr"
10509   [(set (reg:SI GBR_REG)
10510         (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10511          UNSPECV_GBR))]
10512   "TARGET_SH1"
10513   "ldc  %0,gbr"
10514   [(set_attr "type" "move")])
10516 ;;------------------------------------------------------------------------------
10517 ;; Thread pointer relative memory loads and stores.
10519 ;; On SH there are GBR displacement address modes which can be utilized to
10520 ;; access memory behind the thread pointer.
10521 ;; Since we do not allow using GBR for general purpose memory accesses, these
10522 ;; GBR addressing modes are formed by the combine pass.
10523 ;; This could be done with fewer patterns than below by using a mem predicate
10524 ;; for the GBR mem, but then reload would try to reload addresses with a
10525 ;; zero displacement for some strange reason.
10527 (define_insn "*mov<mode>_gbr_load"
10528   [(set (match_operand:QIHISI 0 "register_operand" "=z")
10529         (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10530                              (match_operand:QIHISI 1 "gbr_displacement"))))]
10531   "TARGET_SH1"
10532   "mov.<bwl>    @(%O1,gbr),%0"
10533   [(set_attr "type" "load")])
10535 (define_insn "*mov<mode>_gbr_load"
10536   [(set (match_operand:QIHISI 0 "register_operand" "=z")
10537         (mem:QIHISI (reg:SI GBR_REG)))]
10538   "TARGET_SH1"
10539   "mov.<bwl>    @(0,gbr),%0"
10540   [(set_attr "type" "load")])
10542 (define_insn "*mov<mode>_gbr_load"
10543   [(set (match_operand:SI 0 "register_operand" "=z")
10544         (sign_extend:SI
10545           (mem:QIHI (plus:SI (reg:SI GBR_REG)
10546                              (match_operand:QIHI 1 "gbr_displacement")))))]
10547   "TARGET_SH1"
10548   "mov.<bw>     @(%O1,gbr),%0"
10549   [(set_attr "type" "load")])
10551 (define_insn "*mov<mode>_gbr_load"
10552   [(set (match_operand:SI 0 "register_operand" "=z")
10553         (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10554   "TARGET_SH1"
10555   "mov.<bw>     @(0,gbr),%0"
10556   [(set_attr "type" "load")])
10558 (define_insn "*mov<mode>_gbr_store"
10559   [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10560                              (match_operand:QIHISI 0 "gbr_displacement")))
10561         (match_operand:QIHISI 1 "register_operand" "z"))]
10562   "TARGET_SH1"
10563   "mov.<bwl>    %1,@(%O0,gbr)"
10564   [(set_attr "type" "store")])
10566 (define_insn "*mov<mode>_gbr_store"
10567   [(set (mem:QIHISI (reg:SI GBR_REG))
10568         (match_operand:QIHISI 0 "register_operand" "z"))]
10569   "TARGET_SH1"
10570   "mov.<bwl>    %0,@(0,gbr)"
10571   [(set_attr "type" "store")])
10573 ;; DImode memory accesses have to be split in two SImode accesses.
10574 ;; Split them before reload, so that it gets a better chance to figure out
10575 ;; how to deal with the R0 restriction for the individual SImode accesses.
10576 ;; Do not match this insn during or after reload because it can't be split
10577 ;; afterwards.
10578 (define_insn_and_split "*movdi_gbr_load"
10579   [(set (match_operand:DI 0 "register_operand")
10580         (match_operand:DI 1 "gbr_address_mem"))]
10581   "TARGET_SH1 && can_create_pseudo_p ()"
10582   "#"
10583   "&& 1"
10584   [(set (match_dup 3) (match_dup 5))
10585    (set (match_dup 4) (match_dup 6))]
10587   /* Swap low/high part load order on little endian, so that the result reg
10588      of the second load can be used better.  */
10589   int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10590   operands[3 + off] = gen_lowpart (SImode, operands[0]);
10591   operands[5 + off] = gen_lowpart (SImode, operands[1]);
10592   operands[4 - off] = gen_highpart (SImode, operands[0]);
10593   operands[6 - off] = gen_highpart (SImode, operands[1]);
10596 (define_insn_and_split "*movdi_gbr_store"
10597   [(set (match_operand:DI 0 "gbr_address_mem")
10598         (match_operand:DI 1 "register_operand"))]
10599   "TARGET_SH1 && can_create_pseudo_p ()"
10600   "#"
10601   "&& 1"
10602   [(set (match_dup 3) (match_dup 5))
10603    (set (match_dup 4) (match_dup 6))]
10605   /* Swap low/high part store order on big endian, so that stores of function
10606      call results can save a reg copy.  */
10607   int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10608   operands[3 + off] = gen_lowpart (SImode, operands[0]);
10609   operands[5 + off] = gen_lowpart (SImode, operands[1]);
10610   operands[4 - off] = gen_highpart (SImode, operands[0]);
10611   operands[6 - off] = gen_highpart (SImode, operands[1]);
10614 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
10615 ;; in particular when the displacements are in the range of the regular move
10616 ;; insns.  Thus, in the first split pass after the combine pass we search
10617 ;; for missed opportunities and try to fix them up ourselves.
10618 ;; If an equivalent GBR address can be determined the load / store is split
10619 ;; into one of the GBR load / store patterns.
10620 ;; All of that must happen before reload (GBR address modes use R0 as the
10621 ;; other operand) and there's no point of doing it if the GBR is not
10622 ;; referenced in a function at all.
10623 (define_split
10624   [(set (match_operand:QIHISIDI 0 "register_operand")
10625         (match_operand:QIHISIDI 1 "memory_operand"))]
10626   "TARGET_SH1 && !reload_in_progress && !reload_completed
10627    && df_regs_ever_live_p (GBR_REG)"
10628   [(set (match_dup 0) (match_dup 1))]
10630   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10631   if (gbr_mem != NULL_RTX)
10632     operands[1] = replace_equiv_address (operands[1], gbr_mem);
10633   else
10634     FAIL;
10637 (define_split
10638   [(set (match_operand:SI 0 "register_operand")
10639         (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10640   "TARGET_SH1 && !reload_in_progress && !reload_completed
10641    && df_regs_ever_live_p (GBR_REG)"
10642   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10644   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10645   if (gbr_mem != NULL_RTX)
10646     operands[1] = replace_equiv_address (operands[1], gbr_mem);
10647   else
10648     FAIL;
10651 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10652 ;; Split those so that a GBR load can be used.
10653 (define_split
10654   [(set (match_operand:SI 0 "register_operand")
10655         (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10656   "TARGET_SH2A && !reload_in_progress && !reload_completed
10657    && df_regs_ever_live_p (GBR_REG)"
10658   [(set (match_dup 2) (match_dup 1))
10659    (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10661   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10662   if (gbr_mem != NULL_RTX)
10663     {
10664       operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10665       operands[1] = replace_equiv_address (operands[1], gbr_mem);
10666     }
10667   else
10668     FAIL;
10671 (define_split
10672   [(set (match_operand:QIHISIDI 0 "memory_operand")
10673         (match_operand:QIHISIDI 1 "register_operand"))]
10674   "TARGET_SH1 && !reload_in_progress && !reload_completed
10675    && df_regs_ever_live_p (GBR_REG)"
10676   [(set (match_dup 0) (match_dup 1))]
10678   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10679   if (gbr_mem != NULL_RTX)
10680     operands[0] = replace_equiv_address (operands[0], gbr_mem);
10681   else
10682     FAIL;
10685 ;;------------------------------------------------------------------------------
10686 ;; case instruction for switch statements.
10688 ;; operand 0 is index
10689 ;; operand 1 is the minimum bound
10690 ;; operand 2 is the maximum bound - minimum bound + 1
10691 ;; operand 3 is CODE_LABEL for the table;
10692 ;; operand 4 is the CODE_LABEL to go to if index out of range.
10693 (define_expand "casesi"
10694   [(match_operand:SI 0 "arith_reg_operand" "")
10695    (match_operand:SI 1 "arith_reg_operand" "")
10696    (match_operand:SI 2 "arith_reg_operand" "")
10697    (match_operand 3 "" "") (match_operand 4 "" "")]
10698   ""
10700   rtx reg = gen_reg_rtx (SImode);
10701   rtx reg2 = gen_reg_rtx (SImode);
10702   if (TARGET_SHMEDIA)
10703     {
10704       rtx reg = gen_reg_rtx (DImode);
10705       rtx reg2 = gen_reg_rtx (DImode);
10706       rtx reg3 = gen_reg_rtx (Pmode);
10707       rtx reg4 = gen_reg_rtx (Pmode);
10708       rtx reg5 = gen_reg_rtx (Pmode);
10709       rtx load, test;
10711       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10712       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10713       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10715       test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10716       emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
10717                                       operands[4]));
10718       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10719       test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10720       emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10721       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10722       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10723                                                (Pmode, operands[3])));
10724       /* Messy: can we subreg to clean this up? */
10725       if (Pmode == DImode)
10726         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10727       else
10728         load = gen_casesi_load_media (reg4,
10729                                       gen_rtx_SUBREG (DImode, reg3, 0),
10730                                       reg2, operands[3]);
10731       PUT_MODE (SET_SRC (load), Pmode);
10732       emit_insn (load);
10733       /* ??? The following add could be eliminated if we used ptrel.  */
10734       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10735       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10736       emit_barrier ();
10737       DONE;
10738     }
10739   operands[1] = copy_to_mode_reg (SImode, operands[1]);
10740   operands[2] = copy_to_mode_reg (SImode, operands[2]);
10741   /* If optimizing, casesi_worker depends on the mode of the instruction
10742      before label it 'uses' - operands[3].  */
10743   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10744                            reg));
10745   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10746   if (TARGET_SH2)
10747     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10748   else
10749     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10750   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10751      operands[3], but to lab.  We will fix this up in
10752      machine_dependent_reorg.  */
10753   emit_barrier ();
10754   DONE;
10757 (define_expand "casesi_0"
10758   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10759    (set (match_dup 4) (minus:SI (match_dup 4)
10760                                 (match_operand:SI 1 "arith_operand" "")))
10761    (set (reg:SI T_REG)
10762         (gtu:SI (match_dup 4)
10763                 (match_operand:SI 2 "arith_reg_operand" "")))
10764    (set (pc)
10765         (if_then_else (ne (reg:SI T_REG)
10766                           (const_int 0))
10767                       (label_ref (match_operand 3 "" ""))
10768                       (pc)))]
10769   "TARGET_SH1"
10770   "")
10772 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10773 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10774 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10775 (define_insn "casesi_worker_0"
10776   [(set (match_operand:SI 0 "register_operand" "=r,r")
10777         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10778                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10779    (clobber (match_scratch:SI 3 "=X,1"))
10780    (clobber (match_scratch:SI 4 "=&z,z"))]
10781   "TARGET_SH1"
10782   "#")
10784 (define_split
10785   [(set (match_operand:SI 0 "register_operand" "")
10786         (unspec:SI [(match_operand:SI 1 "register_operand" "")
10787                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10788    (clobber (match_scratch:SI 3 ""))
10789    (clobber (match_scratch:SI 4 ""))]
10790   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10791   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10792    (parallel [(set (match_dup 0)
10793               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10794                           (label_ref (match_dup 2))] UNSPEC_CASESI))
10795               (clobber (match_dup 3))])
10796    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10798   if (GET_CODE (operands[2]) == CODE_LABEL)
10799     LABEL_NUSES (operands[2])++;
10802 (define_split
10803   [(set (match_operand:SI 0 "register_operand" "")
10804         (unspec:SI [(match_operand:SI 1 "register_operand" "")
10805                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10806    (clobber (match_scratch:SI 3 ""))
10807    (clobber (match_scratch:SI 4 ""))]
10808   "TARGET_SH2 && reload_completed"
10809   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10810    (parallel [(set (match_dup 0)
10811               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10812                           (label_ref (match_dup 2))] UNSPEC_CASESI))
10813               (clobber (match_dup 3))])]
10815   if (GET_CODE (operands[2]) == CODE_LABEL)
10816     LABEL_NUSES (operands[2])++;
10819 (define_insn "casesi_worker_1"
10820   [(set (match_operand:SI 0 "register_operand" "=r,r")
10821         (unspec:SI [(reg:SI R0_REG)
10822                     (match_operand:SI 1 "register_operand" "0,r")
10823                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10824    (clobber (match_scratch:SI 3 "=X,1"))]
10825   "TARGET_SH1"
10827   rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10829   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10831   switch (GET_MODE (diff_vec))
10832     {
10833     case SImode:
10834       return   "shll2   %1"     "\n"
10835              "  mov.l   @(r0,%1),%0";
10836     case HImode:
10837       return   "add     %1,%1"  "\n"
10838              "  mov.w   @(r0,%1),%0";
10839     case QImode:
10840       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10841         return         "mov.b   @(r0,%1),%0"    "\n"
10842                "        extu.b  %0,%0";
10843       else
10844         return "mov.b   @(r0,%1),%0";
10846     default:
10847       gcc_unreachable ();
10848     }
10850   [(set_attr "length" "4")])
10852 (define_insn "casesi_worker_2"
10853   [(set (match_operand:SI 0 "register_operand" "=r,r")
10854         (unspec:SI [(reg:SI R0_REG)
10855                     (match_operand:SI 1 "register_operand" "0,r")
10856                     (label_ref (match_operand 2 "" ""))
10857                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10858    (clobber (match_operand:SI 4 "" "=X,1"))]
10859   "TARGET_SH2 && reload_completed && flag_pic"
10861   rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10862   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10864   switch (GET_MODE (diff_vec))
10865     {
10866     case SImode:
10867       return   "shll2   %1"             "\n"
10868              "  add     r0,%1"          "\n"
10869              "  mova    %O3,r0"         "\n"
10870              "  mov.l   @(r0,%1),%0";
10871     case HImode:
10872       return   "add     %1,%1"          "\n"
10873              "  add     r0,%1"          "\n"
10874              "  mova    %O3,r0"         "\n"
10875              "  mov.w   @(r0,%1),%0";
10876     case QImode:
10877       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10878         return         "add     r0,%1"          "\n"
10879                 "       mova    %O3,r0"         "\n"
10880                 "       mov.b   @(r0,%1),%0"    "\n"
10881                 "       extu.b  %0,%0";
10882       else
10883         return         "add     r0,%1"          "\n"
10884                 "       mova    %O3,r0"         "\n"
10885                 "       mov.b   @(r0,%1),%0";
10886     default:
10887       gcc_unreachable ();
10888     }
10890   [(set_attr "length" "8")])
10892 (define_insn "casesi_shift_media"
10893   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10894         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10895                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10896                     UNSPEC_CASESI)))]
10897   "TARGET_SHMEDIA"
10899   rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10901   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10903   switch (GET_MODE (diff_vec))
10904     {
10905     case SImode:
10906       return "shlli     %1, 2, %0";
10907     case HImode:
10908       return "shlli     %1, 1, %0";
10909     case QImode:
10910       if (rtx_equal_p (operands[0], operands[1]))
10911         return "";
10912       return "add       %1, r63, %0";
10913     default:
10914       gcc_unreachable ();
10915     }
10917   [(set_attr "type" "arith_media")])
10919 (define_insn "casesi_load_media"
10920   [(set (match_operand 0 "any_arith_reg_dest" "=r")
10921         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10922                       (match_operand:DI 2 "arith_reg_operand" "r")
10923                       (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
10924   "TARGET_SHMEDIA"
10926   rtx diff_vec = PATTERN (NEXT_INSN (operands[3]));
10928   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10930   switch (GET_MODE (diff_vec))
10931     {
10932     case SImode:
10933       return "ldx.l     %1, %2, %0";
10934     case HImode:
10935 #if 0
10936       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10937         return "ldx.uw  %1, %2, %0";
10938 #endif
10939       return "ldx.w     %1, %2, %0";
10940     case QImode:
10941       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10942         return "ldx.ub  %1, %2, %0";
10943       return "ldx.b     %1, %2, %0";
10944     default:
10945       gcc_unreachable ();
10946     }
10948   [(set_attr "type" "load_media")])
10950 (define_expand "simple_return"
10951   [(simple_return)]
10952  "sh_can_use_simple_return_p ()")
10954 (define_expand "return"
10955   [(return)]
10956  "reload_completed && epilogue_completed"
10958   if (TARGET_SHMEDIA)
10959     {
10960       emit_jump_insn (gen_return_media ());
10961       DONE;
10962     }
10964   if (TARGET_SHCOMPACT
10965       && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
10966     {
10967       emit_jump_insn (gen_shcompact_return_tramp ());
10968       DONE;
10969     }
10972 (define_insn "*<code>_i"
10973   [(any_return)]
10974   "TARGET_SH1 && ! (TARGET_SHCOMPACT
10975                     && (crtl->args.info.call_cookie
10976                         & CALL_COOKIE_RET_TRAMP (1)))
10977    && reload_completed
10978    && ! sh_cfun_trap_exit_p ()"
10980   if (TARGET_SH2A && (dbr_sequence_length () == 0)
10981       && !current_function_interrupt)
10982     return "rts/n";
10983   else
10984     return "%@  %#";
10986   [(set_attr "type" "return")
10987    (set_attr "needs_delay_slot" "yes")])
10989 ;; trapa has no delay slot.
10990 (define_insn "*return_trapa"
10991   [(return)]
10992   "TARGET_SH1 && !TARGET_SHCOMPACT
10993    && reload_completed"
10994   "%@"
10995   [(set_attr "type" "return")])
10997 (define_expand "shcompact_return_tramp"
10998   [(return)]
10999   "TARGET_SHCOMPACT
11000    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11002   rtx reg = gen_rtx_REG (Pmode, R0_REG);
11004   function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
11005   emit_jump_insn (gen_shcompact_return_tramp_i ());
11006   DONE;
11009 (define_insn "shcompact_return_tramp_i"
11010   [(parallel [(return) (use (reg:SI R0_REG))])]
11011   "TARGET_SHCOMPACT
11012    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11013   "jmp  @r0%#"
11014   [(set_attr "type" "jump_ind")
11015    (set_attr "needs_delay_slot" "yes")])
11017 (define_insn "return_media_i"
11018   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
11019   "TARGET_SHMEDIA && reload_completed"
11020   "blink        %0, r63"
11021   [(set_attr "type" "jump_media")])
11023 (define_insn "return_media_rte"
11024   [(return)]
11025   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
11026   "rte"
11027   [(set_attr "type" "jump_media")])
11029 (define_expand "return_media"
11030   [(return)]
11031   "TARGET_SHMEDIA && reload_completed"
11033   int tr_regno = sh_media_register_for_return ();
11034   rtx tr;
11036   if (current_function_interrupt)
11037     {
11038       emit_jump_insn (gen_return_media_rte ());
11039       DONE;
11040     }
11041   if (tr_regno < 0)
11042     {
11043       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
11045       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
11046       tr_regno = TR0_REG;
11047       tr = gen_rtx_REG (Pmode, tr_regno);
11048       emit_move_insn (tr, r18);
11049     }
11050   else
11051     tr = gen_rtx_REG (Pmode, tr_regno);
11053   emit_jump_insn (gen_return_media_i (tr));
11054   DONE;
11057 (define_insn "shcompact_preserve_incoming_args"
11058   [(set (match_operand:SI 0 "register_operand" "+r")
11059         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
11060   "TARGET_SHCOMPACT"
11061   ""
11062   [(set_attr "length" "0")])
11064 (define_insn "shcompact_incoming_args"
11065   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
11066    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
11067    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
11068    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
11069    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
11070    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
11071    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
11072    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
11073    (set (mem:BLK (reg:SI MACL_REG))
11074         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
11075    (use (reg:SI R0_REG))
11076    (clobber (reg:SI R0_REG))
11077    (clobber (reg:SI MACL_REG))
11078    (clobber (reg:SI MACH_REG))
11079    (clobber (reg:SI PR_REG))]
11080   "TARGET_SHCOMPACT"
11081   "jsr  @r0%#"
11082   [(set_attr "needs_delay_slot" "yes")])
11084 (define_insn "shmedia_save_restore_regs_compact"
11085   [(set (reg:SI SP_REG)
11086         (plus:SI (reg:SI SP_REG)
11087                  (match_operand:SI 0 "immediate_operand" "i")))
11088    (use (reg:SI R0_REG))
11089    (clobber (reg:SI PR_REG))]
11090   "TARGET_SHCOMPACT
11091    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
11092        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
11093   "jsr @r0%#"
11094   [(set_attr "needs_delay_slot" "yes")])
11096 (define_expand "prologue"
11097   [(const_int 0)]
11098   ""
11100   sh_expand_prologue ();
11101   DONE;
11104 (define_expand "epilogue"
11105   [(return)]
11106   ""
11108   sh_expand_epilogue (false);
11109   if (TARGET_SHMEDIA
11110       || (TARGET_SHCOMPACT
11111           && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11112     {
11113       emit_jump_insn (gen_return ());
11114       DONE;
11115     }
11118 (define_expand "eh_return"
11119   [(use (match_operand 0 "register_operand" ""))]
11120   ""
11122   rtx ra = operands[0];
11124   if (TARGET_SHMEDIA64)
11125     emit_insn (gen_eh_set_ra_di (ra));
11126   else
11127     emit_insn (gen_eh_set_ra_si (ra));
11129   DONE;
11132 ;; Clobber the return address on the stack.  We can't expand this
11133 ;; until we know where it will be put in the stack frame.
11135 (define_insn "eh_set_ra_si"
11136   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11137       UNSPECV_EH_RETURN)
11138    (clobber (match_scratch:SI 1 "=&r"))]
11139   "! TARGET_SHMEDIA64"
11140   "#")
11142 (define_insn "eh_set_ra_di"
11143   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11144       UNSPECV_EH_RETURN)
11145    (clobber (match_scratch:DI 1 "=&r"))]
11146   "TARGET_SHMEDIA64"
11147   "#")
11149 (define_split
11150   [(unspec_volatile [(match_operand 0 "register_operand" "")]
11151       UNSPECV_EH_RETURN)
11152    (clobber (match_scratch 1 ""))]
11153   "reload_completed"
11154   [(const_int 0)]
11156   sh_set_return_address (operands[0], operands[1]);
11157   DONE;
11160 (define_insn "blockage"
11161   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11162   ""
11163   ""
11164   [(set_attr "length" "0")])
11166 ;; Define movml instructions for SH2A target.  Currently they are
11167 ;; used to push and pop all banked registers only.
11169 (define_insn "movml_push_banked"
11170   [(set (match_operand:SI 0 "register_operand" "=r")
11171           (plus (match_dup 0) (const_int -32)))
11172    (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11173    (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11174    (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11175    (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11176    (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11177    (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11178    (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11179    (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11180   "TARGET_SH2A && REGNO (operands[0]) == 15"
11181   "movml.l      r7,@-r15"
11182   [(set_attr "in_delay_slot" "no")])
11184 (define_insn "movml_pop_banked"
11185   [(set (match_operand:SI 0 "register_operand" "=r")
11186           (plus (match_dup 0) (const_int 32)))
11187    (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11188    (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11189    (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11190    (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11191    (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11192    (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11193    (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11194    (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11195   "TARGET_SH2A && REGNO (operands[0]) == 15"
11196   "movml.l      @r15+,r7"
11197   [(set_attr "in_delay_slot" "no")])
11199 ;; ------------------------------------------------------------------------
11200 ;; Scc instructions
11201 ;; ------------------------------------------------------------------------
11203 (define_insn "movt"
11204   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11205         (match_operand:SI 1 "t_reg_operand"))]
11206   "TARGET_SH1"
11207   "movt %0"
11208   [(set_attr "type" "arith")])
11210 (define_insn "movrt"
11211   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11212         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11213   "TARGET_SH2A"
11214   "movrt        %0"
11215   [(set_attr "type" "arith")])
11217 (define_expand "cstore4_media"
11218   [(set (match_operand:SI 0 "register_operand" "=r")
11219         (match_operator:SI 1 "sh_float_comparison_operator"
11220          [(match_operand 2 "logical_operand" "")
11221           (match_operand 3 "cmp_operand" "")]))]
11222   "TARGET_SHMEDIA"
11224   enum machine_mode mode = GET_MODE (operands[2]);
11225   enum rtx_code code = GET_CODE (operands[1]);
11226   bool invert, swap;
11227   if (mode == VOIDmode)
11228     mode = GET_MODE (operands[3]);
11229   if (operands[2] == const0_rtx)
11230     {
11231       if (code == EQ || code == NE)
11232         operands[2] = operands[3], operands[3] = const0_rtx;
11233     }
11234   else
11235     operands[2] = force_reg (mode, operands[2]);
11236   if (operands[3] != const0_rtx)
11237     operands[3] = force_reg (mode, operands[3]);
11239   switch (code)
11240     {
11241     case GEU:
11242     case GE:
11243       swap = invert = !FLOAT_MODE_P (mode);
11244       break;
11246     case LEU:
11247     case LE:
11248       swap = FLOAT_MODE_P (mode), invert = !swap;
11249       break;
11251     case LTU:
11252     case LT:
11253       swap = true, invert = false;
11254       break;
11256     case GTU:
11257     case GT:
11258     case EQ:
11259     case UNORDERED:
11260       swap = invert = false;
11261       break;
11263     case NE:
11264       swap = invert = true;
11265       break;
11267     default:
11268       gcc_unreachable ();
11269   }
11271   if (swap)
11272     {
11273       rtx tem = operands[2];
11274       operands[2] = operands[3];
11275       operands[3] = tem;
11276       code = swap_condition (code);
11277     }
11279   if (invert)
11280     {
11281       rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11282       code = reverse_condition (code);
11283       operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11284       emit_insn (gen_cstore4_media (tem, operands[1],
11285                                     operands[2], operands[3]));
11286       code = EQ;
11287       operands[2] = tem;
11288       operands[3] = const0_rtx;
11289     }
11291   operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11294 (define_expand "cstoresi4"
11295   [(set (match_operand:SI 0 "register_operand" "=r")
11296         (match_operator:SI 1 "comparison_operator"
11297          [(match_operand:SI 2 "cmpsi_operand" "")
11298           (match_operand:SI 3 "arith_operand" "")]))]
11299   "TARGET_SH1 || TARGET_SHMEDIA"
11301   if (TARGET_SHMEDIA)
11302     {
11303       emit_insn (gen_cstore4_media (operands[0], operands[1],
11304                                     operands[2], operands[3]));
11305       DONE;
11306     }
11308    if (sh_expand_t_scc (operands))
11309      DONE;
11311    if (! currently_expanding_to_rtl)
11312      FAIL;
11313    
11314    sh_emit_compare_and_set (operands, SImode);
11315    DONE;
11318 (define_expand "cstoredi4"
11319   [(set (match_operand:SI 0 "register_operand" "=r")
11320         (match_operator:SI 1 "comparison_operator"
11321          [(match_operand:DI 2 "arith_operand" "")
11322           (match_operand:DI 3 "arith_operand" "")]))]
11323   "TARGET_SH2 || TARGET_SHMEDIA"
11325   if (TARGET_SHMEDIA)
11326     {
11327       emit_insn (gen_cstore4_media (operands[0], operands[1],
11328                                     operands[2], operands[3]));
11329       DONE;
11330     }
11332    if (sh_expand_t_scc (operands))
11333      DONE;
11335    if (! currently_expanding_to_rtl)
11336      FAIL;
11337    
11338    sh_emit_compare_and_set (operands, DImode);
11339    DONE;
11342 ;; Move the complement of the T reg to a reg.
11343 ;; On SH2A the movrt insn can be used.
11344 ;; On anything else than SH2A this has to be done with multiple instructions.
11345 ;; One obvious way would be:
11346 ;;      cmp/eq  ...
11347 ;;      movt    r0
11348 ;;      xor     #1,r0
11350 ;; However, this puts pressure on r0 in most cases and thus the following is
11351 ;; more appealing:
11352 ;;      cmp/eq  ...
11353 ;;      mov     #-1,temp
11354 ;;      negc    temp,dest
11356 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11357 ;; becomes a one instruction operation.  Moreover, care must be taken that
11358 ;; the insn can still be combined with inverted compare and branch code
11359 ;; around it.  On the other hand, if a function returns the complement of
11360 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11361 ;; lead to better code.
11362 (define_expand "movnegt"
11363   [(set (match_operand:SI 0 "arith_reg_dest" "")
11364         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11365   "TARGET_SH1"
11367   if (TARGET_SH2A)
11368     emit_insn (gen_movrt (operands[0], operands[1]));
11369   else
11370     {
11371       rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11372       emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11373     }
11374   DONE;
11377 (define_insn "movrt_negc"
11378   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11379         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11380    (set (reg:SI T_REG) (const_int 1))
11381    (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11382   "TARGET_SH1"
11383   "negc %2,%0"
11384   [(set_attr "type" "arith")])
11386 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11387 ;; pattern can be used by the combine pass.  Using a scratch reg for the
11388 ;; -1 constant results in slightly better register allocations compared to
11389 ;; generating a pseudo reg before reload.
11390 (define_insn_and_split "*movrt_negc"
11391   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11392         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11393    (clobber (match_scratch:SI 2 "=r"))
11394    (clobber (reg:SI T_REG))]
11395   "TARGET_SH1 && ! TARGET_SH2A"
11396   "#"
11397   "&& reload_completed"
11398   [(set (match_dup 2) (const_int -1))
11399    (parallel
11400        [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11401         (set (reg:SI T_REG) (const_int 1))
11402         (use (match_dup 2))])])
11404 ;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
11405 ;; clobber the T bit, which is useful when storing the T bit and the
11406 ;; negated T bit in parallel.  On SH2A the movrt insn can be used for that.
11407 ;; Usually we don't want this insn to be matched, except for cases where the
11408 ;; T bit clobber is really not appreciated.  Hence the extra use on T_REG.
11409 (define_insn_and_split "movrt_xor"
11410   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11411         (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11412    (use (reg:SI T_REG))]
11413   "TARGET_SH1 && !TARGET_SH2A"
11414   "#"
11415   "&& reload_completed"
11416   [(set (match_dup 0) (reg:SI T_REG))
11417    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11419 ;; Store the T bit and the negated T bit in two regs in parallel.  There is
11420 ;; no real insn to do that, but specifying this pattern will give combine
11421 ;; some opportunities.
11422 (define_insn_and_split "*movt_movrt"
11423   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11424                    (match_operand:SI 1 "negt_reg_operand"))
11425               (set (match_operand:SI 2 "arith_reg_dest")
11426                    (match_operand:SI 3 "t_reg_operand"))])]
11427   "TARGET_SH1"
11428   "#"
11429   "&& 1"
11430   [(const_int 0)]
11432   rtx i = TARGET_SH2A
11433           ? gen_movrt (operands[0], get_t_reg_rtx ())
11434           : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11435   
11436   emit_insn (i);
11437   emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11438   DONE;
11441 (define_insn_and_split "*movt_movrt"
11442   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11443                    (match_operand:SI 1 "t_reg_operand"))
11444               (set (match_operand:SI 2 "arith_reg_dest")
11445                    (match_operand:SI 3 "negt_reg_operand"))])]
11446   "TARGET_SH1"
11447   "#"
11448   "&& 1"
11449   [(parallel [(set (match_dup 2) (match_dup 3))
11450               (set (match_dup 0) (match_dup 1))])])
11452 ;; Use negc to store the T bit in a MSB of a reg in the following way:
11453 ;;      T = 1: 0x80000000 -> reg
11454 ;;      T = 0: 0x7FFFFFFF -> reg
11455 ;; This works because 0 - 0x80000000 = 0x80000000.
11456 (define_insn_and_split "*mov_t_msb_neg"
11457   [(set (match_operand:SI 0 "arith_reg_dest")
11458         (minus:SI (const_int -2147483648)  ;; 0x80000000
11459                   (match_operand 1 "t_reg_operand")))
11460    (clobber (reg:SI T_REG))]
11461   "TARGET_SH1"
11462   "#"
11463   "&& can_create_pseudo_p ()"
11464   [(set (match_dup 2) (const_int -2147483648))
11465    (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11466                                  (reg:SI T_REG)))
11467               (clobber (reg:SI T_REG))])]
11469   operands[2] = gen_reg_rtx (SImode);
11472 ;; These are essentially the same as above, but with the inverted T bit.
11473 ;; Combine recognizes the split patterns, but does not take them sometimes
11474 ;; if the T_REG clobber is specified.  Instead it tries to split out the
11475 ;; T bit negation.  Since these splits are supposed to be taken only by
11476 ;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11477 ;; should be fine.
11478 (define_split
11479   [(set (match_operand:SI 0 "arith_reg_dest")
11480         (plus:SI (match_operand 1 "negt_reg_operand")
11481                  (const_int 2147483647)))]  ;; 0x7fffffff
11482   "TARGET_SH1 && can_create_pseudo_p ()"
11483   [(parallel [(set (match_dup 0)
11484                    (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11485               (clobber (reg:SI T_REG))])])
11487 (define_split
11488   [(set (match_operand:SI 0 "arith_reg_dest")
11489         (if_then_else:SI (match_operand 1 "t_reg_operand")
11490                          (const_int 2147483647)  ;; 0x7fffffff
11491                          (const_int -2147483648)))]  ;; 0x80000000
11492   "TARGET_SH1 && can_create_pseudo_p ()"
11493   [(parallel [(set (match_dup 0)
11494                    (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11495               (clobber (reg:SI T_REG))])])
11497 ;; The *negnegt pattern helps the combine pass to figure out how to fold 
11498 ;; an explicit double T bit negation.
11499 (define_insn_and_split "*negnegt"
11500   [(set (reg:SI T_REG)
11501         (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11502   "TARGET_SH1"
11503   "#"
11504   ""
11505   [(const_int 0)])
11507 ;; Store T bit as all zeros or ones in a reg.
11508 (define_insn "mov_neg_si_t"
11509   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11510         (neg:SI (match_operand 1 "t_reg_operand" "")))]
11511   "TARGET_SH1"
11512   "subc %0,%0"
11513   [(set_attr "type" "arith")])
11515 ;; Store negated T bit as all zeros or ones in a reg.
11516 ;; Use the following sequence:
11517 ;;      subc    Rn,Rn   ! Rn = Rn - Rn - T; T = T
11518 ;;      not     Rn,Rn   ! Rn = 0 - Rn
11519 (define_split
11520   [(set (match_operand:SI 0 "arith_reg_dest" "")
11521         (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11522   "TARGET_SH1"
11523   [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11524    (set (match_dup 0) (not:SI (match_dup 0)))])
11526 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11527 (define_insn_and_split "*movtt"
11528   [(set (reg:SI T_REG)
11529         (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11530   "TARGET_SH1"
11531   "#"
11532   ""
11533   [(const_int 0)])
11535 ;; Invert the T bit.
11536 ;; On SH2A we can use the nott insn.  On anything else this must be done with
11537 ;; multiple insns like:
11538 ;;      movt    Rn
11539 ;;      tst     Rn,Rn
11540 ;; This requires an additional pseudo.  The SH specific sh_treg_combine RTL
11541 ;; pass will look for this insn.  Disallow using it if pseudos can't be
11542 ;; created.
11543 (define_insn_and_split "nott"
11544   [(set (reg:SI T_REG)
11545         (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
11546   "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
11548   gcc_assert (TARGET_SH2A);
11549   return "nott";
11551   "! TARGET_SH2A && can_create_pseudo_p ()"
11552   [(set (match_dup 0) (reg:SI T_REG))
11553    (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11555   operands[0] = gen_reg_rtx (SImode);
11558 ;; Store T bit as MSB in a reg.
11559 ;; T = 0: 0x00000000 -> reg
11560 ;; T = 1: 0x80000000 -> reg
11561 (define_insn_and_split "*movt_msb"
11562   [(set (match_operand:SI 0 "arith_reg_dest")
11563         (mult:SI (match_operand:SI 1 "t_reg_operand")
11564                  (const_int -2147483648)))  ;; 0xffffffff80000000
11565    (clobber (reg:SI T_REG))]
11566   "TARGET_SH1"
11567   "#"
11568   "&& 1"
11569   [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11571 ;; Store inverted T bit as MSB in a reg.
11572 ;; T = 0: 0x80000000 -> reg
11573 ;; T = 1: 0x00000000 -> reg
11574 ;; On SH2A we can get away without clobbering the T_REG.
11575 (define_insn_and_split "*negt_msb"
11576   [(set (match_operand:SI 0 "arith_reg_dest")
11577         (match_operand:SI 1 "negt_reg_shl31_operand"))]
11578   "TARGET_SH2A"
11579   "#"
11580   "&& can_create_pseudo_p ()"
11581   [(const_int 0)]
11583   rtx tmp = gen_reg_rtx (SImode);
11584   emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11585   emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11586   DONE;
11589 (define_insn_and_split "*negt_msb"
11590   [(set (match_operand:SI 0 "arith_reg_dest")
11591         (match_operand:SI 1 "negt_reg_shl31_operand"))
11592    (clobber (reg:SI T_REG))]
11593   "TARGET_SH1 && !TARGET_SH2A"
11594   "#"
11595   "&& can_create_pseudo_p ()"
11596   [(const_int 0)]
11598   rtx tmp = gen_reg_rtx (SImode);
11599   emit_move_insn (tmp, get_t_reg_rtx ());
11600   emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11601   emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11602   DONE;
11605 ;; The *cset_zero patterns convert optimizations such as
11606 ;;      "if (test) x = 0;"
11607 ;; to
11608 ;;      "x &= -(test == 0);"
11609 ;; back to conditional branch sequences if zero-displacement branches
11610 ;; are enabled.
11611 ;; FIXME: These patterns can be removed when conditional execution patterns
11612 ;; are implemented, since ifcvt will not perform these optimizations if
11613 ;; conditional execution is supported.
11614 (define_insn "*cset_zero"
11615   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11616         (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11617                          (const_int -1))
11618                 (match_operand:SI 2 "arith_reg_operand" "0")))]
11619   "TARGET_SH1 && TARGET_ZDCBRANCH"
11621   return       "bf      0f"     "\n"
11622          "      mov     #0,%0"  "\n"
11623          "0:";
11625   [(set_attr "type" "arith") ;; poor approximation
11626    (set_attr "length" "4")])
11628 (define_insn "*cset_zero"
11629   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11630         (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11631                          (match_operand:SI 2 "arith_reg_operand" "0")
11632                          (const_int 0)))]
11633   "TARGET_SH1 && TARGET_ZDCBRANCH"
11635   return       "bt      0f"     "\n"
11636          "      mov     #0,%0"  "\n"
11637          "0:";
11639   [(set_attr "type" "arith") ;; poor approximation
11640    (set_attr "length" "4")])
11642 (define_expand "cstoresf4"
11643   [(set (match_operand:SI 0 "register_operand" "=r")
11644         (match_operator:SI 1 "sh_float_comparison_operator"
11645          [(match_operand:SF 2 "arith_operand" "")
11646           (match_operand:SF 3 "arith_operand" "")]))]
11647   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11649   if (TARGET_SHMEDIA)
11650     {
11651       emit_insn (gen_cstore4_media (operands[0], operands[1],
11652                                     operands[2], operands[3]));
11653       DONE;
11654     }
11656   if (! currently_expanding_to_rtl)
11657     FAIL;
11658    
11659   sh_emit_compare_and_set (operands, SFmode);
11660   DONE;
11663 (define_expand "cstoredf4"
11664   [(set (match_operand:SI 0 "register_operand" "=r")
11665         (match_operator:SI 1 "sh_float_comparison_operator"
11666          [(match_operand:DF 2 "arith_operand" "")
11667           (match_operand:DF 3 "arith_operand" "")]))]
11668   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11670   if (TARGET_SHMEDIA)
11671     {
11672       emit_insn (gen_cstore4_media (operands[0], operands[1],
11673                                     operands[2], operands[3]));
11674       DONE;
11675     }
11677   if (! currently_expanding_to_rtl)
11678     FAIL;
11679    
11680   sh_emit_compare_and_set (operands, DFmode);
11681   DONE;
11684 ;; -------------------------------------------------------------------------
11685 ;; Instructions to cope with inline literal tables
11686 ;; -------------------------------------------------------------------------
11688 ;; 2 byte integer in line
11689 (define_insn "consttable_2"
11690  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11691                     (match_operand 1 "" "")]
11692                    UNSPECV_CONST2)]
11693  ""
11695   if (operands[1] != const0_rtx)
11696     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11697   return "";
11699  [(set_attr "length" "2")
11700  (set_attr "in_delay_slot" "no")])
11702 ;; 4 byte integer in line
11703 (define_insn "consttable_4"
11704  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11705                     (match_operand 1 "" "")]
11706                    UNSPECV_CONST4)]
11707  ""
11709   if (operands[1] != const0_rtx)
11710     {
11711       assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11712       mark_symbol_refs_as_used (operands[0]);
11713     }
11714   return "";
11716  [(set_attr "length" "4")
11717   (set_attr "in_delay_slot" "no")])
11719 ;; 8 byte integer in line
11720 (define_insn "consttable_8"
11721  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11722                     (match_operand 1 "" "")]
11723                    UNSPECV_CONST8)]
11724  ""
11726   if (operands[1] != const0_rtx)
11727     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11728   return "";
11730  [(set_attr "length" "8")
11731   (set_attr "in_delay_slot" "no")])
11733 ;; 4 byte floating point
11734 (define_insn "consttable_sf"
11735  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11736                     (match_operand 1 "" "")]
11737                    UNSPECV_CONST4)]
11738  ""
11740   if (operands[1] != const0_rtx)
11741     {
11742       REAL_VALUE_TYPE d;
11743       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11744       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11745     }
11746   return "";
11748  [(set_attr "length" "4")
11749   (set_attr "in_delay_slot" "no")])
11751 ;; 8 byte floating point
11752 (define_insn "consttable_df"
11753  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11754                     (match_operand 1 "" "")]
11755                    UNSPECV_CONST8)]
11756  ""
11758   if (operands[1] != const0_rtx)
11759     {
11760       REAL_VALUE_TYPE d;
11761       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11762       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11763     }
11764   return "";
11766  [(set_attr "length" "8")
11767   (set_attr "in_delay_slot" "no")])
11769 ;; Alignment is needed for some constant tables; it may also be added for
11770 ;; Instructions at the start of loops, or after unconditional branches.
11771 ;; ??? We would get more accurate lengths if we did instruction
11772 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11773 ;; here is too conservative.
11775 ;; align to a two byte boundary
11776 (define_expand "align_2"
11777  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11778  ""
11779  "")
11781 ;; Align to a four byte boundary.
11782 ;; align_4 and align_log are instructions for the starts of loops, or
11783 ;; after unconditional branches, which may take up extra room.
11784 (define_expand "align_4"
11785  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11786  ""
11787  "")
11789 ;; Align to a cache line boundary.
11790 (define_insn "align_log"
11791  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11792  ""
11793  ""
11794  [(set_attr "length" "0")
11795   (set_attr "in_delay_slot" "no")])
11797 ;; Emitted at the end of the literal table, used to emit the
11798 ;; 32bit branch labels if needed.
11799 (define_insn "consttable_end"
11800   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11801   ""
11803   return output_jump_label_table ();
11805   [(set_attr "in_delay_slot" "no")])
11807 ;; Emitted at the end of the window in the literal table.
11808 (define_insn "consttable_window_end"
11809   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11810   ""
11811   ""
11812   [(set_attr "length" "0")
11813    (set_attr "in_delay_slot" "no")])
11815 ;; -------------------------------------------------------------------------
11816 ;; Minimum / maximum operations.
11817 ;; -------------------------------------------------------------------------
11819 ;; The SH2A clips.b and clips.w insns do a signed min-max function.  If smin
11820 ;; and smax standard name patterns are defined, they will be used during
11821 ;; initial expansion and combine will then be able to form the actual min-max
11822 ;; pattern.
11823 ;; The clips.b and clips.w set the SR.CS bit if the value in the register is
11824 ;; clipped, but there is currently no way of making use of this information.
11825 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11826 (define_expand "<code>si3"
11827   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11828                    (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11829                                  (match_operand 2 "const_int_operand")))
11830               (clobber (reg:SI T_REG))])]
11831   "TARGET_SH2A"
11833   /* Force the comparison value into a register, because greater-than
11834      comparisons can work only on registers.  Combine will be able to pick up
11835      the constant value from the REG_EQUAL note when trying to form a min-max
11836      pattern.  */
11837   operands[2] = force_reg (SImode, operands[2]);
11840 ;; Convert
11841 ;;      smax (smin (...))
11842 ;; to
11843 ;;      smin (smax (...))
11844 (define_insn_and_split "*clips"
11845   [(set (match_operand:SI 0 "arith_reg_dest")
11846         (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
11847                           (match_operand 2 "clips_max_const_int"))
11848                  (match_operand 3 "clips_min_const_int")))]
11849   "TARGET_SH2A"
11850   "#"
11851   "&& 1"
11852   [(set (match_dup 0)
11853         (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
11855 (define_insn "*clips"
11856   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11857         (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
11858                           (match_operand 2 "clips_min_const_int"))
11859                  (match_operand 3 "clips_max_const_int")))]
11860   "TARGET_SH2A"
11862   if (INTVAL (operands[3]) == 127)
11863     return "clips.b     %0";
11864   else if (INTVAL (operands[3]) == 32767)
11865     return "clips.w     %0";
11866   else
11867     gcc_unreachable ();
11869   [(set_attr "type" "arith")])
11871 ;; If the expanded smin or smax patterns were not combined, split them into
11872 ;; a compare and branch sequence, because there are no real smin or smax
11873 ;; insns.
11874 (define_insn_and_split "*<code>si3"
11875   [(set (match_operand:SI 0 "arith_reg_dest")
11876         (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11877                       (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
11878    (clobber (reg:SI T_REG))]
11879   "TARGET_SH2A && can_create_pseudo_p ()"
11880   "#"
11881   "&& 1"
11882   [(const_int 0)]
11884   rtx skip_label = gen_label_rtx ();
11885   emit_move_insn (operands[0], operands[1]);
11887   rtx cmp_val = operands[2];
11888   if (satisfies_constraint_M (cmp_val))
11889     cmp_val = const0_rtx;
11891   emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
11892   emit_jump_insn (<CODE> == SMIN
11893                             ? gen_branch_false (skip_label)
11894                             : gen_branch_true (skip_label));
11896   emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
11897   DONE;
11900 ;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
11901 ;; with a register and a constant.
11902 ;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
11903 ;; clipped, but there is currently no way of making use of this information.
11904 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11905 (define_expand "uminsi3"
11906   [(set (match_operand:SI 0 "arith_reg_dest")
11907         (umin:SI (match_operand:SI 1 "arith_reg_operand")
11908                  (match_operand 2 "const_int_operand")))]
11909   "TARGET_SH2A"
11911   if (INTVAL (operands[2]) == 1)
11912     {
11913       emit_insn (gen_clipu_one (operands[0], operands[1]));
11914       DONE;
11915     }
11916   else if (! clipu_max_const_int (operands[2], VOIDmode))
11917     FAIL;
11920 (define_insn "*clipu"
11921   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11922         (umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
11923                  (match_operand 2 "clipu_max_const_int")))]
11924   "TARGET_SH2A"
11926   if (INTVAL (operands[2]) == 255)
11927     return "clipu.b     %0";
11928   else if (INTVAL (operands[2]) == 65535)
11929     return "clipu.w     %0";
11930   else
11931     gcc_unreachable ();
11933   [(set_attr "type" "arith")])
11935 (define_insn_and_split "clipu_one"
11936   [(set (match_operand:SI 0 "arith_reg_dest")
11937         (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
11938    (clobber (reg:SI T_REG))]
11939   "TARGET_SH2A"
11940   "#"
11941   "&& can_create_pseudo_p ()"
11942   [(const_int 0)]
11944   emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
11945   emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
11946   DONE;
11949 ;; -------------------------------------------------------------------------
11950 ;; Misc
11951 ;; -------------------------------------------------------------------------
11953 ;; String/block move insn.
11955 (define_expand "movmemsi"
11956   [(parallel [(set (mem:BLK (match_operand:BLK 0))
11957                    (mem:BLK (match_operand:BLK 1)))
11958               (use (match_operand:SI 2 "nonmemory_operand"))
11959               (use (match_operand:SI 3 "immediate_operand"))
11960               (clobber (reg:SI PR_REG))
11961               (clobber (reg:SI R4_REG))
11962               (clobber (reg:SI R5_REG))
11963               (clobber (reg:SI R0_REG))])]
11964   "TARGET_SH1 && ! TARGET_SH5"
11966   if (expand_block_move (operands))
11967     DONE;
11968   else
11969     FAIL;
11972 (define_insn "block_move_real"
11973   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11974                    (mem:BLK (reg:SI R5_REG)))
11975               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11976               (clobber (reg:SI PR_REG))
11977               (clobber (reg:SI R0_REG))])]
11978   "TARGET_SH1 && ! TARGET_HARD_SH4"
11979   "jsr  @%0%#"
11980   [(set_attr "type" "sfunc")
11981    (set_attr "needs_delay_slot" "yes")])
11983 (define_insn "block_lump_real"
11984   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11985                    (mem:BLK (reg:SI R5_REG)))
11986               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11987               (use (reg:SI R6_REG))
11988               (clobber (reg:SI PR_REG))
11989               (clobber (reg:SI T_REG))
11990               (clobber (reg:SI R4_REG))
11991               (clobber (reg:SI R5_REG))
11992               (clobber (reg:SI R6_REG))
11993               (clobber (reg:SI R0_REG))])]
11994   "TARGET_SH1 && ! TARGET_HARD_SH4"
11995   "jsr  @%0%#"
11996   [(set_attr "type" "sfunc")
11997    (set_attr "needs_delay_slot" "yes")])
11999 (define_insn "block_move_real_i4"
12000   [(parallel [(set (mem:BLK (reg:SI R4_REG))
12001                    (mem:BLK (reg:SI R5_REG)))
12002               (use (match_operand:SI 0 "arith_reg_operand" "r"))
12003               (clobber (reg:SI PR_REG))
12004               (clobber (reg:SI R0_REG))
12005               (clobber (reg:SI R1_REG))
12006               (clobber (reg:SI R2_REG))])]
12007   "TARGET_HARD_SH4"
12008   "jsr  @%0%#"
12009   [(set_attr "type" "sfunc")
12010    (set_attr "needs_delay_slot" "yes")])
12012 (define_insn "block_lump_real_i4"
12013   [(parallel [(set (mem:BLK (reg:SI R4_REG))
12014                    (mem:BLK (reg:SI R5_REG)))
12015               (use (match_operand:SI 0 "arith_reg_operand" "r"))
12016               (use (reg:SI R6_REG))
12017               (clobber (reg:SI PR_REG))
12018               (clobber (reg:SI T_REG))
12019               (clobber (reg:SI R4_REG))
12020               (clobber (reg:SI R5_REG))
12021               (clobber (reg:SI R6_REG))
12022               (clobber (reg:SI R0_REG))
12023               (clobber (reg:SI R1_REG))
12024               (clobber (reg:SI R2_REG))
12025               (clobber (reg:SI R3_REG))])]
12026   "TARGET_HARD_SH4"
12027   "jsr  @%0%#"
12028   [(set_attr "type" "sfunc")
12029    (set_attr "needs_delay_slot" "yes")])
12031 ;; byte compare pattern
12032 ;; temp = a ^ b;
12033 ;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
12034 (define_insn "cmpstr_t"
12035   [(set (reg:SI T_REG)
12036         (eq:SI (and:SI
12037                  (and:SI
12038                    (and:SI
12039                      (zero_extract:SI
12040                        (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
12041                                (match_operand:SI 1 "arith_reg_operand" "r"))
12042                        (const_int 8) (const_int 0))
12043                      (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12044                                       (const_int 8) (const_int 8)))
12045                     (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12046                                      (const_int 8) (const_int 16)))
12047                  (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12048                                   (const_int 8) (const_int 24)))
12049                (const_int 0)))]
12050   "TARGET_SH1"
12051   "cmp/str      %0,%1"
12052   [(set_attr "type" "mt_group")])
12054 (define_expand "cmpstrsi"
12055   [(set (match_operand:SI 0 "register_operand")
12056         (compare:SI (match_operand:BLK 1 "memory_operand")
12057                     (match_operand:BLK 2 "memory_operand")))
12058    (use (match_operand 3 "immediate_operand"))]
12059   "TARGET_SH1 && optimize"
12061   if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
12062     DONE;
12063   else
12064     FAIL;
12067 (define_expand "cmpstrnsi"
12068   [(set (match_operand:SI 0 "register_operand")
12069         (compare:SI (match_operand:BLK 1 "memory_operand")
12070                     (match_operand:BLK 2 "memory_operand")))
12071    (use (match_operand:SI 3 "immediate_operand"))
12072    (use (match_operand:SI 4 "immediate_operand"))]
12073   "TARGET_SH1 && optimize"
12075   if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
12076     DONE;
12077   else
12078     FAIL;
12081 (define_expand "strlensi"
12082   [(set (match_operand:SI 0 "register_operand")
12083         (unspec:SI [(match_operand:BLK 1 "memory_operand")
12084                    (match_operand:SI 2 "immediate_operand")
12085                    (match_operand:SI 3 "immediate_operand")]
12086                   UNSPEC_BUILTIN_STRLEN))]
12087   "TARGET_SH1 && optimize"
12089  if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
12090    DONE;
12091  else
12092    FAIL;
12096 ;; -------------------------------------------------------------------------
12097 ;; Floating point instructions.
12098 ;; -------------------------------------------------------------------------
12100 ;; ??? All patterns should have a type attribute.
12102 (define_expand "movpsi"
12103   [(set (match_operand:PSI 0 "register_operand" "")
12104         (match_operand:PSI 1 "general_movsrc_operand" ""))]
12105   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12106   "")
12108 ;; The c / m alternative is a fake to guide reload to load directly into
12109 ;; fpscr, since reload doesn't know how to use post-increment.
12110 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
12111 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
12112 ;; predicate after reload.
12113 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
12114 ;; like a mac -> gpr move.
12115 (define_insn "fpu_switch"
12116   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
12117         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
12118   "TARGET_SH2E
12119    && (! reload_completed
12120        || true_regnum (operands[0]) != FPSCR_REG
12121        || !MEM_P (operands[1])
12122        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
12123   "@
12124         ! precision stays the same
12125         lds.l   %1,fpscr
12126         mov.l   %1,%0
12127         #
12128         lds     %1,fpscr
12129         mov     %1,%0
12130         mov.l   %1,%0
12131         sts     fpscr,%0
12132         sts.l   fpscr,%0"
12133   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
12134    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,
12135                      mac_gp,fstore")])
12137 (define_peephole2
12138   [(set (reg:PSI FPSCR_REG)
12139         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
12140   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
12141   [(const_int 0)]
12143   rtx fpscr, mem, new_insn;
12145   fpscr = SET_DEST (PATTERN (curr_insn));
12146   mem = SET_SRC (PATTERN (curr_insn));
12147   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
12149   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
12150   add_reg_note (new_insn, REG_INC, operands[0]);
12151   DONE;
12154 (define_split
12155   [(set (reg:PSI FPSCR_REG)
12156         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
12157   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
12158    && (flag_peephole2 ? epilogue_completed : reload_completed)"
12159   [(const_int 0)]
12161   rtx fpscr, mem, new_insn;
12163   fpscr = SET_DEST (PATTERN (curr_insn));
12164   mem = SET_SRC (PATTERN (curr_insn));
12165   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
12167   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
12168   add_reg_note (new_insn, REG_INC, operands[0]);
12170   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
12171     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
12172   DONE;
12175 ;; ??? This uses the fp unit, but has no type indicating that.
12176 ;; If we did that, this would either give a bogus latency or introduce
12177 ;; a bogus FIFO constraint.
12178 ;; Since this insn is currently only used for prologues/epilogues,
12179 ;; it is probably best to claim no function unit, which matches the
12180 ;; current setting.
12181 (define_insn "toggle_sz"
12182   [(set (reg:PSI FPSCR_REG)
12183         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
12184   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12185   "fschg"
12186   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
12188 ;; There's no way we can use it today, since optimize mode switching
12189 ;; doesn't enable us to know from which mode we're switching to the
12190 ;; mode it requests, to tell whether we can use a relative mode switch
12191 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
12192 ;; memory).
12193 (define_insn "toggle_pr"
12194   [(set (reg:PSI FPSCR_REG)
12195         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
12196   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
12197   "fpchg"
12198   [(set_attr "type" "fpscr_toggle")])
12200 (define_expand "addsf3"
12201   [(set (match_operand:SF 0 "fp_arith_reg_operand")
12202         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
12203                  (match_operand:SF 2 "fp_arith_reg_operand")))]
12204   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12206   if (TARGET_SH2E)
12207     {
12208       expand_sf_binop (&gen_addsf3_i, operands);
12209       DONE;
12210     }
12213 (define_insn "*addsf3_media"
12214   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12215         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12216                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12217   "TARGET_SHMEDIA_FPU"
12218   "fadd.s       %1, %2, %0"
12219   [(set_attr "type" "fparith_media")])
12221 (define_insn_and_split "unary_sf_op"
12222   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12223         (vec_select:V2SF
12224          (vec_concat:V2SF
12225           (vec_select:SF
12226            (match_dup 0)
12227            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
12228           (match_operator:SF 2 "unary_float_operator"
12229             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12230                             (parallel [(match_operand 4
12231                                         "const_int_operand" "n")]))]))
12232          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
12233   "TARGET_SHMEDIA_FPU"
12234   "#"
12235   "TARGET_SHMEDIA_FPU && reload_completed"
12236   [(set (match_dup 5) (match_dup 6))]
12238   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12239   rtx op1 = gen_rtx_REG (SFmode,
12240                          (true_regnum (operands[1])
12241                           + (INTVAL (operands[4]) ^ endian)));
12243   operands[7] = gen_rtx_REG (SFmode,
12244                              (true_regnum (operands[0])
12245                               + (INTVAL (operands[3]) ^ endian)));
12246   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
12248   [(set_attr "type" "fparith_media")])
12250 (define_insn_and_split "binary_sf_op0"
12251   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12252         (vec_concat:V2SF
12253           (match_operator:SF 3 "binary_float_operator"
12254             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12255                             (parallel [(const_int 0)]))
12256              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12257                             (parallel [(const_int 0)]))])
12258           (vec_select:SF
12259            (match_dup 0)
12260            (parallel [(const_int 1)]))))]
12261   "TARGET_SHMEDIA_FPU"
12262   "#"
12263   "&& reload_completed"
12264   [(set (match_dup 4) (match_dup 5))]
12266   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12267   rtx op1 = gen_rtx_REG (SFmode,
12268                          true_regnum (operands[1]) + endian);
12269   rtx op2 = gen_rtx_REG (SFmode,
12270                          true_regnum (operands[2]) + endian);
12272   operands[4] = gen_rtx_REG (SFmode,
12273                              true_regnum (operands[0]) + endian);
12274   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12276   [(set_attr "type" "fparith_media")])
12278 (define_insn_and_split "binary_sf_op1"
12279   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12280         (vec_concat:V2SF
12281           (vec_select:SF
12282            (match_dup 0)
12283            (parallel [(const_int 0)]))
12284           (match_operator:SF 3 "binary_float_operator"
12285             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12286                             (parallel [(const_int 1)]))
12287              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12288                             (parallel [(const_int 1)]))])))]
12289   "TARGET_SHMEDIA_FPU"
12290   "#"
12291   "&& reload_completed"
12292   [(set (match_dup 4) (match_dup 5))]
12294   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12295   rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
12296   rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
12298   operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
12299   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12301   [(set_attr "type" "fparith_media")])
12303 (define_insn "addsf3_i"
12304   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12305         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12306                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12307    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12308   "TARGET_SH2E"
12309   "fadd %2,%0"
12310   [(set_attr "type" "fp")
12311    (set_attr "fp_mode" "single")])
12313 (define_expand "subsf3"
12314   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12315         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12316                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12317   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12319   if (TARGET_SH2E)
12320     {
12321       expand_sf_binop (&gen_subsf3_i, operands);
12322       DONE;
12323     }
12326 (define_insn "*subsf3_media"
12327   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12328         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12329                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12330   "TARGET_SHMEDIA_FPU"
12331   "fsub.s       %1, %2, %0"
12332   [(set_attr "type" "fparith_media")])
12334 (define_insn "subsf3_i"
12335   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12336         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12337                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12338    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12339   "TARGET_SH2E"
12340   "fsub %2,%0"
12341   [(set_attr "type" "fp")
12342    (set_attr "fp_mode" "single")])
12344 (define_expand "mulsf3"
12345   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12346         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12347                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12348   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12350   if (TARGET_SH2E)
12351     {
12352       emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
12353                  get_fpscr_rtx ()));
12354       DONE;
12355     }
12358 (define_insn "*mulsf3_media"
12359   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12360         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12361                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12362   "TARGET_SHMEDIA_FPU"
12363   "fmul.s       %1, %2, %0"
12364   [(set_attr "type" "fparith_media")])
12366 (define_insn "mulsf3_i"
12367   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12368         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12369                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12370    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12371   "TARGET_SH2E"
12372   "fmul %2,%0"
12373   [(set_attr "type" "fp")
12374    (set_attr "fp_mode" "single")])
12376 ;; FMA (fused multiply-add) patterns
12377 (define_expand "fmasf4"
12378   [(set (match_operand:SF 0 "fp_arith_reg_operand")
12379         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
12380                 (match_operand:SF 2 "fp_arith_reg_operand")
12381                 (match_operand:SF 3 "fp_arith_reg_operand")))]
12382   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12384   if (TARGET_SH2E)
12385     {
12386       emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12387                                   operands[3], get_fpscr_rtx ()));
12388       DONE;
12389     }
12392 (define_insn "fmasf4_i"
12393   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12394         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12395                 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12396                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
12397    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
12398   "TARGET_SH2E"
12399   "fmac %1,%2,%0"
12400   [(set_attr "type" "fp")
12401    (set_attr "fp_mode" "single")])
12403 (define_insn "fmasf4_media"
12404   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12405         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12406                 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12407                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12408   "TARGET_SHMEDIA_FPU"
12409   "fmac.s %1, %2, %0"
12410   [(set_attr "type" "fparith_media")])
12412 ;; For some cases such as 'a * b + a' the FMA pattern is not generated by
12413 ;; previous transformations.  If FMA is generally allowed, let the combine
12414 ;; pass utilize it.
12415 (define_insn_and_split "*fmasf4"
12416   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12417         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
12418                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12419                  (match_operand:SF 3 "arith_reg_operand" "0")))
12420    (use (match_operand:PSI 4 "fpscr_operand"))]
12421   "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
12422   "fmac %1,%2,%0"
12423   "&& can_create_pseudo_p ()"
12424   [(parallel [(set (match_dup 0)
12425                    (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
12426               (use (match_dup 4))])]
12428   /* Change 'b * a + a' into 'a * b + a'.
12429      This is better for register allocation.  */
12430   if (REGNO (operands[2]) == REGNO (operands[3]))
12431     {
12432       rtx tmp = operands[1];
12433       operands[1] = operands[2];
12434       operands[2] = tmp;
12435     }
12437   [(set_attr "type" "fp")
12438    (set_attr "fp_mode" "single")])
12440 (define_insn "*fmasf4_media"
12441   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12442         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12443                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12444                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12445   "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
12446   "fmac.s %1, %2, %0"
12447   [(set_attr "type" "fparith_media")])
12449 (define_expand "divsf3"
12450   [(set (match_operand:SF 0 "fp_arith_reg_operand")
12451         (div:SF (match_operand:SF 1 "fp_arith_reg_operand")
12452                 (match_operand:SF 2 "fp_arith_reg_operand")))]
12453   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12455   if (TARGET_SH2E)
12456     {
12457       expand_sf_binop (&gen_divsf3_i, operands);
12458       DONE;
12459     }
12462 (define_insn "*divsf3_media"
12463   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12464         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12465                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12466   "TARGET_SHMEDIA_FPU"
12467   "fdiv.s       %1, %2, %0"
12468   [(set_attr "type" "fdiv_media")])
12470 (define_insn "divsf3_i"
12471   [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
12472         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12473                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12474    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12475   "TARGET_SH2E"
12476   "fdiv %2,%0"
12477   [(set_attr "type" "fdiv")
12478    (set_attr "fp_mode" "single")])
12480 (define_insn "floatdisf2"
12481   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12482         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12483   "TARGET_SHMEDIA_FPU"
12484   "float.qs %1, %0"
12485   [(set_attr "type" "fpconv_media")])
12487 (define_expand "floatsisf2"
12488   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12489         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
12490   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12492   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12493     {
12494       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1],
12495                                        get_fpscr_rtx ()));
12496       DONE;
12497     }
12500 (define_insn "*floatsisf2_media"
12501   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12502         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12503   "TARGET_SHMEDIA_FPU"
12504   "float.ls     %1, %0"
12505   [(set_attr "type" "fpconv_media")])
12507 (define_insn "floatsisf2_i4"
12508   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12509         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
12510    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12511   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12512   "float        %1,%0"
12513   [(set_attr "type" "fp")
12514    (set_attr "fp_mode" "single")])
12516 (define_insn "*floatsisf2_ie"
12517   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12518         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
12519   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12520   "float        %1,%0"
12521   [(set_attr "type" "fp")])
12523 (define_insn "fix_truncsfdi2"
12524   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12525         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12526   "TARGET_SHMEDIA_FPU"
12527   "ftrc.sq %1, %0"
12528   [(set_attr "type" "fpconv_media")])
12530 (define_expand "fix_truncsfsi2"
12531   [(set (match_operand:SI 0 "fpul_operand" "=y")
12532         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12533   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12535   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12536     {
12537       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1],
12538                                            get_fpscr_rtx ()));
12539       DONE;
12540     }
12543 (define_insn "*fix_truncsfsi2_media"
12544   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12545         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12546   "TARGET_SHMEDIA_FPU"
12547   "ftrc.sl      %1, %0"
12548   [(set_attr "type" "fpconv_media")])
12550 (define_insn "fix_truncsfsi2_i4"
12551   [(set (match_operand:SI 0 "fpul_operand" "=y")
12552         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12553    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12554   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12555   "ftrc %1,%0"
12556   [(set_attr "type" "ftrc_s")
12557    (set_attr "fp_mode" "single")])
12559 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
12560 ;; fix_truncsfsi2_i4.
12561 ;; (define_insn "fix_truncsfsi2_i4_2"
12562 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12563 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12564 ;;   (use (reg:PSI FPSCR_REG))
12565 ;;   (clobber (reg:SI FPUL_REG))]
12566 ;;  "TARGET_SH4"
12567 ;;  "#"
12568 ;;  [(set_attr "length" "4")
12569 ;;   (set_attr "fp_mode" "single")])
12571 ;;(define_split
12572 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12573 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12574 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
12575 ;;   (clobber (reg:SI FPUL_REG))]
12576 ;;  "TARGET_SH4"
12577 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12578 ;;            (use (match_dup 2))])
12579 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
12581 (define_insn "*fixsfsi"
12582   [(set (match_operand:SI 0 "fpul_operand" "=y")
12583         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12584   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12585   "ftrc %1,%0"
12586   [(set_attr "type" "fp")])
12588 (define_insn "cmpgtsf_t"
12589   [(set (reg:SI T_REG)
12590         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12591                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12592   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12593   "fcmp/gt      %1,%0"
12594   [(set_attr "type" "fp_cmp")
12595    (set_attr "fp_mode" "single")])
12597 (define_insn "cmpeqsf_t"
12598   [(set (reg:SI T_REG)
12599         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12600                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12601   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12602   "fcmp/eq      %1,%0"
12603   [(set_attr "type" "fp_cmp")
12604    (set_attr "fp_mode" "single")])
12606 (define_insn "ieee_ccmpeqsf_t"
12607   [(set (reg:SI T_REG)
12608         (ior:SI (reg:SI T_REG)
12609                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12610                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
12611   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12613   return output_ieee_ccmpeq (insn, operands);
12615   [(set_attr "length" "4")])
12618 (define_insn "cmpgtsf_t_i4"
12619   [(set (reg:SI T_REG)
12620         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12621                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12622    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12623   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12624   "fcmp/gt      %1,%0"
12625   [(set_attr "type" "fp_cmp")
12626    (set_attr "fp_mode" "single")])
12628 (define_insn "cmpeqsf_t_i4"
12629   [(set (reg:SI T_REG)
12630         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12631                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12632    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12633   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12634   "fcmp/eq      %1,%0"
12635   [(set_attr "type" "fp_cmp")
12636    (set_attr "fp_mode" "single")])
12638 (define_insn "*ieee_ccmpeqsf_t_4"
12639   [(set (reg:SI T_REG)
12640         (ior:SI (reg:SI T_REG)
12641                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12642                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12643    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12644   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12646   return output_ieee_ccmpeq (insn, operands);
12648   [(set_attr "length" "4")
12649    (set_attr "fp_mode" "single")])
12651 (define_insn "cmpeqsf_media"
12652   [(set (match_operand:SI 0 "register_operand" "=r")
12653         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12654                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12655   "TARGET_SHMEDIA_FPU"
12656   "fcmpeq.s     %1, %2, %0"
12657   [(set_attr "type" "fcmp_media")])
12659 (define_insn "cmpgtsf_media"
12660   [(set (match_operand:SI 0 "register_operand" "=r")
12661         (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12662                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12663   "TARGET_SHMEDIA_FPU"
12664   "fcmpgt.s     %1, %2, %0"
12665   [(set_attr "type" "fcmp_media")])
12667 (define_insn "cmpgesf_media"
12668   [(set (match_operand:SI 0 "register_operand" "=r")
12669         (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12670                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12671   "TARGET_SHMEDIA_FPU"
12672   "fcmpge.s     %1, %2, %0"
12673   [(set_attr "type" "fcmp_media")])
12675 (define_insn "cmpunsf_media"
12676   [(set (match_operand:SI 0 "register_operand" "=r")
12677         (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12678                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12679   "TARGET_SHMEDIA_FPU"
12680   "fcmpun.s     %1, %2, %0"
12681   [(set_attr "type" "fcmp_media")])
12683 (define_expand "cbranchsf4"
12684   [(set (pc)
12685         (if_then_else (match_operator 0 "sh_float_comparison_operator"
12686                        [(match_operand:SF 1 "arith_operand" "")
12687                         (match_operand:SF 2 "arith_operand" "")])
12688                       (match_operand 3 "" "")
12689                       (pc)))]
12690   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12692   if (TARGET_SHMEDIA)
12693     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12694                                           operands[3]));
12695   else
12696     sh_emit_compare_and_branch (operands, SFmode);
12697   DONE;
12700 (define_expand "negsf2"
12701   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12702         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12703   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12705   if (TARGET_SH2E)
12706     {
12707       expand_sf_unop (&gen_negsf2_i, operands);
12708       DONE;
12709     }
12712 (define_insn "*negsf2_media"
12713   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12714         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12715   "TARGET_SHMEDIA_FPU"
12716   "fneg.s       %1, %0"
12717   [(set_attr "type" "fmove_media")])
12719 (define_insn "negsf2_i"
12720   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12721         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12722    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12723   "TARGET_SH2E"
12724   "fneg %0"
12725   [(set_attr "type" "fmove")
12726    (set_attr "fp_mode" "single")])
12728 (define_expand "sqrtsf2"
12729   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12730         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12731   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12733   if (TARGET_SH3E)
12734     {
12735       expand_sf_unop (&gen_sqrtsf2_i, operands);
12736       DONE;
12737     }
12740 (define_insn "*sqrtsf2_media"
12741   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12742         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12743   "TARGET_SHMEDIA_FPU"
12744   "fsqrt.s      %1, %0"
12745   [(set_attr "type" "fdiv_media")])
12747 (define_insn "sqrtsf2_i"
12748   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12749         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12750    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12751   "TARGET_SH3E"
12752   "fsqrt        %0"
12753   [(set_attr "type" "fdiv")
12754    (set_attr "fp_mode" "single")])
12756 (define_insn "rsqrtsf2"
12757   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12758         (div:SF (match_operand:SF 1 "immediate_operand" "i")
12759                 (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
12760    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12761   "TARGET_FPU_ANY && TARGET_FSRRA
12762    && operands[1] == CONST1_RTX (SFmode)"
12763   "fsrra        %0"
12764   [(set_attr "type" "fsrra")
12765    (set_attr "fp_mode" "single")])
12767 ;; When the sincos pattern is defined, the builtin functions sin and cos
12768 ;; will be expanded to the sincos pattern and one of the output values will
12769 ;; remain unused.
12770 (define_expand "sincossf3"
12771   [(set (match_operand:SF 0 "nonimmediate_operand")
12772         (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12773    (set (match_operand:SF 1 "nonimmediate_operand")
12774         (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
12775   "TARGET_FPU_ANY && TARGET_FSCA"
12777   rtx scaled = gen_reg_rtx (SFmode);
12778   rtx truncated = gen_reg_rtx (SImode);
12779   rtx fsca = gen_reg_rtx (V2SFmode);
12780   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12782   emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12783   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12784   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12785                           get_fpscr_rtx ()));
12787   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12788   emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
12789   DONE;
12792 (define_insn_and_split "fsca"
12793   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12794         (vec_concat:V2SF
12795          (unspec:SF [(mult:SF
12796                       (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12797                       (match_operand:SF 2 "fsca_scale_factor" "i"))
12798                     ] UNSPEC_FSINA)
12799          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12800                     ] UNSPEC_FCOSA)))
12801    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12802   "TARGET_FPU_ANY && TARGET_FSCA"
12803   "fsca fpul,%d0"
12804   "&& !fpul_operand (operands[1], SImode)"
12805   [(const_int 0)]
12807   /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12808      to a simple reg, otherwise reload will have trouble reloading the
12809      pseudo into fpul.  */
12810   rtx x = XEXP (operands[1], 0);
12811   while (x != NULL_RTX && !fpul_operand (x, SImode))
12812     {
12813       gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12814       x = XEXP (x, 0);
12815     }
12817   gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12818   emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12819   DONE;
12821   [(set_attr "type" "fsca")
12822    (set_attr "fp_mode" "single")])
12824 (define_expand "abssf2"
12825   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12826         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12827   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12829   if (TARGET_SH2E)
12830     {
12831       expand_sf_unop (&gen_abssf2_i, operands);
12832       DONE;
12833     }
12836 (define_insn "*abssf2_media"
12837   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12838         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12839   "TARGET_SHMEDIA_FPU"
12840   "fabs.s       %1, %0"
12841   [(set_attr "type" "fmove_media")])
12843 (define_insn "abssf2_i"
12844   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12845         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12846    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12847   "TARGET_SH2E"
12848   "fabs %0"
12849   [(set_attr "type" "fmove")
12850    (set_attr "fp_mode" "single")])
12852 (define_expand "adddf3"
12853   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12854         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12855                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12856   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12858   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12859     {
12860       expand_df_binop (&gen_adddf3_i, operands);
12861       DONE;
12862     }
12865 (define_insn "*adddf3_media"
12866   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12867         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12868                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12869   "TARGET_SHMEDIA_FPU"
12870   "fadd.d       %1, %2, %0"
12871   [(set_attr "type" "dfparith_media")])
12873 (define_insn "adddf3_i"
12874   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12875         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12876                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12877    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12878   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12879   "fadd %2,%0"
12880   [(set_attr "type" "dfp_arith")
12881    (set_attr "fp_mode" "double")])
12883 (define_expand "subdf3"
12884   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12885         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12886                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12887   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12889   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12890     {
12891       expand_df_binop (&gen_subdf3_i, operands);
12892       DONE;
12893     }
12896 (define_insn "*subdf3_media"
12897   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12898         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12899                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12900   "TARGET_SHMEDIA_FPU"
12901   "fsub.d       %1, %2, %0"
12902   [(set_attr "type" "dfparith_media")])
12904 (define_insn "subdf3_i"
12905   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12906         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12907                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12908    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12909   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12910   "fsub %2,%0"
12911   [(set_attr "type" "dfp_arith")
12912    (set_attr "fp_mode" "double")])
12914 (define_expand "muldf3"
12915   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12916         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12917                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12918   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12920   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12921     {
12922       expand_df_binop (&gen_muldf3_i, operands);
12923       DONE;
12924     }
12927 (define_insn "*muldf3_media"
12928   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12929         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12930                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12931   "TARGET_SHMEDIA_FPU"
12932   "fmul.d       %1, %2, %0"
12933   [(set_attr "type" "dfmul_media")])
12935 (define_insn "muldf3_i"
12936   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12937         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12938                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12939    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12940   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12941   "fmul %2,%0"
12942   [(set_attr "type" "dfp_mul")
12943    (set_attr "fp_mode" "double")])
12945 (define_expand "divdf3"
12946   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12947         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12948                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12949   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12951   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12952     {
12953       expand_df_binop (&gen_divdf3_i, operands);
12954       DONE;
12955     }
12958 (define_insn "*divdf3_media"
12959   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12960         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12961                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12962   "TARGET_SHMEDIA_FPU"
12963   "fdiv.d       %1, %2, %0"
12964   [(set_attr "type" "dfdiv_media")])
12966 (define_insn "divdf3_i"
12967   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12968         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12969                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12970    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12971   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12972   "fdiv %2,%0"
12973   [(set_attr "type" "dfdiv")
12974    (set_attr "fp_mode" "double")])
12976 (define_insn "floatdidf2"
12977   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12978         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12979   "TARGET_SHMEDIA_FPU"
12980   "float.qd     %1, %0"
12981   [(set_attr "type" "dfpconv_media")])
12983 (define_expand "floatsidf2"
12984   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12985         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
12986   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12988   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12989     {
12990       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12991                                       get_fpscr_rtx ()));
12992       DONE;
12993     }
12996 (define_insn "*floatsidf2_media"
12997   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12998         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12999   "TARGET_SHMEDIA_FPU"
13000   "float.ld     %1, %0"
13001   [(set_attr "type" "dfpconv_media")])
13003 (define_insn "floatsidf2_i"
13004   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13005         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
13006    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13007   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13008   "float        %1,%0"
13009   [(set_attr "type" "dfp_conv")
13010    (set_attr "fp_mode" "double")])
13012 (define_insn "fix_truncdfdi2"
13013   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13014         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13015   "TARGET_SHMEDIA_FPU"
13016   "ftrc.dq      %1, %0"
13017   [(set_attr "type" "dfpconv_media")])
13019 (define_expand "fix_truncdfsi2"
13020   [(set (match_operand:SI 0 "fpul_operand" "")
13021         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13022   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13024   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13025     {
13026       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
13027                                           get_fpscr_rtx ()));
13028       DONE;
13029     }
13032 (define_insn "*fix_truncdfsi2_media"
13033   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13034         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13035   "TARGET_SHMEDIA_FPU"
13036   "ftrc.dl      %1, %0"
13037   [(set_attr "type" "dfpconv_media")])
13039 (define_insn "fix_truncdfsi2_i"
13040   [(set (match_operand:SI 0 "fpul_operand" "=y")
13041         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13042    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13043   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13044   "ftrc %1,%0"
13045   [(set_attr "type" "dfp_conv")
13046    (set_attr "dfp_comp" "no")
13047    (set_attr "fp_mode" "double")])
13049 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
13050 ;; fix_truncdfsi2_i.
13051 ;; (define_insn "fix_truncdfsi2_i4"
13052 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13053 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
13054 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
13055 ;;    (clobber (reg:SI FPUL_REG))]
13056 ;;   "TARGET_SH4"
13057 ;;   "#"
13058 ;;   [(set_attr "length" "4")
13059 ;;    (set_attr "fp_mode" "double")])
13061 ;; (define_split
13062 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13063 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
13064 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
13065 ;;    (clobber (reg:SI FPUL_REG))]
13066 ;;   "TARGET_SH4"
13067 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
13068 ;;            (use (match_dup 2))])
13069 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
13071 (define_insn "cmpgtdf_t"
13072   [(set (reg:SI T_REG)
13073         (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13074                (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13075    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13076   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13077   "fcmp/gt      %1,%0"
13078   [(set_attr "type" "dfp_cmp")
13079    (set_attr "fp_mode" "double")])
13081 (define_insn "cmpeqdf_t"
13082   [(set (reg:SI T_REG)
13083         (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13084                (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13085    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13086   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13087   "fcmp/eq      %1,%0"
13088   [(set_attr "type" "dfp_cmp")
13089    (set_attr "fp_mode" "double")])
13091 (define_insn "*ieee_ccmpeqdf_t"
13092   [(set (reg:SI T_REG)
13093         (ior:SI (reg:SI T_REG)
13094                 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13095                        (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
13096    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13097   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13099   return output_ieee_ccmpeq (insn, operands);
13101   [(set_attr "length" "4")
13102    (set_attr "fp_mode" "double")])
13104 (define_insn "cmpeqdf_media"
13105   [(set (match_operand:SI 0 "register_operand" "=r")
13106         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13107                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13108   "TARGET_SHMEDIA_FPU"
13109   "fcmpeq.d     %1,%2,%0"
13110   [(set_attr "type" "fcmp_media")])
13112 (define_insn "cmpgtdf_media"
13113   [(set (match_operand:SI 0 "register_operand" "=r")
13114         (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13115                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13116   "TARGET_SHMEDIA_FPU"
13117   "fcmpgt.d     %1,%2,%0"
13118   [(set_attr "type" "fcmp_media")])
13120 (define_insn "cmpgedf_media"
13121   [(set (match_operand:SI 0 "register_operand" "=r")
13122         (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13123                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13124   "TARGET_SHMEDIA_FPU"
13125   "fcmpge.d     %1,%2,%0"
13126   [(set_attr "type" "fcmp_media")])
13128 (define_insn "cmpundf_media"
13129   [(set (match_operand:SI 0 "register_operand" "=r")
13130         (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13131                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13132   "TARGET_SHMEDIA_FPU"
13133   "fcmpun.d     %1,%2,%0"
13134   [(set_attr "type" "fcmp_media")])
13136 (define_expand "cbranchdf4"
13137   [(set (pc)
13138         (if_then_else (match_operator 0 "sh_float_comparison_operator"
13139                        [(match_operand:DF 1 "arith_operand" "")
13140                         (match_operand:DF 2 "arith_operand" "")])
13141                       (match_operand 3 "" "")
13142                       (pc)))]
13143   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13145   if (TARGET_SHMEDIA)
13146     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13147                                           operands[3]));
13148   else
13149     sh_emit_compare_and_branch (operands, DFmode);
13150   DONE;
13153 (define_expand "negdf2"
13154   [(set (match_operand:DF 0 "fp_arith_reg_operand")
13155         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13156   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13158   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13159     {
13160       expand_df_unop (&gen_negdf2_i, operands);
13161       DONE;
13162     }
13165 (define_insn "*negdf2_media"
13166   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13167         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13168   "TARGET_SHMEDIA_FPU"
13169   "fneg.d       %1, %0"
13170   [(set_attr "type" "fmove_media")])
13172 (define_insn "negdf2_i"
13173   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13174         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13175    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13176   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13177   "fneg %0"
13178   [(set_attr "type" "fmove")
13179    (set_attr "fp_mode" "double")])
13181 (define_expand "sqrtdf2"
13182   [(set (match_operand:DF 0 "fp_arith_reg_operand")
13183         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13184   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13186   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13187     {
13188       expand_df_unop (&gen_sqrtdf2_i, operands);
13189       DONE;
13190     }
13193 (define_insn "*sqrtdf2_media"
13194   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13195         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13196   "TARGET_SHMEDIA_FPU"
13197   "fsqrt.d      %1, %0"
13198   [(set_attr "type" "dfdiv_media")])
13200 (define_insn "sqrtdf2_i"
13201   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13202         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13203    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13204   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13205   "fsqrt        %0"
13206   [(set_attr "type" "dfdiv")
13207    (set_attr "fp_mode" "double")])
13209 (define_expand "absdf2"
13210   [(set (match_operand:DF 0 "fp_arith_reg_operand")
13211         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13212   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13214   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13215     {
13216       expand_df_unop (&gen_absdf2_i, operands);
13217       DONE;
13218     }
13221 (define_insn "*absdf2_media"
13222   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13223         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13224   "TARGET_SHMEDIA_FPU"
13225   "fabs.d       %1, %0"
13226   [(set_attr "type" "fmove_media")])
13228 (define_insn "absdf2_i"
13229   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13230         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13231    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13232   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13233   "fabs %0"
13234   [(set_attr "type" "fmove")
13235    (set_attr "fp_mode" "double")])
13237 (define_expand "extendsfdf2"
13238   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13239         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
13240   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13242   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13243     {
13244       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
13245                                         get_fpscr_rtx ()));
13246       DONE;
13247     }
13250 (define_insn "*extendsfdf2_media"
13251   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13252         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13253   "TARGET_SHMEDIA_FPU"
13254   "fcnv.sd      %1, %0"
13255   [(set_attr "type" "dfpconv_media")])
13257 (define_insn "extendsfdf2_i4"
13258   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13259         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
13260    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13261   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13262   "fcnvsd  %1,%0"
13263   [(set_attr "type" "fp")
13264    (set_attr "fp_mode" "double")])
13266 (define_expand "truncdfsf2"
13267   [(set (match_operand:SF 0 "fpul_operand" "")
13268         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13269   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13271   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13272     {
13273       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
13274                                        get_fpscr_rtx ()));
13275       DONE;
13276     }
13279 (define_insn "*truncdfsf2_media"
13280   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13281         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13282   "TARGET_SHMEDIA_FPU"
13283   "fcnv.ds      %1, %0"
13284   [(set_attr "type" "dfpconv_media")])
13286 (define_insn "truncdfsf2_i4"
13287   [(set (match_operand:SF 0 "fpul_operand" "=y")
13288         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13289    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13290   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13291   "fcnvds  %1,%0"
13292   [(set_attr "type" "fp")
13293    (set_attr "fp_mode" "double")])
13295 ;; -------------------------------------------------------------------------
13296 ;; Bit field extract patterns.
13297 ;; -------------------------------------------------------------------------
13299 ;; These give better code for packed bitfields,  because they allow
13300 ;; auto-increment addresses to be generated.
13302 (define_expand "insv"
13303   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
13304                          (match_operand:SI 1 "immediate_operand" "")
13305                          (match_operand:SI 2 "immediate_operand" ""))
13306         (match_operand:SI 3 "general_operand" ""))]
13307   "TARGET_SH1 && TARGET_BIG_ENDIAN"
13309   rtx addr_target, orig_address, shift_reg, qi_val;
13310   HOST_WIDE_INT bitsize, size, v = 0;
13311   rtx x = operands[3];
13313   if (TARGET_SH2A && TARGET_BITOPS
13314       && (satisfies_constraint_Sbw (operands[0])
13315           || satisfies_constraint_Sbv (operands[0]))
13316       && satisfies_constraint_M (operands[1])
13317       && satisfies_constraint_K03 (operands[2]))
13318     {
13319       if (satisfies_constraint_N (operands[3]))
13320         {
13321           emit_insn (gen_bclr_m2a (operands[0], operands[2]));
13322           DONE;
13323         }
13324       else if (satisfies_constraint_M (operands[3]))
13325         {
13326           emit_insn (gen_bset_m2a (operands[0], operands[2]));
13327           DONE;
13328         }
13329       else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
13330                 && satisfies_constraint_M (operands[1]))
13331         {
13332           emit_insn (gen_bst_m2a (operands[0], operands[2]));
13333           DONE;
13334         }
13335       else if (REG_P (operands[3])
13336                && satisfies_constraint_M (operands[1]))
13337         {
13338           emit_insn (gen_bld_reg (operands[3], const0_rtx));
13339           emit_insn (gen_bst_m2a (operands[0], operands[2]));
13340           DONE;
13341         }
13342     }
13343   /* ??? expmed doesn't care for non-register predicates.  */
13344   if (! memory_operand (operands[0], VOIDmode)
13345       || ! immediate_operand (operands[1], VOIDmode)
13346       || ! immediate_operand (operands[2], VOIDmode)
13347       || ! general_operand (x, VOIDmode))
13348     FAIL;
13349   /* If this isn't a 16 / 24 / 32 bit field, or if
13350      it doesn't start on a byte boundary, then fail.  */
13351   bitsize = INTVAL (operands[1]);
13352   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13353       || (INTVAL (operands[2]) % 8) != 0)
13354     FAIL;
13356   size = bitsize / 8;
13357   orig_address = XEXP (operands[0], 0);
13358   shift_reg = gen_reg_rtx (SImode);
13359   if (CONST_INT_P (x))
13360     {
13361       v = INTVAL (x);
13362       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13363     }
13364   else
13365     {
13366       emit_insn (gen_movsi (shift_reg, operands[3]));
13367       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13368     }
13369   addr_target = copy_addr_to_reg (plus_constant (Pmode,
13370                                                  orig_address, size - 1));
13372   operands[0] = replace_equiv_address (operands[0], addr_target);
13373   emit_insn (gen_movqi (operands[0], qi_val));
13375   while (size -= 1)
13376     {
13377       if (CONST_INT_P (x))
13378         qi_val
13379           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13380       else
13381         {
13382           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13383           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13384         }
13385       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13386       emit_insn (gen_movqi (operands[0], qi_val));
13387     }
13389   DONE;
13392 (define_insn "movua"
13393   [(set (match_operand:SI 0 "register_operand" "=z")
13394         (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13395                    UNSPEC_MOVUA))]
13396   "TARGET_SH4A_ARCH"
13397   "movua.l      %1,%0"
13398   [(set_attr "type" "movua")])
13400 ;; We shouldn't need this, but cse replaces increments with references
13401 ;; to other regs before flow has a chance to create post_inc
13402 ;; addressing modes, and only postreload's cse_move2add brings the
13403 ;; increments back to a usable form.
13404 (define_peephole2
13405   [(set (match_operand:SI 0 "register_operand" "")
13406         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13407                          (const_int 32) (const_int 0)))
13408    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13409   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
13410   [(set (match_operand:SI 0 "register_operand" "")
13411         (sign_extract:SI (mem:SI (post_inc:SI
13412                                   (match_operand:SI 1 "register_operand" "")))
13413                          (const_int 32) (const_int 0)))]
13414   "")
13416 (define_expand "extv"
13417   [(set (match_operand:SI 0 "register_operand" "")
13418         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13419                          (match_operand 2 "const_int_operand" "")
13420                          (match_operand 3 "const_int_operand" "")))]
13421   "TARGET_SH4A_ARCH || TARGET_SH2A"
13423   if (TARGET_SH2A && TARGET_BITOPS
13424       && (satisfies_constraint_Sbw (operands[1])
13425           || satisfies_constraint_Sbv (operands[1]))
13426       && satisfies_constraint_M (operands[2])
13427       && satisfies_constraint_K03 (operands[3]))
13428    {
13429       emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13430       if (REGNO (operands[0]) != T_REG)
13431         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13432       DONE;
13433    }
13434   if (TARGET_SH4A_ARCH
13435       && INTVAL (operands[2]) == 32
13436       && INTVAL (operands[3]) == 0
13437       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13438     {
13439       rtx src = adjust_address (operands[1], BLKmode, 0);
13440       set_mem_size (src, 4);
13441       emit_insn (gen_movua (operands[0], src));
13442       DONE;
13443     }
13445   FAIL;
13448 (define_expand "extzv"
13449   [(set (match_operand:SI 0 "register_operand" "")
13450         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13451                          (match_operand 2 "const_int_operand" "")
13452                          (match_operand 3 "const_int_operand" "")))]
13453   "TARGET_SH4A_ARCH || TARGET_SH2A"
13455   if (TARGET_SH2A && TARGET_BITOPS
13456       && (satisfies_constraint_Sbw (operands[1])
13457           || satisfies_constraint_Sbv (operands[1]))
13458       && satisfies_constraint_M (operands[2])
13459       && satisfies_constraint_K03 (operands[3]))
13460     {
13461       emit_insn (gen_bld_m2a (operands[1], operands[3]));
13462       if (REGNO (operands[0]) != T_REG)
13463         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13464       DONE;
13465     }
13466   if (TARGET_SH4A_ARCH
13467       && INTVAL (operands[2]) == 32
13468       && INTVAL (operands[3]) == 0
13469       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13470     {
13471       rtx src = adjust_address (operands[1], BLKmode, 0);
13472       set_mem_size (src, 4);
13473       emit_insn (gen_movua (operands[0], src));
13474       DONE;
13475     }
13477   FAIL;
13480 ;; SH2A instructions for bitwise operations.
13481 ;; FIXME: Convert multiple instruction insns to insn_and_split.
13482 ;; FIXME: Use iterators to fold at least and,xor,or insn variations.
13484 ;; Clear a bit in a memory location.
13485 (define_insn "bclr_m2a"
13486   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13487         (and:QI
13488             (not:QI (ashift:QI (const_int 1)
13489                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
13490             (match_dup 0)))]
13491   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13492   "@
13493         bclr.b  %1,%0
13494         bclr.b  %1,@(0,%t0)"
13495 [(set_attr "length" "4,4")])
13497 (define_insn "bclrmem_m2a"
13498   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13499         (and:QI (match_dup 0)
13500                 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13501   "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13502   "@
13503         bclr.b  %W1,%0
13504         bclr.b  %W1,@(0,%t0)"
13505   [(set_attr "length" "4,4")])
13507 ;; Set a bit in a memory location.
13508 (define_insn "bset_m2a"
13509   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13510         (ior:QI
13511             (ashift:QI (const_int 1)
13512                        (match_operand:QI 1 "const_int_operand" "K03,K03"))
13513             (match_dup 0)))]
13514   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13515   "@
13516         bset.b  %1,%0
13517         bset.b  %1,@(0,%t0)"
13518   [(set_attr "length" "4,4")])
13520 (define_insn "bsetmem_m2a"
13521   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13522         (ior:QI (match_dup 0)
13523                 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13524   "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13525   "@
13526         bset.b  %V1,%0
13527         bset.b  %V1,@(0,%t0)"
13528   [(set_attr "length" "4,4")])
13530 ;;; Transfer the contents of the T bit to a specified bit of memory.
13531 (define_insn "bst_m2a"
13532   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13533         (if_then_else (eq (reg:SI T_REG) (const_int 0))
13534             (and:QI
13535                 (not:QI (ashift:QI (const_int 1)
13536                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
13537                 (match_dup 0))
13538             (ior:QI
13539                 (ashift:QI (const_int 1) (match_dup 1))
13540                 (match_dup 0))))]
13541   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13542   "@
13543         bst.b   %1,%0
13544         bst.b   %1,@(0,%t0)"
13545   [(set_attr "length" "4")])
13547 ;; Store a specified bit of memory in the T bit.
13548 (define_insn "bld_m2a"
13549   [(set (reg:SI T_REG)
13550         (zero_extract:SI
13551             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13552             (const_int 1)
13553             (match_operand 1 "const_int_operand" "K03,K03")))]
13554   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13555   "@
13556         bld.b   %1,%0
13557         bld.b   %1,@(0,%t0)"
13558   [(set_attr "length" "4,4")])
13560 ;; Store a specified bit of memory in the T bit.
13561 (define_insn "bldsign_m2a"
13562   [(set (reg:SI T_REG)
13563         (sign_extract:SI
13564             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13565             (const_int 1)
13566             (match_operand 1 "const_int_operand" "K03,K03")))]
13567   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13568   "@
13569         bld.b   %1,%0
13570         bld.b   %1,@(0,%t0)"
13571   [(set_attr "length" "4,4")])
13573 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13574 (define_insn "bld_reg"
13575   [(set (reg:SI T_REG)
13576         (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13577                          (const_int 1)
13578                          (match_operand 1 "const_int_operand" "K03")))]
13579   "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13580   "bld  %1,%0")
13582 (define_insn "*bld_regqi"
13583   [(set (reg:SI T_REG)
13584         (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13585                          (const_int 1)
13586                          (match_operand 1 "const_int_operand" "K03")))]
13587   "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13588   "bld  %1,%0")
13590 ;; Take logical and of a specified bit of memory with the T bit and
13591 ;; store its result in the T bit.
13592 (define_insn "band_m2a"
13593   [(set (reg:SI T_REG)
13594         (and:SI (reg:SI T_REG)
13595                 (zero_extract:SI
13596                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13597                     (const_int 1)
13598                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13599   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13600   "@
13601         band.b  %1,%0
13602         band.b  %1,@(0,%t0)"
13603   [(set_attr "length" "4,4")])
13605 (define_insn "bandreg_m2a"
13606   [(set (match_operand:SI 0 "register_operand" "=r,r")
13607         (and:SI (zero_extract:SI
13608                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13609                     (const_int 1)
13610                     (match_operand 2 "const_int_operand" "K03,K03"))
13611                 (match_operand:SI 3 "register_operand" "r,r")))]
13612   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13614   static const char* alt[] =
13615   {
13616        "band.b  %2,%1"          "\n"
13617     "   movt    %0",
13619        "band.b  %2,@(0,%t1)"    "\n"
13620     "   movt    %0"
13621   };
13622   return alt[which_alternative];
13624   [(set_attr "length" "6,6")])
13626 ;; Take logical or of a specified bit of memory with the T bit and
13627 ;; store its result in the T bit.
13628 (define_insn "bor_m2a"
13629   [(set (reg:SI T_REG)
13630         (ior:SI (reg:SI T_REG)
13631                 (zero_extract:SI
13632                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13633                     (const_int 1)
13634                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13635   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13636   "@
13637         bor.b   %1,%0
13638         bor.b   %1,@(0,%t0)"
13639   [(set_attr "length" "4,4")])
13641 (define_insn "borreg_m2a"
13642   [(set (match_operand:SI 0 "register_operand" "=r,r")
13643         (ior:SI (zero_extract:SI
13644                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13645                     (const_int 1)
13646                     (match_operand 2 "const_int_operand" "K03,K03"))
13647                 (match_operand:SI 3 "register_operand" "=r,r")))]
13648   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13650   static const char* alt[] =
13651   {
13652        "bor.b   %2,%1"          "\n"
13653     "   movt    %0",
13655        "bor.b   %2,@(0,%t1)"    "\n"
13656     "   movt    %0"
13657   };
13658   return alt[which_alternative];
13660   [(set_attr "length" "6,6")])
13662 ;; Take exclusive or of a specified bit of memory with the T bit and
13663 ;; store its result in the T bit.
13664 (define_insn "bxor_m2a"
13665   [(set (reg:SI T_REG)
13666         (xor:SI (reg:SI T_REG)
13667                 (zero_extract:SI
13668                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13669                     (const_int 1)
13670                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13671   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13672   "@
13673         bxor.b  %1,%0
13674         bxor.b  %1,@(0,%t0)"
13675   [(set_attr "length" "4,4")])
13677 (define_insn "bxorreg_m2a"
13678   [(set (match_operand:SI 0 "register_operand" "=r,r")
13679         (xor:SI (zero_extract:SI
13680                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13681                     (const_int 1)
13682                     (match_operand 2 "const_int_operand" "K03,K03"))
13683                 (match_operand:SI 3 "register_operand" "=r,r")))]
13684   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13686   static const char* alt[] =
13687   {
13688        "bxor.b  %2,%1"          "\n"
13689     "   movt    %0",
13691        "bxor.b  %2,@(0,%t1)"    "\n"
13692     "   movt    %0"
13693   };
13694   return alt[which_alternative];
13696   [(set_attr "length" "6,6")])
13698 ;; -------------------------------------------------------------------------
13699 ;; Peepholes
13700 ;; -------------------------------------------------------------------------
13701 ;; This matches cases where the bit in a memory location is set.
13702 (define_peephole2
13703   [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13704         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13705    (set (match_dup 0)
13706         (ior:SI (match_dup 0)
13707         (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
13708    (set (match_dup 1)
13709         (match_operand 3 "arith_reg_operand" "r,r"))]
13710   "TARGET_SH2A && TARGET_BITOPS
13711    && satisfies_constraint_Pso (operands[2])
13712    && REGNO (operands[0]) == REGNO (operands[3])"
13713   [(set (match_dup 1)
13714         (ior:QI (match_dup 1) (match_dup 2)))]
13715   "")
13717 ;; This matches cases where the bit in a memory location is cleared.
13718 (define_peephole2
13719   [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13720         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13721    (set (match_dup 0)
13722         (and:SI (match_dup 0)
13723         (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
13724    (set (match_dup 1)
13725         (match_operand 3 "arith_reg_operand" "r,r"))]
13726   "TARGET_SH2A && TARGET_BITOPS
13727    && satisfies_constraint_Psz (operands[2])
13728    && REGNO (operands[0]) == REGNO (operands[3])"
13729   [(set (match_dup 1)
13730         (and:QI (match_dup 1) (match_dup 2)))]
13731   "")
13733 ;; This matches cases where a stack pointer increment at the start of the
13734 ;; epilogue combines with a stack slot read loading the return value.
13735 (define_peephole
13736   [(set (match_operand:SI 0 "arith_reg_operand" "")
13737         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13738    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13739   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13740   "mov.l        @%1+,%0")
13742 ;; See the comment on the dt combiner pattern above.
13743 (define_peephole
13744   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13745         (plus:SI (match_dup 0)
13746                  (const_int -1)))
13747    (set (reg:SI T_REG)
13748         (eq:SI (match_dup 0) (const_int 0)))]
13749   "TARGET_SH2"
13750   "dt   %0")
13752 ;; The following peepholes fold load sequences for which reload was not
13753 ;; able to generate a displacement addressing move insn.
13754 ;; This can happen when reload has to transform a move insn 
13755 ;; without displacement into one with displacement.  Or when reload can't
13756 ;; fit a displacement into the insn's constraints.  In the latter case, the
13757 ;; load destination reg remains at r0, which reload compensates by inserting
13758 ;; another mov insn.
13760 ;; Fold sequence:
13761 ;;      mov #54,r0
13762 ;;      mov.{b,w} @(r0,r15),r0
13763 ;;      mov r0,r3
13764 ;; into:
13765 ;;      mov.{b,w} @(54,r15),r3
13767 (define_peephole2
13768   [(set (match_operand:SI 0 "arith_reg_dest" "")
13769         (match_operand:SI 1 "const_int_operand" ""))
13770    (set (match_operand:SI 2 "arith_reg_dest" "")
13771         (sign_extend:SI
13772          (mem:QI (plus:SI (match_dup 0)
13773                           (match_operand:SI 3 "arith_reg_operand" "")))))
13774    (set (match_operand:QI 4 "arith_reg_dest" "")
13775         (match_operand:QI 5 "arith_reg_operand" ""))]
13776   "TARGET_SH2A
13777    && sh_legitimate_index_p (QImode, operands[1], true, true)
13778    && REGNO (operands[2]) == REGNO (operands[5])
13779    && peep2_reg_dead_p (3, operands[5])"
13780   [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13781   "")
13783 (define_peephole2
13784   [(set (match_operand:SI 0 "arith_reg_dest" "")
13785         (match_operand:SI 1 "const_int_operand" ""))
13786    (set (match_operand:SI 2 "arith_reg_dest" "")
13787         (sign_extend:SI
13788          (mem:HI (plus:SI (match_dup 0)
13789                           (match_operand:SI 3 "arith_reg_operand" "")))))
13790    (set (match_operand:HI 4 "arith_reg_dest" "")
13791         (match_operand:HI 5 "arith_reg_operand" ""))]
13792   "TARGET_SH2A
13793    && sh_legitimate_index_p (HImode, operands[1], true, true)
13794    && REGNO (operands[2]) == REGNO (operands[5])
13795    && peep2_reg_dead_p (3, operands[5])"
13796   [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13797   "")
13799 ;; Fold sequence:
13800 ;;      mov #54,r0
13801 ;;      mov.{b,w} @(r0,r15),r1
13802 ;; into:
13803 ;;      mov.{b,w} @(54,r15),r1
13805 (define_peephole2
13806   [(set (match_operand:SI 0 "arith_reg_dest" "")
13807         (match_operand:SI 1 "const_int_operand" ""))
13808    (set (match_operand:SI 2 "arith_reg_dest" "")
13809          (sign_extend:SI
13810          (mem:QI (plus:SI (match_dup 0)
13811                           (match_operand:SI 3 "arith_reg_operand" "")))))]
13812   "TARGET_SH2A
13813    && sh_legitimate_index_p (QImode, operands[1], true, true)
13814    && (peep2_reg_dead_p (2, operands[0])
13815        || REGNO (operands[0]) == REGNO (operands[2]))"
13816   [(set (match_dup 2)
13817         (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13818   "")
13820 (define_peephole2
13821   [(set (match_operand:SI 0 "arith_reg_dest" "")
13822         (match_operand:SI 1 "const_int_operand" ""))
13823    (set (match_operand:SI 2 "arith_reg_dest" "")
13824          (sign_extend:SI
13825          (mem:HI (plus:SI (match_dup 0)
13826                           (match_operand:SI 3 "arith_reg_operand" "")))))]
13827   "TARGET_SH2A
13828    && sh_legitimate_index_p (HImode, operands[1], true, true)
13829    && (peep2_reg_dead_p (2, operands[0])
13830        || REGNO (operands[0]) == REGNO (operands[2]))"
13831   [(set (match_dup 2)
13832         (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13833   "")
13835 ;; Fold sequence:
13836 ;;      mov.{b,w} @(r0,r15),r0
13837 ;;      mov r0,r3
13838 ;; into:
13839 ;;      mov.{b,w} @(r0,r15),r3
13841 ;; This can happen when initially a displacement address is picked, where
13842 ;; the destination reg is fixed to r0, and then the address is transformed
13843 ;; into 'r0 + reg'.
13844 (define_peephole2
13845   [(set (match_operand:SI 0 "arith_reg_dest" "")
13846         (sign_extend:SI
13847          (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13848                           (match_operand:SI 2 "arith_reg_operand" "")))))
13849    (set (match_operand:QI 3 "arith_reg_dest" "")
13850         (match_operand:QI 4 "arith_reg_operand" ""))]
13851   "TARGET_SH1
13852    && REGNO (operands[0]) == REGNO (operands[4])
13853    && peep2_reg_dead_p (2, operands[0])"
13854   [(set (match_dup 3)
13855         (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13856   "")
13858 (define_peephole2
13859   [(set (match_operand:SI 0 "arith_reg_dest" "")
13860         (sign_extend:SI
13861          (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13862                           (match_operand:SI 2 "arith_reg_operand" "")))))
13863    (set (match_operand:HI 3 "arith_reg_dest" "")
13864         (match_operand:HI 4 "arith_reg_operand" ""))]
13865   "TARGET_SH1
13866    && REGNO (operands[0]) == REGNO (operands[4])
13867    && peep2_reg_dead_p (2, operands[0])"
13868   [(set (match_dup 3)
13869         (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13870   "")
13872 (define_peephole
13873   [(set (match_operand:SI 0 "register_operand" "=r")
13874         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13875    (set (mem:SF (match_dup 0))
13876         (match_operand:SF 2 "general_movsrc_operand" ""))]
13877   "TARGET_SH1 && REGNO (operands[0]) == 0
13878    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13879        || (GET_CODE (operands[2]) == SUBREG
13880            && REGNO (SUBREG_REG (operands[2])) < 16))
13881    && reg_unused_after (operands[0], insn)"
13882   "mov.l        %2,@(%0,%1)")
13884 (define_peephole
13885   [(set (match_operand:SI 0 "register_operand" "=r")
13886         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13887    (set (match_operand:SF 2 "general_movdst_operand" "")
13889         (mem:SF (match_dup 0)))]
13890   "TARGET_SH1 && REGNO (operands[0]) == 0
13891    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13892        || (GET_CODE (operands[2]) == SUBREG
13893            && REGNO (SUBREG_REG (operands[2])) < 16))
13894    && reg_unused_after (operands[0], insn)"
13895   "mov.l        @(%0,%1),%2")
13897 (define_peephole
13898   [(set (match_operand:SI 0 "register_operand" "=r")
13899         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13900    (set (mem:SF (match_dup 0))
13901         (match_operand:SF 2 "general_movsrc_operand" ""))]
13902   "TARGET_SH2E && REGNO (operands[0]) == 0
13903    && ((REG_P (operands[2])
13904         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13905        || (GET_CODE (operands[2]) == SUBREG
13906            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13907    && reg_unused_after (operands[0], insn)"
13908   "fmov{.s|}    %2,@(%0,%1)")
13910 (define_peephole
13911   [(set (match_operand:SI 0 "register_operand" "=r")
13912         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13913    (set (match_operand:SF 2 "general_movdst_operand" "")
13915         (mem:SF (match_dup 0)))]
13916   "TARGET_SH2E && REGNO (operands[0]) == 0
13917    && ((REG_P (operands[2])
13918         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13919        || (GET_CODE (operands[2]) == SUBREG
13920            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13921    && reg_unused_after (operands[0], insn)"
13922   "fmov{.s|}    @(%0,%1),%2")
13924 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13925 (define_insn "sp_switch_1"
13926   [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
13927     UNSPECV_SP_SWITCH_B))]
13928   "TARGET_SH1"
13930   return       "mov.l   r0,@-r15"       "\n"
13931          "      mov.l   %0,r0"          "\n"
13932          "      mov.l   @r0,r0"         "\n"
13933          "      mov.l   r15,@-r0"       "\n"
13934          "      mov     r0,r15";
13936   [(set_attr "length" "10")])
13938 ;; Switch back to the original stack for interrupt functions with the
13939 ;; sp_switch attribute.
13940 (define_insn "sp_switch_2"
13941   [(unspec_volatile [(const_int 0)]
13942     UNSPECV_SP_SWITCH_E)]
13943   "TARGET_SH1"
13945   return       "mov.l   @r15,r15"       "\n"
13946          "      mov.l   @r15+,r0";
13948   [(set_attr "length" "4")])
13950 ;; -------------------------------------------------------------------------
13951 ;; Integer vector moves
13952 ;; -------------------------------------------------------------------------
13954 (define_expand "movv8qi"
13955   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13956         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13957   "TARGET_SHMEDIA"
13959   prepare_move_operands (operands, V8QImode);
13962 (define_insn "movv8qi_i"
13963   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13964         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13965   "TARGET_SHMEDIA
13966    && (register_operand (operands[0], V8QImode)
13967        || sh_register_operand (operands[1], V8QImode))"
13968   "@
13969         add     %1, r63, %0
13970         movi    %1, %0
13971         #
13972         ld%M1.q %m1, %0
13973         st%M0.q %m0, %N1"
13974   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13975    (set_attr "length" "4,4,16,4,4")])
13977 (define_split
13978   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13979         (subreg:V8QI (const_int 0) 0))]
13980   "TARGET_SHMEDIA"
13981   [(set (match_dup 0)
13982         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13983                             (const_int 0) (const_int 0) (const_int 0)
13984                             (const_int 0) (const_int 0)]))])
13986 (define_split
13987   [(set (match_operand 0 "arith_reg_dest" "")
13988         (match_operand 1 "sh_rep_vec" ""))]
13989   "TARGET_SHMEDIA && reload_completed
13990    && GET_MODE (operands[0]) == GET_MODE (operands[1])
13991    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13992    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13993    && (XVECEXP (operands[1], 0, 0) != const0_rtx
13994        || XVECEXP (operands[1], 0, 1) != const0_rtx)
13995    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13996        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13997   [(set (match_dup 0) (match_dup 1))
13998    (match_dup 2)]
14000   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
14001   rtx elt1 = XVECEXP (operands[1], 0, 1);
14003   if (unit_size > 2)
14004     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
14005   else
14006     {
14007       if (unit_size < 2)
14008         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
14009       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
14010     }
14011   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
14012   operands[1] = XVECEXP (operands[1], 0, 0);
14013   if (unit_size < 2)
14014     {
14015       if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
14016         operands[1]
14017           = GEN_INT (TARGET_LITTLE_ENDIAN
14018                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
14019                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
14020       else
14021         {
14022           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
14023           operands[1]
14024             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
14025         }
14026     }
14029 (define_split
14030   [(set (match_operand 0 "arith_reg_dest" "")
14031         (match_operand 1 "sh_const_vec" ""))]
14032   "TARGET_SHMEDIA && reload_completed
14033    && GET_MODE (operands[0]) == GET_MODE (operands[1])
14034    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
14035   [(set (match_dup 0) (match_dup 1))]
14037   rtx v = operands[1];
14038   enum machine_mode new_mode
14039     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
14041   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
14042   operands[1]
14043     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
14046 (define_expand "movv2hi"
14047   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
14048         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
14049   "TARGET_SHMEDIA"
14051   prepare_move_operands (operands, V2HImode);
14054 (define_insn "movv2hi_i"
14055   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14056         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14057   "TARGET_SHMEDIA
14058    && (register_operand (operands[0], V2HImode)
14059        || sh_register_operand (operands[1], V2HImode))"
14060   "@
14061         add.l   %1, r63, %0
14062         movi    %1, %0
14063         #
14064         ld%M1.l %m1, %0
14065         st%M0.l %m0, %N1"
14066   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
14067    (set_attr "length" "4,4,16,4,4")
14068    (set (attr "highpart")
14069         (cond [(match_test "sh_contains_memref_p (insn)")
14070                (const_string "user")]
14071               (const_string "ignore")))])
14073 (define_expand "movv4hi"
14074   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
14075         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
14076   "TARGET_SHMEDIA"
14078   prepare_move_operands (operands, V4HImode);
14081 (define_insn "movv4hi_i"
14082   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14083         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14084   "TARGET_SHMEDIA
14085    && (register_operand (operands[0], V4HImode)
14086        || sh_register_operand (operands[1], V4HImode))"
14087   "@
14088         add     %1, r63, %0
14089         movi    %1, %0
14090         #
14091         ld%M1.q %m1, %0
14092         st%M0.q %m0, %N1"
14093   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
14094    (set_attr "length" "4,4,16,4,4")
14095    (set_attr "highpart" "depend")])
14097 (define_expand "movv2si"
14098   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
14099         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
14100   "TARGET_SHMEDIA"
14102   prepare_move_operands (operands, V2SImode);
14105 (define_insn "movv2si_i"
14106   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
14107         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14108   "TARGET_SHMEDIA
14109    && (register_operand (operands[0], V2SImode)
14110        || sh_register_operand (operands[1], V2SImode))"
14111   "@
14112         add     %1, r63, %0
14113         #
14114         #
14115         ld%M1.q %m1, %0
14116         st%M0.q %m0, %N1"
14117   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
14118    (set_attr "length" "4,4,16,4,4")
14119    (set_attr "highpart" "depend")])
14121 ;; -------------------------------------------------------------------------
14122 ;; Multimedia Intrinsics
14123 ;; -------------------------------------------------------------------------
14125 (define_insn "absv2si2"
14126   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14127         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
14128   "TARGET_SHMEDIA"
14129   "mabs.l       %1, %0"
14130   [(set_attr "type" "mcmp_media")
14131    (set_attr "highpart" "depend")])
14133 (define_insn "absv4hi2"
14134   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14135         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
14136   "TARGET_SHMEDIA"
14137   "mabs.w       %1, %0"
14138   [(set_attr "type" "mcmp_media")
14139    (set_attr "highpart" "depend")])
14141 (define_insn "addv2si3"
14142   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14143         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14144                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14145   "TARGET_SHMEDIA"
14146   "madd.l       %1, %2, %0"
14147   [(set_attr "type" "arith_media")
14148    (set_attr "highpart" "depend")])
14150 (define_insn "addv4hi3"
14151   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14152         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14153                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14154   "TARGET_SHMEDIA"
14155   "madd.w       %1, %2, %0"
14156   [(set_attr "type" "arith_media")
14157    (set_attr "highpart" "depend")])
14159 (define_insn_and_split "addv2hi3"
14160   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14161         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
14162                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
14163   "TARGET_SHMEDIA"
14164   "#"
14165   "TARGET_SHMEDIA"
14166   [(const_int 0)]
14168   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14169   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14170   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14171   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14172   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14174   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
14175   emit_insn (gen_truncdisi2 (si_dst, di_dst));
14176   DONE;
14178   [(set_attr "highpart" "must_split")])
14180 (define_insn "ssaddv2si3"
14181   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14182         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14183                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14184   "TARGET_SHMEDIA"
14185   "madds.l      %1, %2, %0"
14186   [(set_attr "type" "mcmp_media")
14187    (set_attr "highpart" "depend")])
14189 (define_insn "usaddv8qi3"
14190   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14191         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
14192                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14193   "TARGET_SHMEDIA"
14194   "madds.ub     %1, %2, %0"
14195   [(set_attr "type" "mcmp_media")
14196    (set_attr "highpart" "depend")])
14198 (define_insn "ssaddv4hi3"
14199   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14200         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14201                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14202   "TARGET_SHMEDIA"
14203   "madds.w      %1, %2, %0"
14204   [(set_attr "type" "mcmp_media")
14205    (set_attr "highpart" "depend")])
14207 (define_insn "negcmpeqv8qi"
14208   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14209         (neg:V8QI (eq:V8QI
14210                     (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14211                     (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14212   "TARGET_SHMEDIA"
14213   "mcmpeq.b     %N1, %N2, %0"
14214   [(set_attr "type" "mcmp_media")
14215    (set_attr "highpart" "depend")])
14217 (define_insn "negcmpeqv2si"
14218   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14219         (neg:V2SI (eq:V2SI
14220                     (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14221                     (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14222   "TARGET_SHMEDIA"
14223   "mcmpeq.l     %N1, %N2, %0"
14224   [(set_attr "type" "mcmp_media")
14225    (set_attr "highpart" "depend")])
14227 (define_insn "negcmpeqv4hi"
14228   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14229         (neg:V4HI (eq:V4HI
14230                     (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14231                     (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14232   "TARGET_SHMEDIA"
14233   "mcmpeq.w     %N1, %N2, %0"
14234   [(set_attr "type" "mcmp_media")
14235    (set_attr "highpart" "depend")])
14237 (define_insn "negcmpgtuv8qi"
14238   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14239         (neg:V8QI (gtu:V8QI
14240                     (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14241                     (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14242   "TARGET_SHMEDIA"
14243   "mcmpgt.ub    %N1, %N2, %0"
14244   [(set_attr "type" "mcmp_media")
14245    (set_attr "highpart" "depend")])
14247 (define_insn "negcmpgtv2si"
14248   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14249         (neg:V2SI (gt:V2SI
14250                     (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14251                     (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14252   "TARGET_SHMEDIA"
14253   "mcmpgt.l     %N1, %N2, %0"
14254   [(set_attr "type" "mcmp_media")
14255    (set_attr "highpart" "depend")])
14257 (define_insn "negcmpgtv4hi"
14258   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14259         (neg:V4HI (gt:V4HI
14260                     (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14261                     (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14262   "TARGET_SHMEDIA"
14263   "mcmpgt.w     %N1, %N2, %0"
14264   [(set_attr "type" "mcmp_media")
14265    (set_attr "highpart" "depend")])
14267 (define_insn "mcmv"
14268   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14269         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14270                         (match_operand:DI 2 "arith_reg_operand" "r"))
14271                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
14272                         (not:DI (match_dup 2)))))]
14273   "TARGET_SHMEDIA"
14274   "mcmv %N1, %2, %0"
14275   [(set_attr "type" "arith_media")
14276    (set_attr "highpart" "depend")])
14278 (define_insn "mcnvs_lw"
14279   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14280         (vec_concat:V4HI
14281          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
14282          (ss_truncate:V2HI
14283            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14284   "TARGET_SHMEDIA"
14285   "mcnvs.lw     %N1, %N2, %0"
14286   [(set_attr "type" "mcmp_media")])
14288 (define_insn "mcnvs_wb"
14289   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14290         (vec_concat:V8QI
14291          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14292          (ss_truncate:V4QI
14293            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14294   "TARGET_SHMEDIA"
14295   "mcnvs.wb     %N1, %N2, %0"
14296   [(set_attr "type" "mcmp_media")])
14298 (define_insn "mcnvs_wub"
14299   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14300         (vec_concat:V8QI
14301          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14302          (us_truncate:V4QI
14303            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14304   "TARGET_SHMEDIA"
14305   "mcnvs.wub    %N1, %N2, %0"
14306   [(set_attr "type" "mcmp_media")])
14308 (define_insn "mextr_rl"
14309   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14310         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14311                              (match_operand:HI 3 "mextr_bit_offset" "i"))
14312                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14313                            (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14314   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14316   static char templ[21];
14317   sprintf (templ, "mextr%d      %%N1, %%N2, %%0",
14318            (int) INTVAL (operands[3]) >> 3);
14319   return templ;
14321   [(set_attr "type" "arith_media")])
14323 (define_insn "*mextr_lr"
14324   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14325         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14326                            (match_operand:HI 3 "mextr_bit_offset" "i"))
14327                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14328                              (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14329   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14331   static char templ[21];
14332   sprintf (templ, "mextr%d      %%N2, %%N1, %%0",
14333            (int) INTVAL (operands[4]) >> 3);
14334   return templ;
14336   [(set_attr "type" "arith_media")])
14338 ; mextrN can be modelled with vec_select / vec_concat, but the selection
14339 ; vector then varies depending on endianness.
14340 (define_expand "mextr1"
14341   [(match_operand:DI 0 "arith_reg_dest" "")
14342    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14343    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14344   "TARGET_SHMEDIA"
14346   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14347                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
14348   DONE;
14351 (define_expand "mextr2"
14352   [(match_operand:DI 0 "arith_reg_dest" "")
14353    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14354    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14355   "TARGET_SHMEDIA"
14357   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14358                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
14359   DONE;
14362 (define_expand "mextr3"
14363   [(match_operand:DI 0 "arith_reg_dest" "")
14364    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14365    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14366   "TARGET_SHMEDIA"
14368   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14369                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
14370   DONE;
14373 (define_expand "mextr4"
14374   [(match_operand:DI 0 "arith_reg_dest" "")
14375    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14376    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14377   "TARGET_SHMEDIA"
14379   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14380                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
14381   DONE;
14384 (define_expand "mextr5"
14385   [(match_operand:DI 0 "arith_reg_dest" "")
14386    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14387    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14388   "TARGET_SHMEDIA"
14390   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14391                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
14392   DONE;
14395 (define_expand "mextr6"
14396   [(match_operand:DI 0 "arith_reg_dest" "")
14397    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14398    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14399   "TARGET_SHMEDIA"
14401   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14402                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
14403   DONE;
14406 (define_expand "mextr7"
14407   [(match_operand:DI 0 "arith_reg_dest" "")
14408    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14409    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14410   "TARGET_SHMEDIA"
14412   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14413                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
14414   DONE;
14417 (define_expand "mmacfx_wl"
14418   [(match_operand:V2SI 0 "arith_reg_dest" "")
14419    (match_operand:V2HI 1 "extend_reg_operand" "")
14420    (match_operand:V2HI 2 "extend_reg_operand" "")
14421    (match_operand:V2SI 3 "arith_reg_operand" "")]
14422   "TARGET_SHMEDIA"
14424   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14425                               operands[1], operands[2]));
14426   DONE;
14429 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14430 ;; is depend
14431 (define_insn "mmacfx_wl_i"
14432   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14433         (ss_plus:V2SI
14434          (match_operand:V2SI 1 "arith_reg_operand" "0")
14435          (ss_truncate:V2SI
14436           (ashift:V2DI
14437            (sign_extend:V2DI
14438             (mult:V2SI
14439              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14440              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14441            (const_int 1)))))]
14442   "TARGET_SHMEDIA"
14443   "mmacfx.wl    %2, %3, %0"
14444   [(set_attr "type" "mac_media")
14445    (set_attr "highpart" "depend")])
14447 (define_expand "mmacnfx_wl"
14448   [(match_operand:V2SI 0 "arith_reg_dest" "")
14449    (match_operand:V2HI 1 "extend_reg_operand" "")
14450    (match_operand:V2HI 2 "extend_reg_operand" "")
14451    (match_operand:V2SI 3 "arith_reg_operand" "")]
14452   "TARGET_SHMEDIA"
14454   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14455                                operands[1], operands[2]));
14456   DONE;
14459 (define_insn "mmacnfx_wl_i"
14460   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14461         (ss_minus:V2SI
14462          (match_operand:V2SI 1 "arith_reg_operand" "0")
14463          (ss_truncate:V2SI
14464           (ashift:V2DI
14465            (sign_extend:V2DI
14466             (mult:V2SI
14467              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14468              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14469            (const_int 1)))))]
14470   "TARGET_SHMEDIA"
14471   "mmacnfx.wl   %2, %3, %0"
14472   [(set_attr "type" "mac_media")
14473    (set_attr "highpart" "depend")])
14475 (define_insn "mulv2si3"
14476   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14477         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14478                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14479   "TARGET_SHMEDIA"
14480   "mmul.l       %1, %2, %0"
14481   [(set_attr "type" "d2mpy_media")
14482    (set_attr "highpart" "depend")])
14484 (define_insn "mulv4hi3"
14485   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14486         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14487                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14488   "TARGET_SHMEDIA"
14489   "mmul.w       %1, %2, %0"
14490   [(set_attr "type" "dmpy_media")
14491    (set_attr "highpart" "depend")])
14493 (define_insn "mmulfx_l"
14494   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14495         (ss_truncate:V2SI
14496          (ashiftrt:V2DI
14497           (mult:V2DI
14498            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14499            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14500           (const_int 31))))]
14501   "TARGET_SHMEDIA"
14502   "mmulfx.l     %1, %2, %0"
14503   [(set_attr "type" "d2mpy_media")
14504    (set_attr "highpart" "depend")])
14506 (define_insn "mmulfx_w"
14507   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14508         (ss_truncate:V4HI
14509          (ashiftrt:V4SI
14510           (mult:V4SI
14511            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14512            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14513           (const_int 15))))]
14514   "TARGET_SHMEDIA"
14515   "mmulfx.w     %1, %2, %0"
14516   [(set_attr "type" "dmpy_media")
14517    (set_attr "highpart" "depend")])
14519 (define_insn "mmulfxrp_w"
14520   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14521         (ss_truncate:V4HI
14522          (ashiftrt:V4SI
14523           (plus:V4SI
14524            (mult:V4SI
14525             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14526             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14527            (const_int 16384))
14528           (const_int 15))))]
14529   "TARGET_SHMEDIA"
14530   "mmulfxrp.w   %1, %2, %0"
14531   [(set_attr "type" "dmpy_media")
14532    (set_attr "highpart" "depend")])
14535 (define_expand "mmulhi_wl"
14536   [(match_operand:V2SI 0 "arith_reg_dest" "")
14537    (match_operand:V4HI 1 "arith_reg_operand" "")
14538    (match_operand:V4HI 2 "arith_reg_operand" "")]
14539   "TARGET_SHMEDIA"
14541   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14542              (operands[0], operands[1], operands[2]));
14543   DONE;
14546 (define_expand "mmullo_wl"
14547   [(match_operand:V2SI 0 "arith_reg_dest" "")
14548    (match_operand:V4HI 1 "arith_reg_operand" "")
14549    (match_operand:V4HI 2 "arith_reg_operand" "")]
14550   "TARGET_SHMEDIA"
14552   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14553              (operands[0], operands[1], operands[2]));
14554   DONE;
14557 (define_insn "mmul23_wl"
14558   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14559         (vec_select:V2SI
14560          (mult:V4SI
14561           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14562           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14563          (parallel [(const_int 2) (const_int 3)])))]
14564   "TARGET_SHMEDIA"
14566   return (TARGET_LITTLE_ENDIAN
14567           ? "mmulhi.wl  %1, %2, %0"
14568           : "mmullo.wl  %1, %2, %0");
14570   [(set_attr "type" "dmpy_media")
14571    (set (attr "highpart")
14572         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14573          (const_string "user")))])
14575 (define_insn "mmul01_wl"
14576   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14577         (vec_select:V2SI
14578          (mult:V4SI
14579           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14580           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14581          (parallel [(const_int 0) (const_int 1)])))]
14582   "TARGET_SHMEDIA"
14584   return (TARGET_LITTLE_ENDIAN
14585           ? "mmullo.wl  %1, %2, %0"
14586           : "mmulhi.wl  %1, %2, %0");
14588   [(set_attr "type" "dmpy_media")
14589    (set (attr "highpart")
14590         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14591          (const_string "user")))])
14594 (define_expand "mmulsum_wq"
14595   [(match_operand:DI 0 "arith_reg_dest" "")
14596    (match_operand:V4HI 1 "arith_reg_operand" "")
14597    (match_operand:V4HI 2 "arith_reg_operand" "")
14598    (match_operand:DI 3 "arith_reg_operand" "")]
14599   "TARGET_SHMEDIA"
14601   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14602                                operands[1], operands[2]));
14603   DONE;
14606 (define_insn "mmulsum_wq_i"
14607   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14608         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14609          (plus:DI
14610           (plus:DI
14611            (vec_select:DI
14612             (mult:V4DI
14613              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14614              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14615             (parallel [(const_int 0)]))
14616            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14617                                      (sign_extend:V4DI (match_dup 3)))
14618                           (parallel [(const_int 1)])))
14619           (plus:DI
14620            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14621                                      (sign_extend:V4DI (match_dup 3)))
14622                           (parallel [(const_int 2)]))
14623            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14624                                      (sign_extend:V4DI (match_dup 3)))
14625                           (parallel [(const_int 3)]))))))]
14626   "TARGET_SHMEDIA"
14627   "mmulsum.wq   %2, %3, %0"
14628   [(set_attr "type" "mac_media")])
14630 (define_expand "mperm_w"
14631   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14632    (match_operand:V4HI 1 "arith_reg_operand" "r")
14633    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14634   "TARGET_SHMEDIA"
14636   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14637              (operands[0], operands[1], operands[2]));
14638   DONE;
14641 ; This use of vec_select isn't exactly correct according to rtl.texi
14642 ; (because not constant), but it seems a straightforward extension.
14643 (define_insn "mperm_w_little"
14644   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14645         (vec_select:V4HI
14646          (match_operand:V4HI 1 "arith_reg_operand" "r")
14647          (parallel
14648           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14649                             (const_int 2) (const_int 0))
14650            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14651            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14652            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14653   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14654   "mperm.w      %1, %N2, %0"
14655   [(set_attr "type" "arith_media")])
14657 (define_insn "mperm_w_big"
14658   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14659         (vec_select:V4HI
14660          (match_operand:V4HI 1 "arith_reg_operand" "r")
14661          (parallel
14662           [(zero_extract:QI (not:QI (match_operand:QI 2
14663                                      "extend_reg_or_0_operand" "rZ"))
14664                             (const_int 2) (const_int 0))
14665            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14666            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14667            (zero_extract:QI (not:QI (match_dup 2))
14668                             (const_int 2) (const_int 6))])))]
14669   "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
14670   "mperm.w      %1, %N2, %0"
14671   [(set_attr "type" "arith_media")])
14673 (define_insn "mperm_w0"
14674   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14675         (vec_duplicate:V4HI (truncate:HI (match_operand 1
14676                                           "trunc_hi_operand" "r"))))]
14677   "TARGET_SHMEDIA"
14678   "mperm.w      %1, r63, %0"
14679   [(set_attr "type" "arith_media")
14680    (set_attr "highpart" "ignore")])
14682 (define_expand "msad_ubq"
14683   [(match_operand:DI 0 "arith_reg_dest" "")
14684    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14685    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14686    (match_operand:DI 3 "arith_reg_operand" "")]
14687   "TARGET_SHMEDIA"
14689   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14690                              operands[1], operands[2]));
14691   DONE;
14694 (define_insn "msad_ubq_i"
14695   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14696         (plus:DI
14697          (plus:DI
14698           (plus:DI
14699            (plus:DI
14700             (match_operand:DI 1 "arith_reg_operand" "0")
14701             (abs:DI (vec_select:DI
14702                      (minus:V8DI
14703                       (zero_extend:V8DI
14704                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14705                       (zero_extend:V8DI
14706                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14707                      (parallel [(const_int 0)]))))
14708            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14709                                               (zero_extend:V8DI (match_dup 3)))
14710                                   (parallel [(const_int 1)]))))
14711           (plus:DI
14712            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14713                                               (zero_extend:V8DI (match_dup 3)))
14714                                   (parallel [(const_int 2)])))
14715            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14716                                               (zero_extend:V8DI (match_dup 3)))
14717                                   (parallel [(const_int 3)])))))
14718          (plus:DI
14719           (plus:DI
14720            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14721                                               (zero_extend:V8DI (match_dup 3)))
14722                                   (parallel [(const_int 4)])))
14723            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14724                                               (zero_extend:V8DI (match_dup 3)))
14725                                   (parallel [(const_int 5)]))))
14726           (plus:DI
14727            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14728                                               (zero_extend:V8DI (match_dup 3)))
14729                                   (parallel [(const_int 6)])))
14730            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14731                                               (zero_extend:V8DI (match_dup 3)))
14732                                   (parallel [(const_int 7)])))))))]
14733   "TARGET_SHMEDIA"
14734   "msad.ubq     %N2, %N3, %0"
14735   [(set_attr "type" "mac_media")])
14737 (define_insn "mshalds_l"
14738   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14739         (ss_truncate:V2SI
14740          (ashift:V2DI
14741           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14742           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14743                   (const_int 31)))))]
14744   "TARGET_SHMEDIA"
14745   "mshalds.l    %1, %2, %0"
14746   [(set_attr "type" "mcmp_media")
14747    (set_attr "highpart" "depend")])
14749 (define_insn "mshalds_w"
14750   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14751         (ss_truncate:V4HI
14752          (ashift:V4SI
14753           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14754           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14755                   (const_int 15)))))]
14756   "TARGET_SHMEDIA"
14757   "mshalds.w    %1, %2, %0"
14758   [(set_attr "type" "mcmp_media")
14759    (set_attr "highpart" "depend")])
14761 (define_insn "ashrv2si3"
14762   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14763         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14764                        (match_operand:DI 2 "arith_reg_operand" "r")))]
14765   "TARGET_SHMEDIA"
14766   "mshard.l     %1, %2, %0"
14767   [(set_attr "type" "arith_media")
14768    (set_attr "highpart" "depend")])
14770 (define_insn "ashrv4hi3"
14771   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14772         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14773                        (match_operand:DI 2 "arith_reg_operand" "r")))]
14774   "TARGET_SHMEDIA"
14775   "mshard.w     %1, %2, %0"
14776   [(set_attr "type" "arith_media")
14777    (set_attr "highpart" "depend")])
14779 (define_insn "mshards_q"
14780   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14781         (ss_truncate:HI
14782          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14783                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14784   "TARGET_SHMEDIA"
14785   "mshards.q    %1, %N2, %0"
14786   [(set_attr "type" "mcmp_media")])
14788 (define_expand "mshfhi_b"
14789   [(match_operand:V8QI 0 "arith_reg_dest" "")
14790    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14791    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14792   "TARGET_SHMEDIA"
14794   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14795              (operands[0], operands[1], operands[2]));
14796   DONE;
14799 (define_expand "mshflo_b"
14800   [(match_operand:V8QI 0 "arith_reg_dest" "")
14801    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14802    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14803   "TARGET_SHMEDIA"
14805   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14806              (operands[0], operands[1], operands[2]));
14807   DONE;
14810 (define_insn "mshf4_b"
14811   [(set
14812     (match_operand:V8QI 0 "arith_reg_dest" "=r")
14813     (vec_select:V8QI
14814      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14815                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14816      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14817                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14818   "TARGET_SHMEDIA"
14820   return (TARGET_LITTLE_ENDIAN
14821           ? "mshfhi.b   %N1, %N2, %0"
14822           : "mshflo.b   %N1, %N2, %0");
14824   [(set_attr "type" "arith_media")
14825    (set (attr "highpart")
14826         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14827          (const_string "user")))])
14829 (define_insn "mshf0_b"
14830   [(set
14831     (match_operand:V8QI 0 "arith_reg_dest" "=r")
14832     (vec_select:V8QI
14833      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14834                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14835      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14836                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14837   "TARGET_SHMEDIA"
14839   return (TARGET_LITTLE_ENDIAN
14840           ? "mshflo.b   %N1, %N2, %0"
14841           : "mshfhi.b   %N1, %N2, %0");
14843   [(set_attr "type" "arith_media")
14844    (set (attr "highpart")
14845         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14846          (const_string "user")))])
14848 (define_expand "mshfhi_l"
14849   [(match_operand:V2SI 0 "arith_reg_dest" "")
14850    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14851    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14852   "TARGET_SHMEDIA"
14854   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14855              (operands[0], operands[1], operands[2]));
14856   DONE;
14859 (define_expand "mshflo_l"
14860   [(match_operand:V2SI 0 "arith_reg_dest" "")
14861    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14862    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14863   "TARGET_SHMEDIA"
14865   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14866              (operands[0], operands[1], operands[2]));
14867   DONE;
14870 (define_insn "mshf4_l"
14871   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14872         (vec_select:V2SI
14873          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14874                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14875          (parallel [(const_int 1) (const_int 3)])))]
14876   "TARGET_SHMEDIA"
14878   return (TARGET_LITTLE_ENDIAN
14879           ? "mshfhi.l   %N1, %N2, %0"
14880           : "mshflo.l   %N1, %N2, %0");
14882   [(set_attr "type" "arith_media")
14883    (set (attr "highpart")
14884         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14885          (const_string "user")))])
14887 (define_insn "mshf0_l"
14888   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14889         (vec_select:V2SI
14890          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14891                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14892          (parallel [(const_int 0) (const_int 2)])))]
14893   "TARGET_SHMEDIA"
14895   return (TARGET_LITTLE_ENDIAN
14896           ? "mshflo.l   %N1, %N2, %0"
14897           : "mshfhi.l   %N1, %N2, %0");
14899   [(set_attr "type" "arith_media")
14900    (set (attr "highpart")
14901         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14902          (const_string "user")))])
14904 (define_expand "mshfhi_w"
14905   [(match_operand:V4HI 0 "arith_reg_dest" "")
14906    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14907    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14908   "TARGET_SHMEDIA"
14910   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14911              (operands[0], operands[1], operands[2]));
14912   DONE;
14915 (define_expand "mshflo_w"
14916   [(match_operand:V4HI 0 "arith_reg_dest" "")
14917    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14918    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14919   "TARGET_SHMEDIA"
14921   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14922              (operands[0], operands[1], operands[2]));
14923   DONE;
14926 (define_insn "mshf4_w"
14927   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14928         (vec_select:V4HI
14929          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14930                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14931          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14932   "TARGET_SHMEDIA"
14934   return (TARGET_LITTLE_ENDIAN
14935           ? "mshfhi.w   %N1, %N2, %0"
14936           : "mshflo.w   %N1, %N2, %0");
14938   [(set_attr "type" "arith_media")
14939    (set (attr "highpart")
14940         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14941          (const_string "user")))])
14943 (define_insn "mshf0_w"
14944   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14945         (vec_select:V4HI
14946          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14947                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14948          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14949   "TARGET_SHMEDIA"
14951   return (TARGET_LITTLE_ENDIAN
14952           ? "mshflo.w   %N1, %N2, %0"
14953           : "mshfhi.w   %N1, %N2, %0");
14955   [(set_attr "type" "arith_media")
14956    (set (attr "highpart")
14957         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14958          (const_string "user")))])
14960 (define_insn "mshflo_w_x"
14961   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14962         (vec_select:V4HI
14963          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14964                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14965          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14966   "TARGET_SHMEDIA"
14967   "mshflo.w     %N1, %N2, %0"
14968   [(set_attr "type" "arith_media")
14969    (set_attr "highpart" "ignore")])
14971 ;; These are useful to expand ANDs and as combiner patterns.
14972 (define_insn_and_split "mshfhi_l_di"
14973   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14974         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14975                              (const_int 32))
14976                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14977                         (const_int -4294967296))))]
14978   "TARGET_SHMEDIA"
14979   "@
14980         mshfhi.l        %N1, %N2, %0
14981         #"
14982   "TARGET_SHMEDIA && reload_completed
14983    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14984   [(set (match_dup 3) (match_dup 4))
14985    (set (match_dup 5) (match_dup 6))]
14987   operands[3] = gen_lowpart (SImode, operands[0]);
14988   operands[4] = gen_highpart (SImode, operands[1]);
14989   operands[5] = gen_highpart (SImode, operands[0]);
14990   operands[6] = gen_highpart (SImode, operands[2]);
14992   [(set_attr "type" "arith_media")])
14994 (define_insn "*mshfhi_l_di_rev"
14995   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14996         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14997                         (const_int -4294967296))
14998                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14999                              (const_int 32))))]
15000   "TARGET_SHMEDIA"
15001   "mshfhi.l     %N2, %N1, %0"
15002   [(set_attr "type" "arith_media")])
15004 (define_split
15005   [(set (match_operand:DI 0 "arith_reg_dest" "")
15006         (ior:DI (zero_extend:DI (match_operand:SI 1
15007                                               "extend_reg_or_0_operand" ""))
15008                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
15009                         (const_int -4294967296))))
15010    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
15011   "TARGET_SHMEDIA"
15012   [(const_int 0)]
15014   emit_insn (gen_ashldi3_media (operands[3],
15015                                 simplify_gen_subreg (DImode, operands[1],
15016                                                      SImode, 0),
15017                                 GEN_INT (32)));
15018   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
15019   DONE;
15022 (define_insn "mshflo_l_di"
15023   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15024         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15025                         (const_int 4294967295))
15026                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15027                            (const_int 32))))]
15029   "TARGET_SHMEDIA"
15030   "mshflo.l     %N1, %N2, %0"
15031   [(set_attr "type" "arith_media")
15032    (set_attr "highpart" "ignore")])
15034 (define_insn "*mshflo_l_di_rev"
15035   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15036         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15037                            (const_int 32))
15038                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15039                         (const_int 4294967295))))]
15041   "TARGET_SHMEDIA"
15042   "mshflo.l     %N2, %N1, %0"
15043   [(set_attr "type" "arith_media")
15044    (set_attr "highpart" "ignore")])
15046 ;; Combiner pattern for trampoline initialization.
15047 (define_insn_and_split "*double_shori"
15048   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15049         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
15050                            (const_int 32))
15051                 (match_operand:DI 2 "const_int_operand" "n")))]
15052   "TARGET_SHMEDIA
15053    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
15054   "#"
15055   "rtx_equal_p (operands[0], operands[1])"
15056   [(const_int 0)]
15058   HOST_WIDE_INT v = INTVAL (operands[2]);
15060   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
15061   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
15062   DONE;
15064   [(set_attr "highpart" "ignore")])
15066 (define_insn "*mshflo_l_di_x"
15067   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15068         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
15069                                  "rZ"))
15070                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15071                            (const_int 32))))]
15072   "TARGET_SHMEDIA"
15073   "mshflo.l     %N1, %N2, %0"
15074   [(set_attr "type" "arith_media")
15075    (set_attr "highpart" "ignore")])
15077 (define_insn_and_split "concat_v2sf"
15078   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
15079 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
15080         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
15081                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
15082   "TARGET_SHMEDIA"
15083   "@
15084         mshflo.l        %N1, %N2, %0
15085         #
15086         #"
15087   "TARGET_SHMEDIA && reload_completed
15088    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
15089   [(set (match_dup 3) (match_dup 1))
15090    (set (match_dup 4) (match_dup 2))]
15092   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
15093   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
15095   [(set_attr "type" "arith_media")
15096    (set_attr "highpart" "ignore")])
15098 (define_insn "*mshflo_l_di_x_rev"
15099   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15100         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15101                            (const_int 32))
15102                 (zero_extend:DI
15103                   (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
15104   "TARGET_SHMEDIA"
15105   "mshflo.l     %N2, %N1, %0"
15106   [(set_attr "type" "arith_media")
15107    (set_attr "highpart" "ignore")])
15109 (define_insn "ashlv2si3"
15110   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15111         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15112                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15113   "TARGET_SHMEDIA"
15114   "mshlld.l     %1, %2, %0"
15115   [(set_attr "type" "arith_media")
15116    (set_attr "highpart" "depend")])
15118 (define_split
15119   [(set (match_operand 0 "any_register_operand" "")
15120         (match_operator 3 "shift_operator"
15121           [(match_operand 1 "any_register_operand" "")
15122            (match_operand 2 "shift_count_reg_operand" "")]))]
15123   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
15124   [(set (match_dup 0) (match_dup 3))]
15126   rtx count = operands[2];
15127   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
15129   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
15130          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
15131          || GET_CODE (count) == TRUNCATE)
15132     count = XEXP (count, 0);
15133   inner_mode = GET_MODE (count);
15134   count = simplify_gen_subreg (outer_mode, count, inner_mode,
15135                                subreg_lowpart_offset (outer_mode, inner_mode));
15136   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
15137                                 operands[1], count);
15140 (define_insn "ashlv4hi3"
15141   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15142         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15143                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15144   "TARGET_SHMEDIA"
15145   "mshlld.w     %1, %2, %0"
15146   [(set_attr "type" "arith_media")
15147    (set_attr "highpart" "depend")])
15149 (define_insn "lshrv2si3"
15150   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15151         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15152                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15153   "TARGET_SHMEDIA"
15154   "mshlrd.l     %1, %2, %0"
15155   [(set_attr "type" "arith_media")
15156    (set_attr "highpart" "depend")])
15158 (define_insn "lshrv4hi3"
15159   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15160         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15161                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15162   "TARGET_SHMEDIA"
15163   "mshlrd.w     %1, %2, %0"
15164   [(set_attr "type" "arith_media")
15165    (set_attr "highpart" "depend")])
15167 (define_insn "subv2si3"
15168   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15169         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15170                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15171   "TARGET_SHMEDIA"
15172   "msub.l       %N1, %2, %0"
15173   [(set_attr "type" "arith_media")
15174    (set_attr "highpart" "depend")])
15176 (define_insn "subv4hi3"
15177   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15178         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15179                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15180   "TARGET_SHMEDIA"
15181   "msub.w       %N1, %2, %0"
15182   [(set_attr "type" "arith_media")
15183    (set_attr "highpart" "depend")])
15185 (define_insn_and_split "subv2hi3"
15186   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15187         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
15188                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
15189   "TARGET_SHMEDIA"
15190   "#"
15191   "TARGET_SHMEDIA"
15192   [(const_int 0)]
15194   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15195   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15196   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15197   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15198   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15200   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
15201   emit_insn (gen_truncdisi2 (si_dst, di_dst));
15202   DONE;
15204   [(set_attr "highpart" "must_split")])
15206 (define_insn "sssubv2si3"
15207   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15208         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15209                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15210   "TARGET_SHMEDIA"
15211   "msubs.l      %N1, %2, %0"
15212   [(set_attr "type" "mcmp_media")
15213    (set_attr "highpart" "depend")])
15215 (define_insn "ussubv8qi3"
15216   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15217         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15218                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15219   "TARGET_SHMEDIA"
15220   "msubs.ub     %N1, %2, %0"
15221   [(set_attr "type" "mcmp_media")
15222    (set_attr "highpart" "depend")])
15224 (define_insn "sssubv4hi3"
15225   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15226         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15227                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15228   "TARGET_SHMEDIA"
15229   "msubs.w      %N1, %2, %0"
15230   [(set_attr "type" "mcmp_media")
15231    (set_attr "highpart" "depend")])
15233 ;; -------------------------------------------------------------------------
15234 ;; Floating Point Intrinsics
15235 ;; -------------------------------------------------------------------------
15237 (define_insn "fcosa_s"
15238   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15239         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15240                    UNSPEC_FCOSA))]
15241   "TARGET_SHMEDIA"
15242   "fcosa.s      %1, %0"
15243   [(set_attr "type" "atrans_media")])
15245 (define_insn "fsina_s"
15246   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15247         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15248                    UNSPEC_FSINA))]
15249   "TARGET_SHMEDIA"
15250   "fsina.s      %1, %0"
15251   [(set_attr "type" "atrans_media")])
15253 (define_insn "fipr"
15254   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15255         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
15256                                                     "fp_arith_reg_operand" "f")
15257                                                    (match_operand:V4SF 2
15258                                                     "fp_arith_reg_operand" "f"))
15259                                          (parallel [(const_int 0)]))
15260                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15261                                          (parallel [(const_int 1)])))
15262                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15263                                          (parallel [(const_int 2)]))
15264                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15265                                          (parallel [(const_int 3)])))))]
15266   "TARGET_SHMEDIA"
15267   "fipr.s       %1, %2, %0"
15268   [(set_attr "type" "fparith_media")])
15270 (define_insn "fsrra_s"
15271   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15272         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
15273                    UNSPEC_FSRRA))]
15274   "TARGET_SHMEDIA"
15275   "fsrra.s      %1, %0"
15276   [(set_attr "type" "atrans_media")])
15278 (define_insn "ftrv"
15279   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
15280         (plus:V4SF
15281          (plus:V4SF
15282           (mult:V4SF
15283            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
15284                             (parallel [(const_int 0) (const_int 5)
15285                                        (const_int 10) (const_int 15)]))
15286            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
15287           (mult:V4SF
15288            (vec_select:V4SF (match_dup 1)
15289                             (parallel [(const_int 4) (const_int 9)
15290                                        (const_int 14) (const_int 3)]))
15291            (vec_select:V4SF (match_dup 2)
15292                             (parallel [(const_int 1) (const_int 2)
15293                                        (const_int 3) (const_int 0)]))))
15294          (plus:V4SF
15295           (mult:V4SF
15296            (vec_select:V4SF (match_dup 1)
15297                             (parallel [(const_int 8) (const_int 13)
15298                                        (const_int 2) (const_int 7)]))
15299            (vec_select:V4SF (match_dup 2)
15300                             (parallel [(const_int 2) (const_int 3)
15301                                        (const_int 0) (const_int 1)])))
15302           (mult:V4SF
15303            (vec_select:V4SF (match_dup 1)
15304                             (parallel [(const_int 12) (const_int 1)
15305                                        (const_int 6) (const_int 11)]))
15306            (vec_select:V4SF (match_dup 2)
15307                             (parallel [(const_int 3) (const_int 0)
15308                                        (const_int 1) (const_int 2)]))))))]
15309   "TARGET_SHMEDIA"
15310   "ftrv.s %1, %2, %0"
15311   [(set_attr "type" "fparith_media")])
15313 (define_insn "ldhi_l"
15314   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15315         (zero_extract:SI
15316          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15317                                   (const_int 3))
15318                           (const_int -3)))
15319          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
15320          (const_int 0)))]
15321   "TARGET_SHMEDIA32"
15322   "ldhi.l       %U1, %0"
15323   [(set_attr "type" "load_media")])
15325 (define_insn "ldhi_q"
15326   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15327         (zero_extract:DI
15328          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15329                                   (const_int 7))
15330                           (const_int -7)))
15331          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
15332          (const_int 0)))]
15333   "TARGET_SHMEDIA32"
15334   "ldhi.q       %U1, %0"
15335   [(set_attr "type" "load_media")])
15337 (define_insn_and_split "*ldhi_q_comb0"
15338   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15339         (zero_extract:DI
15340          (mem:DI (plus:SI (ior:SI (plus:SI
15341                                     (match_operand:SI 1 "register_operand" "r")
15342                                     (match_operand:SI 2 "ua_offset" "I06"))
15343                                   (const_int 7))
15344                           (const_int -7)))
15345          (plus:SI (and:SI (match_dup 1) (const_int 7))
15346                   (const_int 1))
15347          (const_int 0)))]
15348   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15349   "#"
15350   ""
15351   [(pc)]
15353   emit_insn (gen_ldhi_q (operands[0],
15354                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15355   DONE;
15358 (define_insn_and_split "*ldhi_q_comb1"
15359   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15360         (zero_extract:DI
15361          (mem:DI (plus:SI (ior:SI (plus:SI
15362                                     (match_operand:SI 1 "register_operand" "r")
15363                                     (match_operand:SI 2 "ua_offset" "I06"))
15364                                   (const_int 7))
15365                           (const_int -7)))
15366          (plus:SI (and:SI (plus:SI (match_dup 1)
15367                                    (match_operand:SI 3 "ua_offset" "I06"))
15368                           (const_int 7))
15369                   (const_int 1))
15370          (const_int 0)))]
15371   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15372    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15373   "#"
15374   ""
15375   [(pc)]
15377   emit_insn (gen_ldhi_q (operands[0],
15378                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15379   DONE;
15382 (define_insn "ldlo_l"
15383   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15384         (zero_extract:SI
15385          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15386                          (const_int -4)))
15387          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15388          (and:SI (match_dup 1) (const_int 3))))]
15389   "TARGET_SHMEDIA32"
15390   "ldlo.l       %U1, %0"
15391   [(set_attr "type" "load_media")])
15393 (define_insn "ldlo_q"
15394   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15395         (zero_extract:DI
15396          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15397                          (const_int -8)))
15398          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15399          (and:SI (match_dup 1) (const_int 7))))]
15400   "TARGET_SHMEDIA32"
15401   "ldlo.q       %U1, %0"
15402   [(set_attr "type" "load_media")])
15404 (define_insn_and_split "*ldlo_q_comb0"
15405   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15406         (zero_extract:DI
15407          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15408                                   (match_operand:SI 2 "ua_offset" "I06"))
15409                          (const_int -8)))
15410          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15411          (and:SI (match_dup 1) (const_int 7))))]
15412   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15413   "#"
15414   ""
15415   [(pc)]
15417   emit_insn (gen_ldlo_q (operands[0],
15418                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15419   DONE;
15422 (define_insn_and_split "*ldlo_q_comb1"
15423   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15424         (zero_extract:DI
15425          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15426                                   (match_operand:SI 2 "ua_offset" "I06"))
15427                          (const_int -8)))
15428          (minus:SI (const_int 8)
15429                    (and:SI (plus:SI (match_dup 1)
15430                                     (match_operand:SI 3 "ua_offset" "I06"))
15431                            (const_int 7)))
15432          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15433   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15434    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15435   "#"
15436   ""
15437   [(pc)]
15439   emit_insn (gen_ldlo_q (operands[0],
15440                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15441   DONE;
15444 (define_insn "sthi_l"
15445   [(set (zero_extract:SI
15446          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15447                                   (const_int 3))
15448                           (const_int -3)))
15449          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15450          (const_int 0))
15451         (match_operand:SI 1 "arith_reg_operand" "r"))]
15452   "TARGET_SHMEDIA32"
15453   "sthi.l       %U0, %1"
15454   [(set_attr "type" "ustore_media")])
15456 ;; All unaligned stores are considered to be 'narrow' because they typically
15457 ;; operate on less that a quadword, and when they operate on a full quadword,
15458 ;; the vanilla store high / store low sequence will cause a stall if not
15459 ;; scheduled apart.
15460 (define_insn "sthi_q"
15461   [(set (zero_extract:DI
15462          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15463                                   (const_int 7))
15464                           (const_int -7)))
15465          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15466          (const_int 0))
15467         (match_operand:DI 1 "arith_reg_operand" "r"))]
15468   "TARGET_SHMEDIA32"
15469   "sthi.q       %U0, %1"
15470   [(set_attr "type" "ustore_media")])
15472 (define_insn_and_split "*sthi_q_comb0"
15473   [(set (zero_extract:DI
15474          (mem:DI (plus:SI (ior:SI (plus:SI
15475                                     (match_operand:SI 0 "register_operand" "r")
15476                                     (match_operand:SI 1 "ua_offset" "I06"))
15477                                   (const_int 7))
15478                           (const_int -7)))
15479          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15480          (const_int 0))
15481         (match_operand:DI 2 "arith_reg_operand" "r"))]
15482   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15483   "#"
15484   ""
15485   [(pc)]
15487   emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15488                          operands[2]));
15489   DONE;
15492 (define_insn_and_split "*sthi_q_comb1"
15493   [(set (zero_extract:DI
15494          (mem:DI (plus:SI (ior:SI (plus:SI
15495                                     (match_operand:SI 0 "register_operand" "r")
15496                                     (match_operand:SI 1 "ua_offset" "I06"))
15497                                   (const_int 7))
15498                           (const_int -7)))
15499          (plus:SI (and:SI (plus:SI (match_dup 0)
15500                                    (match_operand:SI 2 "ua_offset" "I06"))
15501                           (const_int 7))
15502                   (const_int 1))
15503          (const_int 0))
15504         (match_operand:DI 3 "arith_reg_operand" "r"))]
15505   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15506    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15507   "#"
15508   ""
15509   [(pc)]
15511   emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15512                          operands[3]));
15513   DONE;
15516 ;; This is highpart user because the address is used as full 64 bit.
15517 (define_insn "stlo_l"
15518   [(set (zero_extract:SI
15519          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15520                          (const_int -4)))
15521          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15522          (and:SI (match_dup 0) (const_int 3)))
15523         (match_operand:SI 1 "arith_reg_operand" "r"))]
15524   "TARGET_SHMEDIA32"
15525   "stlo.l       %U0, %1"
15526   [(set_attr "type" "ustore_media")])
15528 (define_insn "stlo_q"
15529   [(set (zero_extract:DI
15530          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15531                          (const_int -8)))
15532          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15533          (and:SI (match_dup 0) (const_int 7)))
15534         (match_operand:DI 1 "arith_reg_operand" "r"))]
15535   "TARGET_SHMEDIA32"
15536   "stlo.q       %U0, %1"
15537   [(set_attr "type" "ustore_media")])
15539 (define_insn_and_split "*stlo_q_comb0"
15540   [(set (zero_extract:DI
15541          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15542                                   (match_operand:SI 1 "ua_offset" "I06"))
15543                          (const_int -8)))
15544          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15545          (and:SI (match_dup 0) (const_int 7)))
15546         (match_operand:DI 2 "arith_reg_operand" "r"))]
15547   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15548   "#"
15549   ""
15550   [(pc)]
15552   emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15553                          operands[2]));
15554   DONE;
15557 (define_insn_and_split "*stlo_q_comb1"
15558   [(set (zero_extract:DI
15559          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15560                                   (match_operand:SI 1 "ua_offset" "I06"))
15561                          (const_int -8)))
15562          (minus:SI (const_int 8)
15563                    (and:SI (plus:SI (match_dup 0)
15564                                     (match_operand:SI 2 "ua_offset" "I06"))
15565                            (const_int 7)))
15566          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15567         (match_operand:DI 3 "arith_reg_operand" "r"))]
15568   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15569   "#"
15570   ""
15571   [(pc)]
15573   emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15574                          operands[3]));
15575    DONE;
15578 (define_insn "ldhi_l64"
15579   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15580         (zero_extract:SI
15581          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15582                                   (const_int 3))
15583                           (const_int -3)))
15584          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15585          (const_int 0)))]
15586   "TARGET_SHMEDIA64"
15587   "ldhi.l       %U1, %0"
15588   [(set_attr "type" "load_media")])
15590 (define_insn "ldhi_q64"
15591   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15592         (zero_extract:DI
15593          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15594                                   (const_int 7))
15595                           (const_int -7)))
15596          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15597          (const_int 0)))]
15598   "TARGET_SHMEDIA64"
15599   "ldhi.q       %U1, %0"
15600   [(set_attr "type" "load_media")])
15602 (define_insn "ldlo_l64"
15603   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15604         (zero_extract:SI
15605          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15606                          (const_int -4)))
15607          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15608          (and:DI (match_dup 1) (const_int 3))))]
15609   "TARGET_SHMEDIA64"
15610   "ldlo.l       %U1, %0"
15611   [(set_attr "type" "load_media")])
15613 (define_insn "ldlo_q64"
15614   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15615         (zero_extract:DI
15616          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15617                          (const_int -8)))
15618          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15619          (and:DI (match_dup 1) (const_int 7))))]
15620   "TARGET_SHMEDIA64"
15621   "ldlo.q       %U1, %0"
15622   [(set_attr "type" "load_media")])
15624 (define_insn "sthi_l64"
15625   [(set (zero_extract:SI
15626          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15627                                   (const_int 3))
15628                           (const_int -3)))
15629          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15630          (const_int 0))
15631         (match_operand:SI 1 "arith_reg_operand" "r"))]
15632   "TARGET_SHMEDIA64"
15633   "sthi.l       %U0, %1"
15634   [(set_attr "type" "ustore_media")])
15636 (define_insn "sthi_q64"
15637   [(set (zero_extract:DI
15638          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15639                                   (const_int 7))
15640                           (const_int -7)))
15641          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15642          (const_int 0))
15643         (match_operand:DI 1 "arith_reg_operand" "r"))]
15644   "TARGET_SHMEDIA64"
15645   "sthi.q       %U0, %1"
15646   [(set_attr "type" "ustore_media")])
15648 (define_insn "stlo_l64"
15649   [(set (zero_extract:SI
15650          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15651                          (const_int -4)))
15652          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15653          (and:DI (match_dup 0) (const_int 3)))
15654         (match_operand:SI 1 "arith_reg_operand" "r"))]
15655   "TARGET_SHMEDIA64"
15656   "stlo.l       %U0, %1"
15657   [(set_attr "type" "ustore_media")])
15659 (define_insn "stlo_q64"
15660   [(set (zero_extract:DI
15661          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15662                          (const_int -8)))
15663          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15664          (and:DI (match_dup 0) (const_int 7)))
15665         (match_operand:DI 1 "arith_reg_operand" "r"))]
15666   "TARGET_SHMEDIA64"
15667   "stlo.q       %U0, %1"
15668   [(set_attr "type" "ustore_media")])
15670 (define_insn "nsb"
15671   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15672         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15673                    UNSPEC_NSB))]
15674   "TARGET_SHMEDIA"
15675   "nsb  %1, %0"
15676   [(set_attr "type" "arith_media")])
15678 (define_insn "nsbsi"
15679   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15680         (zero_extend:SI
15681          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15682                     UNSPEC_NSB)))]
15683   "TARGET_SHMEDIA"
15684   "nsb  %1, %0"
15685   [(set_attr "type" "arith_media")])
15687 (define_insn "nsbdi"
15688   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15689         (zero_extend:DI
15690          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15691                     UNSPEC_NSB)))]
15692   "TARGET_SHMEDIA"
15693   "nsb  %1, %0"
15694   [(set_attr "type" "arith_media")])
15696 (define_expand "ffsdi2"
15697   [(set (match_operand:DI 0 "arith_reg_dest" "")
15698         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15699   "TARGET_SHMEDIA"
15701   rtx scratch = gen_reg_rtx (DImode);
15702   rtx last;
15704   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15705   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15706   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15707   emit_insn (gen_nsbdi (scratch, scratch));
15708   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15709   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15710   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15711   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15713   DONE;
15716 (define_expand "ffssi2"
15717   [(set (match_operand:SI 0 "arith_reg_dest" "")
15718         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15719   "TARGET_SHMEDIA"
15721   rtx scratch = gen_reg_rtx (SImode);
15722   rtx discratch = gen_reg_rtx (DImode);
15723   rtx last;
15725   emit_insn (gen_adddi3 (discratch,
15726                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
15727                          constm1_rtx));
15728   emit_insn (gen_andcdi3 (discratch,
15729                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
15730                           discratch));
15731   emit_insn (gen_nsbsi (scratch, discratch));
15732   last = emit_insn (gen_subsi3 (operands[0],
15733                                 force_reg (SImode, GEN_INT (63)), scratch));
15734   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15736   DONE;
15739 (define_insn "byterev"
15740   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15741         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15742                          (parallel [(const_int 7) (const_int 6) (const_int 5)
15743                                     (const_int 4) (const_int 3) (const_int 2)
15744                                     (const_int 1) (const_int 0)])))]
15745   "TARGET_SHMEDIA"
15746   "byterev      %1, %0"
15747   [(set_attr "type" "arith_media")])
15749 ;; In user mode, the "pref" instruction will raise a RADDERR exception
15750 ;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
15751 ;; implementation of __builtin_prefetch for VxWorks RTPs.
15752 (define_expand "prefetch"
15753   [(prefetch (match_operand 0 "address_operand" "")
15754              (match_operand:SI 1 "const_int_operand" "")
15755              (match_operand:SI 2 "const_int_operand" ""))]
15756   "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15757    && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15759 (define_insn "*prefetch"
15760   [(prefetch (match_operand:SI 0 "register_operand" "r")
15761              (match_operand:SI 1 "const_int_operand" "n")
15762              (match_operand:SI 2 "const_int_operand" "n"))]
15763   "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15764   "pref @%0"
15765   [(set_attr "type" "other")])
15767 (define_insn "*prefetch_media"
15768   [(prefetch (match_operand:QI 0 "address_operand" "p")
15769              (match_operand:SI 1 "const_int_operand" "n")
15770              (match_operand:SI 2 "const_int_operand" "n"))]
15771   "TARGET_SHMEDIA"
15773   operands[0] = gen_rtx_MEM (QImode, operands[0]);
15774   output_asm_insn ("ld%M0.b     %m0,r63", operands);
15775   return "";
15777   [(set_attr "type" "other")])
15779 (define_insn "alloco_i"
15780   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15781         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15782   "TARGET_SHMEDIA32"
15784   rtx xops[2];
15786   if (GET_CODE (operands[0]) == PLUS)
15787     {
15788       xops[0] = XEXP (operands[0], 0);
15789       xops[1] = XEXP (operands[0], 1);
15790     }
15791   else
15792     {
15793       xops[0] = operands[0];
15794       xops[1] = const0_rtx;
15795     }
15796   output_asm_insn ("alloco      %0, %1", xops);
15797   return "";
15799   [(set_attr "type" "other")])
15801 (define_split
15802   [(set (match_operand 0 "any_register_operand" "")
15803         (match_operand 1 "" ""))]
15804   "TARGET_SHMEDIA && reload_completed"
15805   [(set (match_dup 0) (match_dup 1))]
15807   int n_changes = 0;
15809   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15810   if (!n_changes)
15811     FAIL;
15814 ;; -------------------------------------------------------------------------
15815 ;; Stack Protector Patterns
15816 ;; -------------------------------------------------------------------------
15818 (define_expand "stack_protect_set"
15819   [(set (match_operand 0 "memory_operand" "")
15820         (match_operand 1 "memory_operand" ""))]
15821   ""
15823   if (TARGET_SHMEDIA)
15824     {
15825       if (TARGET_SHMEDIA64)
15826         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15827       else
15828         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15829     }
15830   else
15831     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15833   DONE;
15836 (define_insn "stack_protect_set_si"
15837   [(set (match_operand:SI 0 "memory_operand" "=m")
15838         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15839    (set (match_scratch:SI 2 "=&r") (const_int 0))]
15840   "!TARGET_SHMEDIA"
15842   return       "mov.l   %1,%2"  "\n"
15843          "      mov.l   %2,%0"  "\n"
15844          "      mov     #0,%2";
15846   [(set_attr "type" "other")
15847    (set_attr "length" "6")])
15849 (define_insn "stack_protect_set_si_media"
15850   [(set (match_operand:SI 0 "memory_operand" "=m")
15851         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15852    (set (match_scratch:SI 2 "=&r") (const_int 0))]
15853   "TARGET_SHMEDIA"
15855   return       "ld%M1.l %m1,%2" "\n"
15856          "      st%M0.l %m0,%2" "\n"
15857          "      movi    0,%2";
15859   [(set_attr "type" "other")
15860    (set_attr "length" "12")])
15862 (define_insn "stack_protect_set_di_media"
15863   [(set (match_operand:DI 0 "memory_operand" "=m")
15864         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15865    (set (match_scratch:DI 2 "=&r") (const_int 0))]
15866   "TARGET_SHMEDIA64"
15868   return       "ld%M1.q %m1,%2" "\n"
15869          "      st%M0.q %m0,%2" "\n"
15870          "      movi    0,%2";
15872   [(set_attr "type" "other")
15873    (set_attr "length" "12")])
15875 (define_expand "stack_protect_test"
15876   [(match_operand 0 "memory_operand" "")
15877    (match_operand 1 "memory_operand" "")
15878    (match_operand 2 "" "")]
15879   ""
15881   if (TARGET_SHMEDIA)
15882     {
15883       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15884       rtx test;
15886       test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15887       if (TARGET_SHMEDIA64)
15888         {
15889           emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15890                                                       operands[1]));
15891           emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15892         }
15893       else
15894         {
15895           emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15896                                                       operands[1]));
15897           emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15898         }
15899     }
15900   else
15901     {
15902       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15903       emit_jump_insn (gen_branch_true (operands[2]));
15904     }
15906   DONE;
15909 (define_insn "stack_protect_test_si"
15910   [(set (reg:SI T_REG)
15911         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15912                     (match_operand:SI 1 "memory_operand" "m")]
15913                    UNSPEC_SP_TEST))
15914   (set (match_scratch:SI 2 "=&r") (const_int 0))
15915   (set (match_scratch:SI 3 "=&r") (const_int 0))]
15916   "!TARGET_SHMEDIA"
15918   return       "mov.l   %0,%2"  "\n"
15919          "      mov.l   %1,%3"  "\n"
15920          "      cmp/eq  %2,%3"  "\n"
15921          "      mov     #0,%2"  "\n"
15922          "      mov     #0,%3";
15924   [(set_attr "type" "other")
15925    (set_attr "length" "10")])
15927 (define_insn "stack_protect_test_si_media"
15928   [(set (match_operand:SI 0 "register_operand" "=&r")
15929         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15930                     (match_operand:SI 2 "memory_operand" "m")]
15931                    UNSPEC_SP_TEST))
15932   (set (match_scratch:SI 3 "=&r") (const_int 0))]
15933   "TARGET_SHMEDIA"
15935   return       "ld%M1.l %m1,%0"         "\n"
15936          "      ld%M2.l %m2,%3"         "\n"
15937          "      cmpeq   %0,%3,%0"       "\n"
15938          "      movi    0,%3";
15940   [(set_attr "type" "other")
15941    (set_attr "length" "16")])
15943 (define_insn "stack_protect_test_di_media"
15944   [(set (match_operand:DI 0 "register_operand" "=&r")
15945         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15946                     (match_operand:DI 2 "memory_operand" "m")]
15947                    UNSPEC_SP_TEST))
15948   (set (match_scratch:DI 3 "=&r") (const_int 0))]
15949   "TARGET_SHMEDIA64"
15951   return       "ld%M1.q %m1,%0"         "\n"
15952          "      ld%M2.q %m2,%3"         "\n"
15953          "      cmpeq   %0,%3,%0"       "\n"
15954          "      movi    0,%3";
15956   [(set_attr "type" "other")
15957    (set_attr "length" "16")])
15959 ;; -------------------------------------------------------------------------
15960 ;; Atomic operations
15961 ;; -------------------------------------------------------------------------
15963 (include "sync.md")