Merge branches/gcc-4_9-branch rev 225109.
[official-gcc.git] / gcc-4_9-branch / gcc / config / sh / sh.md
blob6b1cf12010ed49c6c42e5670fbc52091b86a8db9
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993-2014 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 ;; Extract LSB, negate and store in T bit.
655 (define_insn "tstsi_t_and_not"
656   [(set (reg:SI T_REG)
657          (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
658                  (const_int 1)))]
659   "TARGET_SH1"
660   "tst  #1,%0"
661   [(set_attr "type" "mt_group")])
663 ;; Extract contiguous bits and compare them against zero.
664 (define_insn "tst<mode>_t_zero_extract_eq"
665   [(set (reg:SI T_REG)
666         (eq:SI (zero_extract:SI (match_operand:QIHISIDI 0 "logical_operand" "z")
667                                 (match_operand:SI 1 "const_int_operand")
668                                 (match_operand:SI 2 "const_int_operand"))
669                (const_int 0)))]
670   "TARGET_SH1
671    && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
673   operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
674   return "tst   %1,%0";
676   [(set_attr "type" "mt_group")])
678 ;; This split is required when testing bits in a QI subreg.
679 (define_split
680   [(set (reg:SI T_REG)
681         (eq:SI
682           (if_then_else:SI
683             (zero_extract:SI (match_operand 0 "logical_operand")
684                              (match_operand 1 "const_int_operand")
685                              (match_operand 2 "const_int_operand"))
686             (match_operand 3 "const_int_operand")
687             (const_int 0))
688           (const_int 0)))]
689   "TARGET_SH1
690    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
691    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
692   [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
693                               (const_int 0)))]
695   if (GET_MODE (operands[0]) == QImode)
696     operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
699 ;; Extract single bit, negate and store it in the T bit.
700 ;; Not used for SH4A.
701 (define_insn "tstsi_t_zero_extract_xor"
702   [(set (reg:SI T_REG)
703         (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
704                                  (match_operand:SI 3 "const_int_operand"))
705                          (match_operand:SI 1 "const_int_operand")
706                          (match_operand:SI 2 "const_int_operand")))]
707   "TARGET_SH1
708    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
709    && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
710   "tst  %3,%0"
711   [(set_attr "type" "mt_group")])
713 ;; Extract single bit, negate and store it in the T bit.
714 ;; Used for SH4A little endian.
715 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
716   [(set (reg:SI T_REG)
717         (zero_extract:SI
718          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
719                             (match_operand:SI 3 "const_int_operand")) 0)
720          (match_operand:SI 1 "const_int_operand")
721          (match_operand:SI 2 "const_int_operand")))]
722   "TARGET_SH1 && TARGET_LITTLE_ENDIAN
723    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
724       == (INTVAL (operands[3]) & 255)
725    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
727   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
728   return "tst   %3,%0";
730   [(set_attr "type" "mt_group")])
732 ;; Extract single bit, negate and store it in the T bit.
733 ;; Used for SH4A big endian.
734 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
735   [(set (reg:SI T_REG)
736         (zero_extract:SI
737          (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
738                             (match_operand:SI 3 "const_int_operand")) 3)
739          (match_operand:SI 1 "const_int_operand")
740          (match_operand:SI 2 "const_int_operand")))]
741   "TARGET_SH1 && TARGET_BIG_ENDIAN
742    && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
743       == (INTVAL (operands[3]) & 255)
744    && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
746   operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
747   return "tst   %3,%0";
749   [(set_attr "type" "mt_group")])
751 (define_insn "cmpeqsi_t"
752   [(set (reg:SI T_REG)
753         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
754                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
755   "TARGET_SH1"
756   "@
757         tst     %0,%0
758         cmp/eq  %1,%0
759         cmp/eq  %1,%0"
760   [(set_attr "type" "mt_group")])
762 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
763 ;; pattern by itself.  What this actually does is:
764 ;;      x == 0: (1 >> 0-0) & 1 = 1
765 ;;      x != 0: (1 >> 0-x) & 1 = 0
766 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
767 (define_insn_and_split "*cmpeqsi_t"
768   [(set (reg:SI T_REG)
769         (and:SI (lshiftrt:SI
770                   (const_int 1)
771                   (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
772                 (const_int 1)))]
773   "TARGET_SH1"
774   "#"
775   "&& 1"
776   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
778 (define_insn "cmpgtsi_t"
779   [(set (reg:SI T_REG)
780         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
781                (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
782   "TARGET_SH1"
783   "@
784         cmp/pl  %0
785         cmp/gt  %1,%0"
786   [(set_attr "type" "mt_group")])
788 (define_insn "cmpgesi_t"
789   [(set (reg:SI T_REG)
790         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
791                (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
792   "TARGET_SH1"
793   "@
794         cmp/pz  %0
795         cmp/ge  %1,%0"
796   [(set_attr "type" "mt_group")])
798 ;; FIXME: This is actually wrong.  There is no way to literally move a
799 ;; general reg to t reg.  Luckily, it seems that this pattern will be only
800 ;; used when the general reg is known be either '0' or '1' during combine.
801 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
802 ;; Due to interactions with other patterns, combine fails to pick the latter
803 ;; and invert the dependent logic.
804 (define_insn "*negtstsi"
805   [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
806   "TARGET_SH1"
807   "cmp/pl       %0"
808   [(set_attr "type" "mt_group")])
810 ;; Some integer sign comparison patterns can be realized with the div0s insn.
811 ;;      div0s   Rm,Rn           T = (Rm >> 31) ^ (Rn >> 31)
812 (define_insn "cmp_div0s_0"
813   [(set (reg:SI T_REG)
814         (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
815                              (match_operand:SI 1 "arith_reg_operand" "r"))
816                      (const_int 31)))]
817   "TARGET_SH1"
818   "div0s        %0,%1"
819   [(set_attr "type" "arith")])
821 (define_insn "cmp_div0s_1"
822   [(set (reg:SI T_REG)
823         (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
824                        (match_operand:SI 1 "arith_reg_operand" "r"))
825                (const_int 0)))]
826   "TARGET_SH1"
827   "div0s        %0,%1"
828   [(set_attr "type" "arith")])
830 (define_insn_and_split "*cmp_div0s_0"
831   [(set (match_operand:SI 0 "arith_reg_dest" "")
832         (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
833                              (match_operand:SI 2 "arith_reg_operand" ""))
834                      (const_int 31)))
835    (clobber (reg:SI T_REG))]
836   "TARGET_SH1"
837   "#"
838   "&& 1"
839   [(set (reg:SI T_REG)
840         (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
841    (set (match_dup 0) (reg:SI T_REG))])
843 (define_insn "*cmp_div0s_0"
844   [(set (reg:SI T_REG)
845         (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand" "%r")
846                             (const_int 31))
847                (ge:SI (match_operand:SI 1 "arith_reg_operand" "r")
848                       (const_int 0))))]
849   "TARGET_SH1"
850   "div0s        %0,%1"
851   [(set_attr "type" "arith")])
853 (define_insn_and_split "*cmp_div0s_1"
854   [(set (match_operand:SI 0 "arith_reg_dest" "")
855         (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
856                        (match_operand:SI 2 "arith_reg_operand" ""))
857                (const_int 0)))
858    (clobber (reg:SI T_REG))]
859   "TARGET_SH1"
860   "#"
861   "&& can_create_pseudo_p ()"
862   [(const_int 0)]
863 ;; We have to go through the movnegt expander here which will handle the
864 ;; SH2A vs non-SH2A cases.
866   emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
867   emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
868   DONE;
871 (define_insn_and_split "*cmp_div0s_1"
872   [(set (reg:SI T_REG)
873         (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
874                        (match_operand:SI 1 "arith_reg_operand" ""))
875                (const_int 0)))]
876   "TARGET_SH1"
877   "#"
878   "&& can_create_pseudo_p ()"
879   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
880                               (const_int 0)))
881    (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
883 (define_insn_and_split "*cmp_div0s_1"
884   [(set (reg:SI T_REG)
885         (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
886                             (const_int 31))
887                (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
888                             (const_int 31))))]
889   "TARGET_SH1"
890   "#"
891   "&& can_create_pseudo_p ()"
892   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
893                               (const_int 0)))
894    (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
896 ;; -------------------------------------------------------------------------
897 ;; SImode compare and branch
898 ;; -------------------------------------------------------------------------
900 (define_expand "cbranchsi4"
901   [(set (pc)
902         (if_then_else (match_operator 0 "comparison_operator"
903                         [(match_operand:SI 1 "arith_operand" "")
904                          (match_operand:SI 2 "arith_operand" "")])
905                       (label_ref (match_operand 3 "" ""))
906                       (pc)))
907    (clobber (reg:SI T_REG))]
908   ""
910   if (TARGET_SHMEDIA)
911     emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
912                                            operands[2], operands[3]));
913   else
914     expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
916   DONE;
919 ;; Combine patterns to invert compare and branch operations for which we
920 ;; don't have actual comparison insns.  These patterns are used in cases
921 ;; which appear after the initial cbranchsi expansion, which also does
922 ;; some condition inversion.
923 (define_split
924   [(set (pc)
925         (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
926                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
927                       (label_ref (match_operand 2))
928                       (pc)))
929    (clobber (reg:SI T_REG))]
930   "TARGET_SH1"
931   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
932    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
933                            (label_ref (match_dup 2))
934                            (pc)))])
936 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
937 ;; and SH2A combine fails to simplify this pattern by itself.
938 ;; What this actually does is:
939 ;;      x == 0: (1 >> 0-0) & 1 = 1
940 ;;      x != 0: (1 >> 0-x) & 1 = 0
941 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
942 (define_split
943   [(set (pc)
944         (if_then_else
945           (eq (and:SI (lshiftrt:SI
946                         (const_int 1)
947                         (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
948                       (const_int 1))
949               (const_int 0))
950           (label_ref (match_operand 2))
951           (pc)))
952    (clobber (reg:SI T_REG))]
953   "TARGET_SH1"
954   [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
955    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
956                            (label_ref (match_dup 2))
957                            (pc)))])
959 ;; FIXME: These could probably use code iterators for the compare op.
960 (define_split
961   [(set (pc)
962         (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
963                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
964                       (label_ref (match_operand 2))
965                       (pc)))
966    (clobber (reg:SI T_REG))]
967   "TARGET_SH1"
968   [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
969    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
970                            (label_ref (match_dup 2))
971                            (pc)))])
973 (define_split
974   [(set (pc)
975         (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
976                           (match_operand:SI 1 "arith_reg_or_0_operand" ""))
977                       (label_ref (match_operand 2))
978                       (pc)))
979    (clobber (reg:SI T_REG))]
980   "TARGET_SH1"
981   [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
982    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
983                            (label_ref (match_dup 2))
984                            (pc)))])
986 (define_split
987   [(set (pc)
988         (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
989                            (match_operand:SI 1 "arith_reg_operand" ""))
990                       (label_ref (match_operand 2))
991                       (pc)))
992    (clobber (reg:SI T_REG))]
993   "TARGET_SH1"
994   [(set (reg:SI T_REG) (gtu: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 (ltu (match_operand:SI 0 "arith_reg_operand" "")
1002                            (match_operand:SI 1 "arith_reg_operand" ""))
1003                       (label_ref (match_operand 2))
1004                       (pc)))
1005    (clobber (reg:SI T_REG))]
1006   "TARGET_SH1"
1007   [(set (reg:SI T_REG) (geu: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 ;; Compare and branch combine patterns for div0s comparisons.
1013 (define_insn_and_split "*cbranch_div0s"
1014   [(set (pc)
1015         (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1016                                   (match_operand:SI 1 "arith_reg_operand" ""))
1017                           (const_int 0))
1018                       (label_ref (match_operand 2))
1019                       (pc)))
1020    (clobber (reg:SI T_REG))]
1021   "TARGET_SH1"
1022   "#"
1023   "&& 1"
1024   [(set (reg:SI T_REG)
1025         (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1026    (set (pc)
1027         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1028                       (label_ref (match_dup 2))
1029                       (pc)))])
1031 (define_insn_and_split "*cbranch_div0s"
1032   [(set (pc)
1033         (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1034                                   (match_operand:SI 1 "arith_reg_operand" ""))
1035                           (const_int 0))
1036                       (label_ref (match_operand 2))
1037                       (pc)))
1038    (clobber (reg:SI T_REG))]
1039   "TARGET_SH1"
1040   "#"
1041   "&& 1"
1042   [(set (reg:SI T_REG)
1043         (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1044    (set (pc)
1045         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1046                       (label_ref (match_dup 2))
1047                       (pc)))])
1049 ;; Conditional move combine pattern for div0s comparisons.
1050 ;; This is used when TARGET_PRETEND_CMOVE is in effect.
1051 (define_insn_and_split "*movsicc_div0s"
1052   [(set (match_operand:SI 0 "arith_reg_dest" "")
1053         (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1054                                      (match_operand:SI 2 "arith_reg_operand" ""))
1055                              (const_int 0))
1056                          (match_operand:SI 3 "arith_reg_operand" "")
1057                          (match_operand:SI 4 "general_movsrc_operand" "")))
1058    (clobber (reg:SI T_REG))]
1059   "TARGET_PRETEND_CMOVE"
1060   "#"
1061   "&& 1"
1062   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1063                               (const_int 0)))
1064    (set (match_dup 0)
1065         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1066                       (match_dup 4)
1067                       (match_dup 3)))])
1069 (define_insn_and_split "*movsicc_div0s"
1070   [(set (match_operand:SI 0 "arith_reg_dest")
1071         (if_then_else:SI (eq (lshiftrt:SI
1072                                 (match_operand:SI 1 "arith_reg_operand")
1073                                 (const_int 31))
1074                              (lshiftrt:SI
1075                                 (match_operand:SI 2 "arith_reg_operand")
1076                                 (const_int 31)))
1077                          (match_operand:SI 3 "arith_reg_operand")
1078                          (match_operand:SI 4 "general_movsrc_operand")))
1079    (clobber (reg:SI T_REG))]
1080    "TARGET_PRETEND_CMOVE"
1081    "#"
1082    "&& 1"
1083   [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1084                               (const_int 0)))
1085    (set (match_dup 0)
1086         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1087                       (match_dup 4)
1088                       (match_dup 3)))])
1090 ;; -------------------------------------------------------------------------
1091 ;; SImode unsigned integer comparisons
1092 ;; -------------------------------------------------------------------------
1094 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1095 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1096 ;; might remain and we have to handle them.  If the '>= 0' case wasn't
1097 ;; handled here, something else would just load a '0' into the second operand
1098 ;; and do the comparison.  We can do slightly better by just setting the
1099 ;; T bit to '1'.
1100 (define_insn_and_split "cmpgeusi_t"
1101   [(set (reg:SI T_REG)
1102         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1103                 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1104   "TARGET_SH1"
1105   "cmp/hs       %1,%0"
1106   "&& satisfies_constraint_Z (operands[1])"
1107   [(set (reg:SI T_REG) (const_int 1))]
1108   ""
1109   [(set_attr "type" "mt_group")])
1111 (define_insn "cmpgtusi_t"
1112   [(set (reg:SI T_REG)
1113         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1114                 (match_operand:SI 1 "arith_reg_operand" "r")))]
1115   "TARGET_SH1"
1116   "cmp/hi       %1,%0"
1117   [(set_attr "type" "mt_group")])
1119 ;; -------------------------------------------------------------------------
1120 ;; DImode compare and branch
1121 ;; -------------------------------------------------------------------------
1123 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1124 ;; Therefore, we aim to have a set of three branches that go straight to the
1125 ;; destination, i.e. only one of them is taken at any one time.
1126 ;; This mechanism should also be slightly better for the sh4-200.
1128 (define_expand "cbranchdi4"
1129   [(set (pc)
1130         (if_then_else (match_operator 0 "comparison_operator"
1131                         [(match_operand:DI 1 "arith_operand" "")
1132                          (match_operand:DI 2 "arith_operand" "")])
1133                       (label_ref (match_operand 3 "" ""))
1134                       (pc)))
1135    (clobber (match_dup 4))
1136    (clobber (reg:SI T_REG))]
1137   "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1139   enum rtx_code comparison;
1141   if (TARGET_SHMEDIA)
1142     {
1143       emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1144                                              operands[2], operands[3]));
1145       DONE;
1146     }
1147   else if (!TARGET_CBRANCHDI4)
1148     {
1149       sh_emit_compare_and_branch (operands, DImode);
1150       DONE;
1151     }
1152   else
1153     {
1154       if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1155         DONE;
1157       comparison = prepare_cbranch_operands (operands, DImode,
1158                                              LAST_AND_UNUSED_RTX_CODE);
1159       if (comparison != GET_CODE (operands[0]))
1160         operands[0]
1161           = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1162        operands[4] = gen_rtx_SCRATCH (SImode);
1163     }
1166 (define_insn_and_split "cbranchdi4_i"
1167   [(set (pc)
1168         (if_then_else (match_operator 0 "comparison_operator"
1169                         [(match_operand:DI 1 "arith_operand" "r,r")
1170                          (match_operand:DI 2 "arith_operand" "rN,I08")])
1171                       (label_ref (match_operand 3 "" ""))
1172                       (pc)))
1173    (clobber (match_scratch:SI 4 "=X,&r"))
1174    (clobber (reg:SI T_REG))]
1175   "TARGET_CBRANCHDI4"
1176   "#"
1177   "&& reload_completed"
1178   [(pc)]
1180   if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1181     FAIL;
1182   DONE;
1185 ;; -------------------------------------------------------------------------
1186 ;; DImode signed integer comparisons
1187 ;; -------------------------------------------------------------------------
1189 (define_insn ""
1190   [(set (reg:SI T_REG)
1191         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1192                        (match_operand:DI 1 "arith_operand" "r"))
1193                (const_int 0)))]
1194   "TARGET_SH1"
1196   return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1197                               insn, operands);
1199   [(set_attr "length" "6")
1200    (set_attr "type" "arith3b")])
1202 (define_insn "cmpeqdi_t"
1203   [(set (reg:SI T_REG)
1204         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1205                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1206   "TARGET_SH1"
1208   static const char* alt[] =
1209   {
1210        "tst     %S0,%S0"        "\n"
1211     "   bf      0f"             "\n"
1212     "   tst     %R0,%R0"        "\n"
1213     "0:",
1215        "cmp/eq  %S1,%S0"        "\n"
1216     "   bf      0f"             "\n"
1217     "   cmp/eq  %R1,%R0"        "\n"
1218     "0:"
1219   };
1220   return alt[which_alternative];
1222   [(set_attr "length" "6")
1223    (set_attr "type" "arith3b")])
1225 (define_split
1226   [(set (reg:SI T_REG)
1227         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1228                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1229 ;; If we applied this split when not optimizing, it would only be
1230 ;; applied during the machine-dependent reorg, when no new basic blocks
1231 ;; may be created.
1232   "TARGET_SH1 && reload_completed && optimize"
1233   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1234    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1235                            (label_ref (match_dup 6))
1236                            (pc)))
1237    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1238    (match_dup 6)]
1240   operands[2] = gen_highpart (SImode, operands[0]);
1241   operands[3] = operands[1] == const0_rtx
1242                 ? const0_rtx
1243                 : gen_highpart (SImode, operands[1]);
1244   operands[4] = gen_lowpart (SImode, operands[0]);
1245   operands[5] = gen_lowpart (SImode, operands[1]);
1246   operands[6] = gen_label_rtx ();
1249 (define_insn "cmpgtdi_t"
1250   [(set (reg:SI T_REG)
1251         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1252                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1253   "TARGET_SH2"
1255   static const char* alt[] =
1256   {
1257        "cmp/eq  %S1,%S0"        "\n"
1258     "   bf{.|/}s        0f"     "\n"
1259     "   cmp/gt  %S1,%S0"        "\n"
1260     "   cmp/hi  %R1,%R0"        "\n"
1261     "0:",
1263         "tst    %S0,%S0"        "\n"
1264     "   bf{.|/}s        0f"     "\n"
1265     "   cmp/pl  %S0"            "\n"
1266     "   cmp/hi  %S0,%R0"        "\n"
1267     "0:"
1268   };
1269   return alt[which_alternative];
1271   [(set_attr "length" "8")
1272    (set_attr "type" "arith3")])
1274 (define_insn "cmpgedi_t"
1275   [(set (reg:SI T_REG)
1276         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1277                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1278   "TARGET_SH2"
1280   static const char* alt[] =
1281   {
1282        "cmp/eq  %S1,%S0"        "\n"
1283     "   bf{.|/}s        0f"     "\n"
1284     "   cmp/ge  %S1,%S0"        "\n"
1285     "   cmp/hs  %R1,%R0"        "\n"
1286     "0:",
1288        "cmp/pz  %S0"
1289   };
1290   return alt[which_alternative];
1292   [(set_attr "length" "8,2")
1293    (set_attr "type" "arith3,mt_group")])
1295 ;; -------------------------------------------------------------------------
1296 ;; DImode unsigned integer comparisons
1297 ;; -------------------------------------------------------------------------
1299 (define_insn "cmpgeudi_t"
1300   [(set (reg:SI T_REG)
1301         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1302                 (match_operand:DI 1 "arith_reg_operand" "r")))]
1303   "TARGET_SH2"
1305   return       "cmp/eq  %S1,%S0"        "\n"
1306          "      bf{.|/}s        0f"     "\n"
1307          "      cmp/hs  %S1,%S0"        "\n"
1308          "      cmp/hs  %R1,%R0"        "\n"
1309          "0:";
1311   [(set_attr "length" "8")
1312    (set_attr "type" "arith3")])
1314 (define_insn "cmpgtudi_t"
1315   [(set (reg:SI T_REG)
1316         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1317                 (match_operand:DI 1 "arith_reg_operand" "r")))]
1318   "TARGET_SH2"
1320   return       "cmp/eq  %S1,%S0"        "\n"
1321          "      bf{.|/}s        0f"     "\n"
1322          "      cmp/hi  %S1,%S0"        "\n"
1323          "      cmp/hi  %R1,%R0"        "\n"
1324          "0:";
1326   [(set_attr "length" "8")
1327    (set_attr "type" "arith3")])
1329 (define_insn "cmpeqsi_media"
1330   [(set (match_operand:SI 0 "register_operand" "=r")
1331         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1332                (match_operand:SI 2 "cmp_operand" "Nr")))]
1333   "TARGET_SHMEDIA"
1334   "cmpeq        %1, %N2, %0"
1335   [(set_attr "type" "cmp_media")])
1337 (define_insn "cmpeqdi_media"
1338   [(set (match_operand:SI 0 "register_operand" "=r")
1339         (eq:SI (match_operand:DI 1 "register_operand" "%r")
1340                (match_operand:DI 2 "cmp_operand" "Nr")))]
1341   "TARGET_SHMEDIA"
1342   "cmpeq        %1, %N2, %0"
1343   [(set_attr "type" "cmp_media")])
1345 (define_insn "cmpgtsi_media"
1346   [(set (match_operand:SI 0 "register_operand" "=r")
1347         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1348                (match_operand:SI 2 "cmp_operand" "rN")))]
1349   "TARGET_SHMEDIA"
1350   "cmpgt        %N1, %N2, %0"
1351   [(set_attr "type" "cmp_media")])
1353 (define_insn "cmpgtdi_media"
1354   [(set (match_operand:SI 0 "register_operand" "=r")
1355         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1356                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1357   "TARGET_SHMEDIA"
1358   "cmpgt        %N1, %N2, %0"
1359   [(set_attr "type" "cmp_media")])
1361 (define_insn "cmpgtusi_media"
1362   [(set (match_operand:SI 0 "register_operand" "=r")
1363         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1364                 (match_operand:SI 2 "cmp_operand" "rN")))]
1365   "TARGET_SHMEDIA"
1366   "cmpgtu       %N1, %N2, %0"
1367   [(set_attr "type" "cmp_media")])
1369 (define_insn "cmpgtudi_media"
1370   [(set (match_operand:SI 0 "register_operand" "=r")
1371         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1372                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1373   "TARGET_SHMEDIA"
1374   "cmpgtu       %N1, %N2, %0"
1375   [(set_attr "type" "cmp_media")])
1377 ; This pattern is for combine.
1378 (define_insn "*cmpne0sisi_media"
1379   [(set (match_operand:SI 0 "register_operand" "=r")
1380         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1381   "TARGET_SHMEDIA"
1382   "cmpgtu       %1,r63,%0"
1383   [(set_attr "type" "cmp_media")])
1385 ;; -------------------------------------------------------------------------
1386 ;; Conditional move instructions
1387 ;; -------------------------------------------------------------------------
1389 ;; The insn names may seem reversed, but note that cmveq performs the move
1390 ;; if op1 == 0, and cmvne does it if op1 != 0.
1392 (define_insn "movdicc_false"
1393   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1394         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1395                              (const_int 0))
1396          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1397          (match_operand:DI 3 "arith_reg_operand" "0")))]
1398   "TARGET_SHMEDIA"
1399   "cmveq        %1, %N2, %0"
1400   [(set_attr "type" "arith_media")])
1402 (define_insn "movdicc_true"
1403   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1404         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1405                              (const_int 0))
1406          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1407          (match_operand:DI 3 "arith_reg_operand" "0")))]
1408   "TARGET_SHMEDIA"
1409   "cmvne        %1, %N2, %0"
1410   [(set_attr "type" "arith_media")])
1412 (define_peephole2
1413   [(set (match_operand:DI 0 "arith_reg_dest" "")
1414         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1415                            [(match_operand:DI 1 "arith_reg_operand" "")
1416                             (const_int 0)])
1417          (match_operand:DI 2 "arith_reg_dest" "")
1418          (match_dup 0)))
1419    (set (match_dup 2) (match_dup 0))]
1420   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1421   [(set (match_dup 2)
1422         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1424   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1425                                 VOIDmode, operands[1], CONST0_RTX (DImode));
1428 (define_peephole2
1429   [(set (match_operand:DI 0 "general_movdst_operand" "")
1430         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1431    (set (match_operand:DI 2 "arith_reg_dest" "")
1432         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1433                            [(match_operand:DI 3 "arith_reg_operand" "")
1434                             (const_int 0)])
1435          (match_dup 0)
1436          (match_dup 2)))]
1437   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1438   [(set (match_dup 2)
1439         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1440   "")
1442 (define_expand "movdicc"
1443   [(set (match_operand:DI 0 "register_operand" "")
1444         (if_then_else:DI (match_operand 1 "comparison_operator" "")
1445                          (match_operand:DI 2 "register_operand" "")
1446                          (match_operand:DI 3 "register_operand" "")))]
1447   "TARGET_SHMEDIA"
1449   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1450       && GET_MODE (XEXP (operands[1], 0)) == DImode
1451       && XEXP (operands[1], 1) == const0_rtx)
1452     ;
1453   else
1454     {
1455       if (!can_create_pseudo_p ())
1456         FAIL;
1458       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1459                                               GET_CODE (operands[1]),
1460                                               XEXP (operands[1], 0),
1461                                               XEXP (operands[1], 1));
1462       if (!operands[1])
1463         FAIL;
1464     }
1467 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1468 ;; SImode to DImode.
1469 (define_insn "movsicc_false"
1470   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1471         (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1472                           (const_int 0))
1473          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1474          (match_operand:SI 3 "arith_reg_operand" "0")))]
1475   "TARGET_SHMEDIA"
1476   "cmveq        %1, %N2, %0"
1477   [(set_attr "type" "arith_media")])
1479 (define_insn "movsicc_true"
1480   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1481         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1482                           (const_int 0))
1483          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1484          (match_operand:SI 3 "arith_reg_operand" "0")))]
1485   "TARGET_SHMEDIA"
1486   "cmvne        %1, %N2, %0"
1487   [(set_attr "type" "arith_media")])
1489 (define_peephole2
1490   [(set (match_operand:SI 0 "arith_reg_dest" "")
1491         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1492                            [(match_operand:SI 1 "arith_reg_operand" "")
1493                             (const_int 0)])
1494          (match_operand:SI 2 "arith_reg_dest" "")
1495          (match_dup 0)))
1496    (set (match_dup 2) (match_dup 0))]
1497   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1498   [(set (match_dup 2)
1499         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1501   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1502                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1505 (define_peephole2
1506   [(set (match_operand:SI 0 "general_movdst_operand" "")
1507         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1508    (set (match_operand:SI 2 "arith_reg_dest" "")
1509         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1510                            [(match_operand:SI 3 "arith_reg_operand" "")
1511                             (const_int 0)])
1512          (match_dup 0)
1513          (match_dup 2)))]
1514   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1515    && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1516   [(set (match_dup 2)
1517         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1519   replace_rtx (operands[4], operands[0], operands[1]);
1522 ;; The register allocator is rather clumsy in handling multi-way conditional
1523 ;; moves, so allow the combiner to make them, and we split them up after
1524 ;; reload.  */
1525 (define_insn_and_split "*movsicc_umin"
1526   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1527         (umin:SI (if_then_else:SI
1528                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1529                        (const_int 0))
1530                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1531                    (match_operand:SI 3 "register_operand" "0"))
1532                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1533    (clobber (match_scratch:SI 5 "=&r"))]
1534   "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1535   "#"
1536   "TARGET_SHMEDIA && reload_completed"
1537   [(pc)]
1539   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1540                                 operands[3]));
1541   emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1542   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1543                                 operands[0]));
1544   DONE;
1547 (define_insn "*movsicc_t_false"
1548   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1549         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1550                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1551                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1552   "TARGET_PRETEND_CMOVE
1553    && (arith_reg_operand (operands[1], SImode)
1554        || (immediate_operand (operands[1], SImode)
1555            && satisfies_constraint_I08 (operands[1])))"
1557   return       "bt      0f"     "\n"
1558          "      mov     %1,%0"  "\n"
1559          "0:";
1561   [(set_attr "type" "mt_group,arith") ;; poor approximation
1562    (set_attr "length" "4")])
1564 (define_insn "*movsicc_t_true"
1565   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1566         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1567                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1568                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1569   "TARGET_PRETEND_CMOVE
1570    && (arith_reg_operand (operands[1], SImode)
1571        || (immediate_operand (operands[1], SImode)
1572            && satisfies_constraint_I08 (operands[1])))"
1574   return       "bf      0f"     "\n"
1575          "      mov     %1,%0"  "\n"
1576          "0:";
1578   [(set_attr "type" "mt_group,arith") ;; poor approximation
1579    (set_attr "length" "4")])
1581 (define_expand "movsicc"
1582   [(set (match_operand:SI 0 "arith_reg_dest" "")
1583         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1584                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1585                          (match_operand:SI 3 "arith_reg_operand" "")))]
1586   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1588   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1589       && GET_MODE (XEXP (operands[1], 0)) == SImode
1590       && (TARGET_SHMEDIA
1591           || (REG_P (XEXP (operands[1], 0))
1592               && REGNO (XEXP (operands[1], 0)) == T_REG))
1593       && XEXP (operands[1], 1) == const0_rtx)
1594     ;
1596   else if (TARGET_PRETEND_CMOVE)
1597     {
1598       enum rtx_code code = GET_CODE (operands[1]);
1599       enum rtx_code new_code = code;
1600       rtx op0 = XEXP (operands[1], 0);
1601       rtx op1 = XEXP (operands[1], 1);
1603       if (! currently_expanding_to_rtl)
1604         FAIL;
1605       switch (code)
1606         {
1607         case LT: case LE: case LEU: case LTU:
1608           if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1609             break;
1610         case NE:
1611           new_code = reverse_condition (code);
1612           break;
1613         case EQ: case GT: case GE: case GEU: case GTU:
1614           break;
1615         default:
1616           FAIL;
1617         }
1618       sh_emit_scc_to_t (new_code, op0, op1);
1619       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1620                                     gen_rtx_REG (SImode, T_REG), const0_rtx);
1621     }
1622   else
1623     {
1624       if (!can_create_pseudo_p ())
1625         FAIL;
1627       operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1628                                               GET_CODE (operands[1]),
1629                                               XEXP (operands[1], 0),
1630                                               XEXP (operands[1], 1));
1631       if (!operands[1])
1632         FAIL;
1633     }
1636 (define_expand "movqicc"
1637   [(set (match_operand:QI 0 "register_operand" "")
1638         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1639                          (match_operand:QI 2 "register_operand" "")
1640                          (match_operand:QI 3 "register_operand" "")))]
1641   "TARGET_SHMEDIA"
1643   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1644   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1645   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1646   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1647   DONE;
1650 ;; -------------------------------------------------------------------------
1651 ;; Addition instructions
1652 ;; -------------------------------------------------------------------------
1654 (define_expand "adddi3"
1655   [(set (match_operand:DI 0 "arith_reg_operand")
1656         (plus:DI (match_operand:DI 1 "arith_reg_operand")
1657                  (match_operand:DI 2 "arith_operand")))]
1658   ""
1660   if (TARGET_SH1)
1661     {
1662       operands[2] = force_reg (DImode, operands[2]);
1663       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1664       DONE;
1665     }
1668 (define_insn "*adddi3_media"
1669   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1670         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1671                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1672   "TARGET_SHMEDIA"
1673   "@
1674         add     %1, %2, %0
1675         addi    %1, %2, %0"
1676   [(set_attr "type" "arith_media")])
1678 (define_insn "*adddisi3_media"
1679   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1680         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1681                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1682   "TARGET_SHMEDIA"
1683   "@
1684         add.l   %1, %2, %0
1685         addi.l  %1, %2, %0"
1686   [(set_attr "type" "arith_media")
1687    (set_attr "highpart" "ignore")])
1689 (define_insn "adddi3z_media"
1690   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1691         (zero_extend:DI
1692          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1693                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1694   "TARGET_SHMEDIA"
1695   "addz.l       %1, %N2, %0"
1696   [(set_attr "type" "arith_media")
1697    (set_attr "highpart" "ignore")])
1699 (define_insn_and_split "adddi3_compact"
1700   [(set (match_operand:DI 0 "arith_reg_dest")
1701         (plus:DI (match_operand:DI 1 "arith_reg_operand")
1702                  (match_operand:DI 2 "arith_reg_operand")))
1703    (clobber (reg:SI T_REG))]
1704   "TARGET_SH1"
1705   "#"
1706   "&& can_create_pseudo_p ()"
1707   [(const_int 0)]
1709   emit_insn (gen_clrt ());
1710   emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1711                        gen_lowpart (SImode, operands[1]),
1712                        gen_lowpart (SImode, operands[2])));
1713   emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1714                        gen_highpart (SImode, operands[1]),
1715                        gen_highpart (SImode, operands[2])));
1716   DONE;
1719 (define_insn "addc"
1720   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1721         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1722                           (match_operand:SI 2 "arith_reg_operand" "r"))
1723                  (reg:SI T_REG)))
1724    (set (reg:SI T_REG)
1725         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1726   "TARGET_SH1"
1727   "addc %2,%0"
1728   [(set_attr "type" "arith")])
1730 ;; A simplified version of the addc insn, where the exact value of the
1731 ;; T bit doesn't matter.  This is easier for combine to pick up.
1732 ;; We allow a reg or 0 for one of the operands in order to be able to
1733 ;; do 'reg + T' sequences.  Reload will load the constant 0 into the reg
1734 ;; as needed.
1735 (define_insn "*addc"
1736   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1737         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1738                           (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1739                  (match_operand:SI 3 "t_reg_operand" "")))
1740    (clobber (reg:SI T_REG))]
1741   "TARGET_SH1"
1742   "addc %2,%0"
1743   [(set_attr "type" "arith")])
1745 ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1746 ;; better, if the sett insn can be done early.
1747 (define_insn_and_split "*addc_r_r_1"
1748   [(set (match_operand:SI 0 "arith_reg_dest" "")
1749         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1750                           (match_operand:SI 2 "arith_reg_operand" ""))
1751                  (const_int 1)))
1752    (clobber (reg:SI T_REG))]
1753   "TARGET_SH1"
1754   "#"
1755   "&& 1"
1756   [(set (reg:SI T_REG) (const_int 1))
1757    (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1758                                           (reg:SI T_REG)))
1759               (clobber (reg:SI T_REG))])])
1761 ;; Left shifts by one are usually done with an add insn to avoid T_REG
1762 ;; clobbers.  Thus addc can also be used to do something like '(x << 1) + 1'.
1763 (define_insn_and_split "*addc_2r_1"
1764   [(set (match_operand:SI 0 "arith_reg_dest")
1765         (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1766                           (const_int 2))
1767                  (const_int 1)))
1768    (clobber (reg:SI T_REG))]
1769   "TARGET_SH1"
1770   "#"
1771   "&& 1"
1772   [(set (reg:SI T_REG) (const_int 1))
1773    (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1774                                           (reg:SI T_REG)))
1775               (clobber (reg:SI T_REG))])])
1777 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1778 ;; matched.  Split this up into a simple sub add sequence, as this will save
1779 ;; us one sett insn.
1780 (define_insn_and_split "*minus_plus_one"
1781   [(set (match_operand:SI 0 "arith_reg_dest" "")
1782         (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1783                            (match_operand:SI 2 "arith_reg_operand" ""))
1784                  (const_int 1)))]
1785   "TARGET_SH1"
1786   "#"
1787   "&& 1"
1788   [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1789    (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1791 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1792 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1793 ;; operation, as opposed to sequences such as
1794 ;;      movt    r2
1795 ;;      add     r2,r3
1797 ;; Even if the constant is not CSE-ed, a sequence such as
1798 ;;      mov     #0,r2
1799 ;;      addc    r2,r3
1800 ;; can be scheduled much better since the load of the constant can be
1801 ;; done earlier, before any comparison insns that store the result in
1802 ;; the T bit.
1803 (define_insn_and_split "*addc_r_1"
1804   [(set (match_operand:SI 0 "arith_reg_dest" "")
1805         (plus:SI (match_operand:SI 1 "t_reg_operand" "")
1806                  (match_operand:SI 2 "arith_reg_operand" "")))
1807    (clobber (reg:SI T_REG))]
1808   "TARGET_SH1"
1809   "#"
1810   "&& 1"
1811   [(parallel [(set (match_dup 0)
1812                    (plus:SI (plus:SI (match_dup 2) (const_int 0))
1813                             (match_dup 1)))
1814               (clobber (reg:SI T_REG))])])
1816 ;; Use shlr-addc to do 'reg + (reg & 1)'.
1817 (define_insn_and_split "*addc_r_lsb"
1818   [(set (match_operand:SI 0 "arith_reg_dest")
1819         (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1820                          (const_int 1))
1821                  (match_operand:SI 2 "arith_reg_operand")))
1822    (clobber (reg:SI T_REG))]
1823   "TARGET_SH1"
1824   "#"
1825   "&& can_create_pseudo_p ()"
1826   [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1827               (clobber (reg:SI T_REG))])]
1829   emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1832 ;; Use shlr-addc to do 'reg + reg + (reg & 1)'.
1833 (define_insn_and_split "*addc_r_r_lsb"
1834   [(set (match_operand:SI 0 "arith_reg_dest")
1835         (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1836                                   (const_int 1))
1837                           (match_operand:SI 2 "arith_reg_operand"))
1838                  (match_operand:SI 3 "arith_reg_operand")))
1839    (clobber (reg:SI T_REG))]
1840   "TARGET_SH1"
1841   "#"
1842   "&& can_create_pseudo_p ()"
1843   [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1844                                           (reg:SI T_REG)))
1845               (clobber (reg:SI T_REG))])]
1847   emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
1850 ;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'.
1851 (define_insn_and_split "*addc_r_lsb_r"
1852   [(set (match_operand:SI 0 "arith_reg_dest")
1853         (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1854                          (const_int 1))
1855                  (plus:SI (match_operand:SI 2 "arith_reg_operand")
1856                           (match_operand:SI 3 "arith_reg_operand"))))
1857    (clobber (reg:SI T_REG))]
1858   "TARGET_SH1"
1859   "#"
1860   "&& can_create_pseudo_p ()"
1861   [(parallel [(set (match_dup 0)
1862                    (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1863                                      (match_dup 2))
1864                             (match_dup 3)))
1865               (clobber (reg:SI T_REG))])])
1867 ;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'.
1868 (define_insn_and_split "*addc_2r_lsb"
1869   [(set (match_operand:SI 0 "arith_reg_dest")
1870         (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
1871                          (const_int 1))
1872                  (mult:SI (match_operand:SI 2 "arith_reg_operand")
1873                           (const_int 2))))
1874    (clobber (reg:SI T_REG))]
1875   "TARGET_SH1"
1876   "#"
1877   "&& can_create_pseudo_p ()"
1878   [(parallel [(set (match_dup 0)
1879                    (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
1880                                      (match_dup 2))
1881                             (match_dup 2)))
1882               (clobber (reg:SI T_REG))])])
1884 ;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'.
1885 (define_insn_and_split "*addc_r_msb"
1886   [(set (match_operand:SI 0 "arith_reg_dest")
1887         (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1888                               (const_int 31))
1889                  (match_operand:SI 2 "arith_reg_operand")))
1890    (clobber (reg:SI T_REG))]
1891   "TARGET_SH1"
1892   "#"
1893   "&& can_create_pseudo_p ()"
1894   [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
1895               (clobber (reg:SI T_REG))])]
1897   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
1900 ;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'.
1901 (define_insn_and_split "*addc_r_r_msb"
1902   [(set (match_operand:SI 0 "arith_reg_dest")
1903         (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1904                                        (const_int 31))
1905                           (match_operand:SI 2 "arith_reg_operand"))
1906                  (match_operand:SI 3 "arith_reg_operand")))
1907    (clobber (reg:SI T_REG))]
1908   "TARGET_SH1"
1909   "#"
1910   "&& can_create_pseudo_p ()"
1911   [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1912                                           (reg:SI T_REG)))
1913               (clobber (reg:SI T_REG))])]
1915   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
1918 ;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)'
1919 ;; into 'reg + reg + (reg & 1)'.
1920 (define_insn_and_split "*addc_2r_msb"
1921   [(set (match_operand:SI 0 "arith_reg_dest")
1922         (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1923                           (const_int 2))
1924                  (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
1925                               (const_int 31))))
1926    (clobber (reg:SI T_REG))]
1927   "TARGET_SH1"
1928   "#"
1929   "&& can_create_pseudo_p ()"
1930   [(parallel [(set (match_dup 0)
1931                    (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31))
1932                                      (match_dup 1))
1933                             (match_dup 1)))
1934               (clobber (reg:SI T_REG))])])
1936 (define_expand "addsi3"
1937   [(set (match_operand:SI 0 "arith_reg_operand" "")
1938         (plus:SI (match_operand:SI 1 "arith_operand" "")
1939                  (match_operand:SI 2 "arith_operand" "")))]
1940   ""
1942   if (TARGET_SHMEDIA)
1943     operands[1] = force_reg (SImode, operands[1]);
1946 (define_insn "addsi3_media"
1947   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1948         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1949                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1950   "TARGET_SHMEDIA"
1951   "@
1952         add.l   %1, %2, %0
1953         addi.l  %1, %2, %0"
1954   [(set_attr "type" "arith_media")
1955    (set_attr "highpart" "ignore")])
1957 (define_insn "addsidi3_media"
1958   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1959         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1960                                   "%r,r")
1961                                  (match_operand:SI 2 "arith_operand"
1962                                   "r,I10"))))]
1963   "TARGET_SHMEDIA"
1964   "@
1965         add.l   %1, %2, %0
1966         addi.l  %1, %2, %0"
1967   [(set_attr "type" "arith_media")
1968    (set_attr "highpart" "ignore")])
1970 (define_insn "*addsi3_compact"
1971   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1972         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1973                  (match_operand:SI 2 "arith_operand" "rI08")))]
1974   "TARGET_SH1"
1975   "add  %2,%0"
1976   [(set_attr "type" "arith")])
1978 ;; -------------------------------------------------------------------------
1979 ;; Subtraction instructions
1980 ;; -------------------------------------------------------------------------
1982 (define_expand "subdi3"
1983   [(set (match_operand:DI 0 "arith_reg_operand" "")
1984         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1985                   (match_operand:DI 2 "arith_reg_operand" "")))]
1986   ""
1988   if (TARGET_SH1)
1989     {
1990       operands[1] = force_reg (DImode, operands[1]);
1991       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1992       DONE;
1993     }
1996 (define_insn "*subdi3_media"
1997   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1998         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1999                   (match_operand:DI 2 "arith_reg_operand" "r")))]
2000   "TARGET_SHMEDIA"
2001   "sub  %N1, %2, %0"
2002   [(set_attr "type" "arith_media")])
2003   
2004 (define_insn "subdisi3_media"
2005   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2006         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2007                   (match_operand:DI 2 "arith_reg_operand" "r")))]
2008   "TARGET_SHMEDIA"
2009   "sub.l        %N1, %2, %0"
2010   [(set_attr "type" "arith_media")
2011    (set_attr "highpart" "ignore")])
2013 (define_insn_and_split "subdi3_compact"
2014   [(set (match_operand:DI 0 "arith_reg_dest")
2015         (minus:DI (match_operand:DI 1 "arith_reg_operand")
2016                  (match_operand:DI 2 "arith_reg_operand")))
2017    (clobber (reg:SI T_REG))]
2018   "TARGET_SH1"
2019   "#"
2020   "&& can_create_pseudo_p ()"
2021   [(const_int 0)]
2023   emit_insn (gen_clrt ());
2024   emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2025                        gen_lowpart (SImode, operands[1]),
2026                        gen_lowpart (SImode, operands[2])));
2027   emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2028                        gen_highpart (SImode, operands[1]),
2029                        gen_highpart (SImode, operands[2])));
2030   DONE;
2033 (define_insn "subc"
2034   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2035         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2036                             (match_operand:SI 2 "arith_reg_operand" "r"))
2037                   (reg:SI T_REG)))
2038    (set (reg:SI T_REG)
2039         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2040                           (reg:SI T_REG))
2041                 (match_dup 1)))]
2042   "TARGET_SH1"
2043   "subc %2,%0"
2044   [(set_attr "type" "arith")])
2046 ;; A simplified version of the subc insn, where the exact value of the
2047 ;; T bit doesn't matter.  This is easier for combine to pick up.
2048 ;; We allow a reg or 0 for one of the operands in order to be able to
2049 ;; do 'reg - T' sequences.  Reload will load the constant 0 into the reg
2050 ;; as needed.
2051 (define_insn "*subc"
2052   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2053         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2054                             (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
2055                   (match_operand:SI 3 "t_reg_operand" "")))
2056    (clobber (reg:SI T_REG))]
2057   "TARGET_SH1"
2058   "subc %2,%0"
2059   [(set_attr "type" "arith")])
2061 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2062 ;; better, if the sett insn can be done early.
2063 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2064 (define_insn_and_split "*subc"
2065   [(set (match_operand:SI 0 "arith_reg_dest" "")
2066         (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2067                  (match_operand:SI 2 "arith_reg_operand" "")))
2068    (clobber (reg:SI T_REG))]
2069   "TARGET_SH1"
2070   "#"
2071   "&& 1"
2072   [(set (reg:SI T_REG) (const_int 1))
2073    (parallel [(set (match_dup 0)
2074                    (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2075                              (reg:SI T_REG)))
2076               (clobber (reg:SI T_REG))])])
2078 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2079 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2080 ;; operation, as opposed to sequences such as
2081 ;;      movt    r2
2082 ;;      sub     r2,r3
2084 ;; Even if the constant is not CSE-ed, a sequence such as
2085 ;;      mov     #0,r2
2086 ;;      subc    r2,r3
2087 ;; can be scheduled much better since the load of the constant can be
2088 ;; done earlier, before any comparison insns that store the result in
2089 ;; the T bit.
2090 (define_insn_and_split "*subc"
2091   [(set (match_operand:SI 0 "arith_reg_dest" "")
2092         (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2093                   (match_operand:SI 2 "t_reg_operand" "")))
2094    (clobber (reg:SI T_REG))]
2095   "TARGET_SH1"
2096   "#"
2097   "&& 1"
2098   [(parallel [(set (match_dup 0)
2099                    (minus:SI (minus:SI (match_dup 1) (const_int 0))
2100                              (match_dup 2)))
2101               (clobber (reg:SI T_REG))])])
2103 (define_insn "*subsi3_internal"
2104   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2105         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2106                   (match_operand:SI 2 "arith_reg_operand" "r")))]
2107   "TARGET_SH1"
2108   "sub  %2,%0"
2109   [(set_attr "type" "arith")])
2111 (define_insn_and_split "*subsi3_media"
2112   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2113         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2114                   (match_operand:SI 2 "extend_reg_operand" "r")))]
2115   "TARGET_SHMEDIA
2116    && (operands[1] != constm1_rtx
2117        || (GET_CODE (operands[2]) != TRUNCATE
2118            && GET_CODE (operands[2]) != SUBREG))"
2119   "sub.l        %N1, %2, %0"
2120   "operands[1] == constm1_rtx"
2121   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2122   ""
2123   [(set_attr "type" "arith_media")
2124    (set_attr "highpart" "ignore")])
2126 (define_split
2127   [(set (match_operand:SI 0 "arith_reg_dest" "")
2128         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2129                                                        "general_extend_operand"
2130                                                        "") 0)) 0)))]
2131   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2132   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2133    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2134   "")
2136 (define_split
2137   [(set (match_operand:SI 0 "arith_reg_dest" "")
2138         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2139                                                        "general_extend_operand"
2140                                                        "") 0)) 3)))]
2141   "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2142   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2143    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2144   "")
2146 ;; Convert
2147 ;;      constant - reg
2148 ;; to
2149 ;;      neg reg
2150 ;;      add reg, #const
2151 ;; since this will sometimes save one instruction.
2152 ;; Otherwise we might get a sequence like
2153 ;;      mov #const, rY
2154 ;;      sub rY, rX
2155 ;;      mov rX, rY
2156 ;; if the source and dest regs are the same.
2157 (define_expand "subsi3"
2158   [(set (match_operand:SI 0 "arith_reg_operand" "")
2159         (minus:SI (match_operand:SI 1 "arith_operand" "")
2160                   (match_operand:SI 2 "arith_reg_operand" "")))]
2161   ""
2163   if (TARGET_SH1 && CONST_INT_P (operands[1]))
2164     {
2165       emit_insn (gen_negsi2 (operands[0], operands[2]));
2166       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2167       DONE;
2168     }
2169   if (TARGET_SHMEDIA)
2170     {
2171       if (!can_create_pseudo_p ()
2172           && ! arith_reg_or_0_operand (operands[1], SImode))
2173         FAIL;
2174       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2175         operands[1] = force_reg (SImode, operands[1]);
2176     }
2179 ;; -------------------------------------------------------------------------
2180 ;; Division instructions
2181 ;; -------------------------------------------------------------------------
2183 ;; We take advantage of the library routines which don't clobber as many
2184 ;; registers as a normal function call would.
2186 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2187 ;; also has an effect on the register that holds the address of the sfunc.
2188 ;; To make this work, we have an extra dummy insn that shows the use
2189 ;; of this register for reorg.
2191 (define_insn "use_sfunc_addr"
2192   [(set (reg:SI PR_REG)
2193         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2194   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2195   ""
2196   [(set_attr "length" "0")])
2198 (define_insn "udivsi3_sh2a"
2199   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2200         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2201                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2202   "TARGET_SH2A"
2203   "divu %2,%1"
2204   [(set_attr "type" "arith")
2205    (set_attr "in_delay_slot" "no")])
2207 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2208 ;; hard register 0.  If we used hard register 0, then the next instruction
2209 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
2210 ;; gets allocated to a stack slot that needs its address reloaded, then
2211 ;; there is nothing to prevent reload from using r0 to reload the address.
2212 ;; This reload would clobber the value in r0 we are trying to store.
2213 ;; If we let reload allocate r0, then this problem can never happen.
2214 (define_insn "udivsi3_i1"
2215   [(set (match_operand:SI 0 "register_operand" "=z")
2216         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2217    (clobber (reg:SI T_REG))
2218    (clobber (reg:SI PR_REG))
2219    (clobber (reg:SI R1_REG))
2220    (clobber (reg:SI R4_REG))
2221    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2222   "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2223   "jsr  @%1%#"
2224   [(set_attr "type" "sfunc")
2225    (set_attr "needs_delay_slot" "yes")])
2227 ; Since shmedia-nofpu code could be linked against shcompact code, and
2228 ; the udivsi3 libcall has the same name, we must consider all registers
2229 ; clobbered that are in the union of the registers clobbered by the
2230 ; shmedia and the shcompact implementation.  Note, if the shcompact
2231 ; implementation actually used shcompact code, we'd need to clobber
2232 ; also r23 and fr23.
2233 (define_insn "udivsi3_i1_media"
2234   [(set (match_operand:SI 0 "register_operand" "=z")
2235         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2236    (clobber (reg:SI T_MEDIA_REG))
2237    (clobber (reg:SI PR_MEDIA_REG))
2238    (clobber (reg:SI R20_REG))
2239    (clobber (reg:SI R21_REG))
2240    (clobber (reg:SI R22_REG))
2241    (clobber (reg:DI TR0_REG))
2242    (clobber (reg:DI TR1_REG))
2243    (clobber (reg:DI TR2_REG))
2244    (use (match_operand 1 "target_reg_operand" "b"))]
2245   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2246   "blink        %1, r18"
2247   [(set_attr "type" "sfunc")
2248    (set_attr "needs_delay_slot" "yes")])
2250 (define_expand "udivsi3_i4_media"
2251   [(set (match_dup 3)
2252         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2253    (set (match_dup 4)
2254         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2255    (set (match_dup 5) (float:DF (match_dup 3)))
2256    (set (match_dup 6) (float:DF (match_dup 4)))
2257    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2258    (set (match_dup 8) (fix:DI (match_dup 7)))
2259    (set (match_operand:SI 0 "register_operand" "")
2260         (truncate:SI (match_dup 8)))]
2261   "TARGET_SHMEDIA_FPU"
2263   operands[3] = gen_reg_rtx (DImode);
2264   operands[4] = gen_reg_rtx (DImode);
2265   operands[5] = gen_reg_rtx (DFmode);
2266   operands[6] = gen_reg_rtx (DFmode);
2267   operands[7] = gen_reg_rtx (DFmode);
2268   operands[8] = gen_reg_rtx (DImode);
2271 (define_insn "udivsi3_i4"
2272   [(set (match_operand:SI 0 "register_operand" "=y")
2273         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2274    (clobber (reg:SI T_REG))
2275    (clobber (reg:SI PR_REG))
2276    (clobber (reg:DF DR0_REG))
2277    (clobber (reg:DF DR2_REG))
2278    (clobber (reg:DF DR4_REG))
2279    (clobber (reg:SI R0_REG))
2280    (clobber (reg:SI R1_REG))
2281    (clobber (reg:SI R4_REG))
2282    (clobber (reg:SI R5_REG))
2283    (use (reg:PSI FPSCR_REG))
2284    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2285   "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2286   "jsr  @%1%#"
2287   [(set_attr "type" "sfunc")
2288    (set_attr "fp_mode" "double")
2289    (set_attr "needs_delay_slot" "yes")])
2291 (define_insn "udivsi3_i4_single"
2292   [(set (match_operand:SI 0 "register_operand" "=y")
2293         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2294    (clobber (reg:SI T_REG))
2295    (clobber (reg:SI PR_REG))
2296    (clobber (reg:DF DR0_REG))
2297    (clobber (reg:DF DR2_REG))
2298    (clobber (reg:DF DR4_REG))
2299    (clobber (reg:SI R0_REG))
2300    (clobber (reg:SI R1_REG))
2301    (clobber (reg:SI R4_REG))
2302    (clobber (reg:SI R5_REG))
2303    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2304   "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2305    && TARGET_FPU_SINGLE"
2306   "jsr  @%1%#"
2307   [(set_attr "type" "sfunc")
2308    (set_attr "needs_delay_slot" "yes")])
2310 (define_insn "udivsi3_i4_int"
2311   [(set (match_operand:SI 0 "register_operand" "=z")
2312         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2313    (clobber (reg:SI T_REG))
2314    (clobber (reg:SI R1_REG))
2315    (clobber (reg:SI PR_REG))
2316    (clobber (reg:SI MACH_REG))
2317    (clobber (reg:SI MACL_REG))
2318    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2319   "TARGET_SH1"
2320   "jsr  @%1%#"
2321   [(set_attr "type" "sfunc")
2322    (set_attr "needs_delay_slot" "yes")])
2325 (define_expand "udivsi3"
2326   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2327    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2328    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2329    (parallel [(set (match_operand:SI 0 "register_operand" "")
2330                    (udiv:SI (reg:SI R4_REG)
2331                             (reg:SI R5_REG)))
2332               (clobber (reg:SI T_REG))
2333               (clobber (reg:SI PR_REG))
2334               (clobber (reg:SI R4_REG))
2335               (use (match_dup 3))])]
2336   ""
2338   rtx last;
2340   operands[3] = gen_reg_rtx (Pmode);
2341   /* Emit the move of the address to a pseudo outside of the libcall.  */
2342   if (TARGET_DIVIDE_CALL_TABLE)
2343     {
2344       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2345          that causes problems when the divide code is supposed to come from a
2346          separate library.  Division by zero is undefined, so dividing 1 can be
2347          implemented by comparing with the divisor.  */
2348       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2349         {
2350           rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2351           emit_insn (gen_cstoresi4 (operands[0], test,
2352                                     operands[1], operands[2]));
2353           DONE;
2354         }
2355       else if (operands[2] == const0_rtx)
2356         {
2357           emit_move_insn (operands[0], operands[2]);
2358           DONE;
2359         }
2360       function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2361       last = gen_udivsi3_i4_int (operands[0], operands[3]);
2362     }
2363   else if (TARGET_DIVIDE_CALL_FP)
2364     {
2365       function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2366       if (TARGET_FPU_SINGLE)
2367         last = gen_udivsi3_i4_single (operands[0], operands[3]);
2368       else
2369         last = gen_udivsi3_i4 (operands[0], operands[3]);
2370     }
2371   else if (TARGET_SHMEDIA_FPU)
2372     {
2373       operands[1] = force_reg (SImode, operands[1]);
2374       operands[2] = force_reg (SImode, operands[2]);
2375       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2376       DONE;
2377     }
2378   else if (TARGET_SH2A)
2379     {
2380       operands[1] = force_reg (SImode, operands[1]);
2381       operands[2] = force_reg (SImode, operands[2]);
2382       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2383       DONE;
2384     }
2385   else if (TARGET_SH5)
2386     {
2387       function_symbol (operands[3],
2388                        TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2389                        SFUNC_STATIC);
2391       if (TARGET_SHMEDIA)
2392         last = gen_udivsi3_i1_media (operands[0], operands[3]);
2393       else if (TARGET_FPU_ANY)
2394         last = gen_udivsi3_i4_single (operands[0], operands[3]);
2395       else
2396         last = gen_udivsi3_i1 (operands[0], operands[3]);
2397     }
2398   else
2399     {
2400       function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2401       last = gen_udivsi3_i1 (operands[0], operands[3]);
2402     }
2403   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2404   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2405   emit_insn (last);
2406   DONE;
2409 (define_insn "divsi3_sh2a"
2410   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2411         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2412                 (match_operand:SI 2 "arith_reg_operand" "z")))]
2413   "TARGET_SH2A"
2414   "divs %2,%1"
2415   [(set_attr "type" "arith")
2416    (set_attr "in_delay_slot" "no")])
2418 (define_insn "divsi3_i1"
2419   [(set (match_operand:SI 0 "register_operand" "=z")
2420         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2421    (clobber (reg:SI T_REG))
2422    (clobber (reg:SI PR_REG))
2423    (clobber (reg:SI R1_REG))
2424    (clobber (reg:SI R2_REG))
2425    (clobber (reg:SI R3_REG))
2426    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2427   "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2428   "jsr  @%1%#"
2429   [(set_attr "type" "sfunc")
2430    (set_attr "needs_delay_slot" "yes")])
2432 (define_insn "divsi3_i1_media"
2433   [(set (match_operand:SI 0 "register_operand" "=z")
2434         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2435    (clobber (reg:SI T_MEDIA_REG))
2436    (clobber (reg:SI PR_MEDIA_REG))
2437    (clobber (reg:SI R1_REG))
2438    (clobber (reg:SI R20_REG))
2439    (clobber (reg:SI R21_REG))
2440    (clobber (reg:SI TR0_REG))
2441    (use (match_operand 1 "target_reg_operand" "b"))]
2442   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2443   "blink        %1, r18"
2444   [(set_attr "type" "sfunc")])
2446 (define_insn "divsi3_media_2"
2447   [(set (match_operand:SI 0 "register_operand" "=z")
2448         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2449    (clobber (reg:SI T_MEDIA_REG))
2450    (clobber (reg:SI PR_MEDIA_REG))
2451    (clobber (reg:SI R1_REG))
2452    (clobber (reg:SI R21_REG))
2453    (clobber (reg:SI TR0_REG))
2454    (use (reg:SI R20_REG))
2455    (use (match_operand 1 "target_reg_operand" "b"))]
2456   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2457   "blink        %1, r18"
2458   [(set_attr "type" "sfunc")])
2460 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2461 ;; hard reg clobbers and data dependencies that we need when we want
2462 ;; to rematerialize the division into a call.
2463 (define_insn_and_split "divsi_inv_call"
2464   [(set (match_operand:SI 0 "register_operand" "=r")
2465         (div:SI (match_operand:SI 1 "register_operand" "r")
2466                 (match_operand:SI 2 "register_operand" "r")))
2467    (clobber (reg:SI R4_REG))
2468    (clobber (reg:SI R5_REG))
2469    (clobber (reg:SI T_MEDIA_REG))
2470    (clobber (reg:SI PR_MEDIA_REG))
2471    (clobber (reg:SI R1_REG))
2472    (clobber (reg:SI R21_REG))
2473    (clobber (reg:SI TR0_REG))
2474    (clobber (reg:SI R20_REG))
2475    (use (match_operand:SI 3 "register_operand" "r"))]
2476   "TARGET_SHMEDIA"
2477   "#"
2478   "&& (reload_in_progress || reload_completed)"
2479   [(set (match_dup 0) (match_dup 3))]
2480   ""
2481   [(set_attr "highpart" "must_split")])
2483 ;; This is the combiner pattern for -mdiv=inv:call .
2484 (define_insn_and_split "*divsi_inv_call_combine"
2485   [(set (match_operand:SI 0 "register_operand" "=z")
2486         (div:SI (match_operand:SI 1 "register_operand" "r")
2487                 (match_operand:SI 2 "register_operand" "r")))
2488    (clobber (reg:SI R4_REG))
2489    (clobber (reg:SI R5_REG))
2490    (clobber (reg:SI T_MEDIA_REG))
2491    (clobber (reg:SI PR_MEDIA_REG))
2492    (clobber (reg:SI R1_REG))
2493    (clobber (reg:SI R21_REG))
2494    (clobber (reg:SI TR0_REG))
2495    (clobber (reg:SI R20_REG))
2496    (use (unspec:SI [(match_dup 1)
2497                     (match_operand:SI 3 "" "")
2498                     (unspec:SI [(match_operand:SI 4 "" "")
2499                                 (match_dup 3)
2500                                 (match_operand:DI 5 "" "")]
2501                      UNSPEC_DIV_INV_M2)
2502                     (match_operand:DI 6 "" "")
2503                     (const_int 0)
2504                     (const_int 0)]
2505          UNSPEC_DIV_INV_M3))]
2506   "TARGET_SHMEDIA"
2507   "#"
2508   "&& (reload_in_progress || reload_completed)"
2509   [(pc)]
2511   const char *name = sh_divsi3_libfunc;
2512   enum sh_function_kind kind = SFUNC_GOT;
2513   rtx sym;
2515   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2516   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2517   while (TARGET_DIVIDE_INV_CALL2)
2518     {
2519       rtx x = operands[3];
2521       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2522         break;
2523       x = XVECEXP (x, 0, 0);
2524       name = "__sdivsi3_2";
2525       kind = SFUNC_STATIC;
2526       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2527       break;
2528     }
2529   sym = function_symbol (NULL, name, kind);
2530   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2531   DONE;
2533   [(set_attr "highpart" "must_split")])
2535 (define_expand "divsi3_i4_media"
2536   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2537    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2538    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2539    (set (match_operand:SI 0 "register_operand" "=r")
2540         (fix:SI (match_dup 5)))]
2541   "TARGET_SHMEDIA_FPU"
2543   operands[3] = gen_reg_rtx (DFmode);
2544   operands[4] = gen_reg_rtx (DFmode);
2545   operands[5] = gen_reg_rtx (DFmode);
2548 (define_insn "divsi3_i4"
2549   [(set (match_operand:SI 0 "register_operand" "=y")
2550         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2551    (clobber (reg:SI PR_REG))
2552    (clobber (reg:DF DR0_REG))
2553    (clobber (reg:DF DR2_REG))
2554    (use (reg:PSI FPSCR_REG))
2555    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2556   "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2557   "jsr  @%1%#"
2558   [(set_attr "type" "sfunc")
2559    (set_attr "fp_mode" "double")
2560    (set_attr "needs_delay_slot" "yes")])
2562 (define_insn "divsi3_i4_single"
2563   [(set (match_operand:SI 0 "register_operand" "=y")
2564         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2565    (clobber (reg:SI PR_REG))
2566    (clobber (reg:DF DR0_REG))
2567    (clobber (reg:DF DR2_REG))
2568    (clobber (reg:SI R2_REG))
2569    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2570   "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2571    && TARGET_FPU_SINGLE"
2572   "jsr  @%1%#"
2573   [(set_attr "type" "sfunc")
2574    (set_attr "needs_delay_slot" "yes")])
2576 (define_insn "divsi3_i4_int"
2577   [(set (match_operand:SI 0 "register_operand" "=z")
2578         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2579    (clobber (reg:SI T_REG))
2580    (clobber (reg:SI PR_REG))
2581    (clobber (reg:SI R1_REG))
2582    (clobber (reg:SI MACH_REG))
2583    (clobber (reg:SI MACL_REG))
2584    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2585   "TARGET_SH1"
2586   "jsr  @%1%#"
2587   [(set_attr "type" "sfunc")
2588    (set_attr "needs_delay_slot" "yes")])
2590 (define_expand "divsi3"
2591   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2592    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2593    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2594    (parallel [(set (match_operand:SI 0 "register_operand" "")
2595                    (div:SI (reg:SI R4_REG)
2596                            (reg:SI R5_REG)))
2597               (clobber (reg:SI T_REG))
2598               (clobber (reg:SI PR_REG))
2599               (clobber (reg:SI R1_REG))
2600               (clobber (reg:SI R2_REG))
2601               (clobber (reg:SI R3_REG))
2602               (use (match_dup 3))])]
2603   ""
2605   rtx last;
2607   operands[3] = gen_reg_rtx (Pmode);
2608   /* Emit the move of the address to a pseudo outside of the libcall.  */
2609   if (TARGET_DIVIDE_CALL_TABLE)
2610     {
2611       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2612       last = gen_divsi3_i4_int (operands[0], operands[3]);
2613     }
2614   else if (TARGET_DIVIDE_CALL_FP)
2615     {
2616       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2617       if (TARGET_FPU_SINGLE)
2618         last = gen_divsi3_i4_single (operands[0], operands[3]);
2619       else
2620         last = gen_divsi3_i4 (operands[0], operands[3]);
2621     }
2622   else if (TARGET_SH2A)
2623     {
2624       operands[1] = force_reg (SImode, operands[1]);
2625       operands[2] = force_reg (SImode, operands[2]);
2626       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2627       DONE;
2628     }
2629   else if (TARGET_DIVIDE_INV)
2630     {
2631       rtx dividend = operands[1];
2632       rtx divisor = operands[2];
2633       rtx tab_base;
2634       rtx nsb_res = gen_reg_rtx (DImode);
2635       rtx norm64 = gen_reg_rtx (DImode);
2636       rtx tab_ix = gen_reg_rtx (DImode);
2637       rtx norm32 = gen_reg_rtx (SImode);
2638       rtx i92 = force_reg (DImode, GEN_INT (92));
2639       rtx scratch0a = gen_reg_rtx (DImode);
2640       rtx scratch0b = gen_reg_rtx (DImode);
2641       rtx inv0 = gen_reg_rtx (SImode);
2642       rtx scratch1a = gen_reg_rtx (DImode);
2643       rtx scratch1b = gen_reg_rtx (DImode);
2644       rtx shift = gen_reg_rtx (DImode);
2645       rtx i2p27, i43;
2646       rtx inv1 = gen_reg_rtx (SImode);
2647       rtx scratch2a = gen_reg_rtx (DImode);
2648       rtx scratch2b = gen_reg_rtx (SImode);
2649       rtx inv2 = gen_reg_rtx (SImode);
2650       rtx scratch3a = gen_reg_rtx (DImode);
2651       rtx scratch3b = gen_reg_rtx (DImode);
2652       rtx scratch3c = gen_reg_rtx (DImode);
2653       rtx scratch3d = gen_reg_rtx (SImode);
2654       rtx scratch3e = gen_reg_rtx (DImode);
2655       rtx result = gen_reg_rtx (SImode);
2657       if (! arith_reg_or_0_operand (dividend, SImode))
2658         dividend = force_reg (SImode, dividend);
2659       if (! arith_reg_operand (divisor, SImode))
2660         divisor = force_reg (SImode, divisor);
2661       if (flag_pic && Pmode != DImode)
2662         {
2663           tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2664           tab_base = gen_datalabel_ref (tab_base);
2665           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2666         }
2667       else
2668         {
2669           tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2670           tab_base = gen_datalabel_ref (tab_base);
2671           tab_base = force_reg (DImode, tab_base);
2672         }
2673       if (TARGET_DIVIDE_INV20U)
2674         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2675       else
2676         i2p27 = GEN_INT (0);
2677       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2678         i43 = force_reg (DImode, GEN_INT (43));
2679       else
2680         i43 = GEN_INT (0);
2681       emit_insn (gen_nsbdi (nsb_res,
2682                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2683       emit_insn (gen_ashldi3_media (norm64,
2684                                     gen_rtx_SUBREG (DImode, divisor, 0),
2685                                     nsb_res));
2686       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2687       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2688       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2689                                    inv0, scratch0a, scratch0b,
2690                                    scratch1a, scratch1b));
2691       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2692       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2693                                    scratch2a));
2694       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2695                                    i2p27, i43,
2696                                    scratch3a, scratch3b, scratch3c,
2697                                    scratch2a, scratch2b, scratch3d, scratch3e));
2698       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2699         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2700       else if (TARGET_DIVIDE_INV_FP)
2701         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2702                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2703                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2704                                      gen_reg_rtx (DFmode)));
2705       else
2706         emit_move_insn (operands[0], result);
2707       DONE;
2708     }
2709   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2710     {
2711       operands[1] = force_reg (SImode, operands[1]);
2712       operands[2] = force_reg (SImode, operands[2]);
2713       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2714       DONE;
2715     }
2716   else if (TARGET_SH5)
2717     {
2718       if (TARGET_DIVIDE_CALL2)
2719         {
2720           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2721           tab_base = gen_datalabel_ref (tab_base);
2722           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2723         }
2724       if (TARGET_FPU_ANY && TARGET_SH1)
2725         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2726       else if (TARGET_DIVIDE_CALL2)
2727         function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2728       else
2729         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2731       if (TARGET_SHMEDIA)
2732         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2733                 (operands[0], operands[3]));
2734       else if (TARGET_FPU_ANY)
2735         last = gen_divsi3_i4_single (operands[0], operands[3]);
2736       else
2737         last = gen_divsi3_i1 (operands[0], operands[3]);
2738     }
2739   else
2740     {
2741       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2742       last = gen_divsi3_i1 (operands[0], operands[3]);
2743     }
2744   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2745   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2746   emit_insn (last);
2747   DONE;
2750 ;; operands: scratch, tab_base, tab_ix
2751 ;; These are unspecs because we could generate an indexed addressing mode
2752 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2753 ;; confuse reload.  See PR27117.
2754 (define_insn "divsi_inv_qitable"
2755   [(set (match_operand:DI 0 "register_operand" "=r")
2756         (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2757                                     (match_operand:DI 2 "register_operand" "r")]
2758                          UNSPEC_DIV_INV_TABLE)))]
2759   "TARGET_SHMEDIA"
2760   "ldx.ub       %1, %2, %0"
2761   [(set_attr "type" "load_media")
2762    (set_attr "highpart" "user")])
2764 ;; operands: scratch, tab_base, tab_ix
2765 (define_insn "divsi_inv_hitable"
2766   [(set (match_operand:DI 0 "register_operand" "=r")
2767         (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2768                                     (match_operand:DI 2 "register_operand" "r")]
2769                          UNSPEC_DIV_INV_TABLE)))]
2770   "TARGET_SHMEDIA"
2771   "ldx.w        %1, %2, %0"
2772   [(set_attr "type" "load_media")
2773    (set_attr "highpart" "user")])
2775 ;; operands: inv0, tab_base, tab_ix, norm32
2776 ;; scratch equiv in sdivsi3_2: r19, r21
2777 (define_expand "divsi_inv_m0"
2778   [(set (match_operand:SI 0 "register_operand" "=r")
2779         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2780                     (match_operand:DI 2 "register_operand" "r")
2781                     (match_operand:SI 3 "register_operand" "r")]
2782          UNSPEC_DIV_INV_M0))
2783    (clobber (match_operand:DI 4 "register_operand" "=r"))
2784    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2785   "TARGET_SHMEDIA"
2788 tab_base: r20
2789 tab_ix: r21
2790 norm32: r25
2791  ldx.ub r20, r21, r19 // u0.8
2792  shlli r21, 1, r21
2793  muls.l r25, r19, r19 // s2.38
2794  ldx.w r20, r21, r21  // s2.14
2795  shari r19, 24, r19   // truncate to s2.14
2796  sub r21, r19, r19    // some 11 bit inverse in s1.14
2799   rtx inv0 = operands[0];
2800   rtx tab_base = operands[1];
2801   rtx tab_ix = operands[2];
2802   rtx norm32 = operands[3];
2803   rtx scratch0 = operands[4];
2804   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2805   rtx scratch1 = operands[5];
2807   emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2808   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2809   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2810   emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2811   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2812   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2813   DONE;
2816 ;; operands: inv1, tab_base, tab_ix, norm32
2817 (define_insn_and_split "divsi_inv_m1"
2818   [(set (match_operand:SI 0 "register_operand" "=r")
2819         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2820                     (match_operand:DI 2 "register_operand" "r")
2821                     (match_operand:SI 3 "register_operand" "r")]
2822          UNSPEC_DIV_INV_M1))
2823    (clobber (match_operand:SI 4 "register_operand" "=r"))
2824    (clobber (match_operand:DI 5 "register_operand" "=r"))
2825    (clobber (match_operand:DI 6 "register_operand" "=r"))
2826    (clobber (match_operand:DI 7 "register_operand" "=r"))
2827    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2828   "TARGET_SHMEDIA"
2829   "#"
2830   "&& !can_create_pseudo_p ()"
2831   [(pc)]
2833 /* inv0: r19
2834  muls.l r19, r19, r18 // u0.28
2835  muls.l r25, r18, r18 // s2.58
2836  shlli r19, 45, r0    // multiply by two and convert to s2.58
2837  sub r0, r18, r18
2838  shari r18, 28, r18   // some 18 bit inverse in s1.30
2841   rtx inv1 = operands[0];
2842   rtx tab_base = operands[1];
2843   rtx tab_ix = operands[2];
2844   rtx norm32 = operands[3];
2845   rtx inv0 = operands[4];
2846   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2847   rtx scratch0a = operands[5];
2848   rtx scratch0b = operands[6];
2849   rtx scratch0 = operands[7];
2850   rtx scratch1 = operands[8];
2851   rtx scratch1_si = gen_lowpart (SImode, scratch1);
2853   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2854                                scratch0a, scratch0b));
2855   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2856   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2857   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2858   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2859   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2860   DONE;
2863 ;; operands: inv2, norm32, inv1, i92
2864 (define_insn_and_split "divsi_inv_m2"
2865   [(set (match_operand:SI 0 "register_operand" "=r")
2866         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2867                     (match_operand:SI 2 "register_operand" "r")
2868                     (match_operand:DI 3 "register_operand" "r")]
2869          UNSPEC_DIV_INV_M2))
2870    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2871   "TARGET_SHMEDIA"
2872   "#"
2873   "&& !can_create_pseudo_p ()"
2874   [(pc)]
2877  muls.l r18, r25, r0  // s2.60
2878  shari r0, 16, r0     // s-16.44
2879   sub
2880  muls.l r0, r18, r19  // s-16.74
2881  shari r19, 30, r19   // s-16.44
2883   rtx inv2 = operands[0];
2884   rtx norm32 = operands[1];
2885   rtx inv1 = operands[2];
2886   rtx i92 = operands[3];
2887   rtx scratch0 = operands[4];
2888   rtx scratch0_si = gen_lowpart (SImode, scratch0);
2890   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2891   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2892   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2893   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2894   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2895   DONE;
2898 (define_insn_and_split "divsi_inv_m3"
2899   [(set (match_operand:SI 0 "register_operand" "=r")
2900         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2901                     (match_operand:SI 2 "register_operand" "r")
2902                     (match_operand:SI 3 "register_operand" "r")
2903                     (match_operand:DI 4 "register_operand" "r")
2904                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2905                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2906          UNSPEC_DIV_INV_M3))
2907    (clobber (match_operand:DI 7 "register_operand" "=r"))
2908    (clobber (match_operand:DI 8 "register_operand" "=r"))
2909    (clobber (match_operand:DI 9 "register_operand" "=r"))
2910    (clobber (match_operand:DI 10 "register_operand" "=r"))
2911    (clobber (match_operand:SI 11 "register_operand" "=r"))
2912    (clobber (match_operand:SI 12 "register_operand" "=r"))
2913    (clobber (match_operand:DI 13 "register_operand" "=r"))]
2914   "TARGET_SHMEDIA"
2915   "#"
2916   "&& !can_create_pseudo_p ()"
2917   [(pc)]
2920   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2921   r0: scratch0  r19: scratch1 r21: scratch2
2923   muls.l r18, r4, r25 // s32.30
2924  muls.l r19, r4, r19  // s15.30
2925  shari r25, 63, r21
2926   shari r19, 14, r19  // s18.-14
2927  sub r25, r19, r0
2928  shard r0, r1, r0
2929  sub r0, r21, r0
2932   rtx result = operands[0];
2933   rtx dividend = operands[1];
2934   rtx inv1 = operands[2];
2935   rtx inv2 = operands[3];
2936   rtx shift = operands[4];
2937   rtx scratch0 = operands[7];
2938   rtx scratch1 = operands[8];
2939   rtx scratch2 = operands[9];
2941   if (satisfies_constraint_N (dividend))
2942     {
2943       emit_move_insn (result, dividend);
2944       DONE;
2945     }
2947   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2948   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2949   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2950   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2951   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2952   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2953   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2954   DONE;
2957 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2958 ;; inv1: tab_base, tab_ix, norm32
2959 ;; inv2: norm32, inv1, i92
2960 (define_insn_and_split "divsi_inv_m1_3"
2961   [(set (match_operand:SI 0 "register_operand" "=r")
2962         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2963                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2964                                 (match_operand:DI 3 "register_operand" "r")
2965                                 (match_operand:SI 4 "register_operand" "r")]
2966                      UNSPEC_DIV_INV_M1)
2967                     (unspec:SI [(match_dup 4)
2968                                 (unspec:SI [(match_dup 2)
2969                                             (match_dup 3)
2970                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
2971                                 (match_operand:SI 5 "" "")]
2972                      UNSPEC_DIV_INV_M2)
2973                     (match_operand:DI 6 "register_operand" "r")
2974                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2975                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2976          UNSPEC_DIV_INV_M3))
2977    (clobber (match_operand:DI 9 "register_operand" "=r"))
2978    (clobber (match_operand:DI 10 "register_operand" "=r"))
2979    (clobber (match_operand:DI 11 "register_operand" "=r"))
2980    (clobber (match_operand:DI 12 "register_operand" "=r"))
2981    (clobber (match_operand:SI 13 "register_operand" "=r"))
2982    (clobber (match_operand:SI 14 "register_operand" "=r"))
2983    (clobber (match_operand:DI 15 "register_operand" "=r"))]
2984   "TARGET_SHMEDIA
2985    && (TARGET_DIVIDE_INV_MINLAT
2986        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2987   "#"
2988   "&& !can_create_pseudo_p ()"
2989   [(pc)]
2991   rtx result = operands[0];
2992   rtx dividend = operands[1];
2993   rtx tab_base = operands[2];
2994   rtx tab_ix = operands[3];
2995   rtx norm32 = operands[4];
2996   /* rtx i92 = operands[5]; */
2997   rtx shift = operands[6];
2998   rtx i2p27 = operands[7];
2999   rtx i43 = operands[8];
3000   rtx scratch0 = operands[9];
3001   rtx scratch0_si = gen_lowpart (SImode, scratch0);
3002   rtx scratch1 = operands[10];
3003   rtx scratch1_si = gen_lowpart (SImode, scratch1);
3004   rtx scratch2 = operands[11];
3005   rtx scratch3 = operands[12];
3006   rtx scratch4 = operands[13];
3007   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3008   rtx scratch5 = operands[14];
3009   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3010   rtx scratch6 = operands[15];
3012   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3013                                scratch0, scratch1));
3014   /* inv0 == scratch4 */
3015   if (! TARGET_DIVIDE_INV20U)
3016     {
3017       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3018       i2p27 = scratch0;
3019       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3020     }
3021   else
3022     {
3023       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3024       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3025     }
3026   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3027   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3028   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3029   /* inv1 == scratch4 */
3031   if (TARGET_DIVIDE_INV_MINLAT)
3032     {
3033       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3034       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3035       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3036       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3037       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3038       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3039       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3040       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3041       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3042       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3043       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3044     }
3045   else
3046     {
3047       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3048       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
3049       emit_insn (gen_nsbdi (scratch6,
3050                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
3051       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3052       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3053       emit_insn (gen_divsi_inv20 (scratch2,
3054                                   norm32, scratch4, dividend,
3055                                   scratch6, scratch3, i43,
3056                                   /* scratch0 may be shared with i2p27.  */
3057                                   scratch0, scratch1, scratch5,
3058                                   label, label, i2p27));
3059     }
3060   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3061   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3062   DONE;
3065 (define_insn "divsi_inv20"
3066   [(set (match_operand:DI 0 "register_operand" "=&r")
3067         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
3068                     (match_operand:SI 2 "register_operand" "r")
3069                     (match_operand:SI 3 "register_operand" "r")
3070                     (match_operand:DI 4 "register_operand" "r")
3071                     (match_operand:DI 5 "register_operand" "r")
3072                     (match_operand:DI 6 "register_operand" "r")
3073                     (match_operand:DI 12 "register_operand" "r")
3074                     (match_operand 10 "target_operand" "b")
3075                     (match_operand 11 "immediate_operand" "i")]
3076          UNSPEC_DIV_INV20))
3077    (clobber (match_operand:DI 7 "register_operand" "=&r"))
3078    (clobber (match_operand:DI 8 "register_operand" "=&r"))
3079    (clobber (match_operand:SI 9 "register_operand" "=r"))]
3080   "TARGET_SHMEDIA
3081    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3083 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3084              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3085              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3086              %10 label (tr), %11 label (imm)
3088  muls.l inv1, norm32, scratch0  // s2.60
3089   muls.l inv1, dividend, result // s32.30
3090   xor i2p27, result_sign, round_scratch
3091  bge/u dividend_nsb, i43, tr.. (label)
3092  shari scratch0, 16, scratch0   // s-16.44
3093  muls.l sratch0_si, inv1, scratch0 // s-16.74
3094   sub result, round_scratch, result
3095   shari dividend, 14, scratch1   // s19.-14
3096  shari scratch0, 30, scratch0   // s-16.44
3097  muls.l scratch0, scratch1, round_scratch // s15.30
3098 label:
3099  sub result, round_scratch, result */
3101   const bool likely = TARGET_DIVIDE_INV20L;
3102   if (likely)
3103     return
3104                "muls.l  %2, %3, %0"     "\n"
3105         "       xor     %12, %5, %7"    "\n"
3106         "       bge/l   %4, %6, %10"    "\n"
3107         "       muls.l  %2, %1, %8"     "\n"
3108         "       shari   %8, 16, %8"     "\n"
3109         "       muls.l  %8, %2, %8"     "\n"
3110         "       shari   %3, 14, %9"     "\n"
3111         "       shari   %8, 30, %8"     "\n"
3112         "       muls.l  %8, %9, %8"     "\n"
3113         "       sub     %0, %8, %0"     "\n"
3114         "%11:   add     %0, %7, %0";
3115   else
3116     return
3117                "muls.l  %2, %1, %8"     "\n"
3118         "       muls.l  %2, %3, %0"     "\n"
3119         "       xor     %12, %5, %7"    "\n"
3120         "       bge/u   %4, %6, %10"    "\n"
3121         "       shari   %8, 16, %8"     "\n"
3122         "       muls.l  %8, %2, %8"     "\n"
3123         "       sub     %0, %7, %0"     "\n"
3124         "       shari   %3, 14, %9"     "\n"
3125         "       shari   %8, 30, %8"     "\n"
3126         "       muls.l  %8, %9, %7"     "\n"
3127         "%11:   sub     %0, %7, %0";
3130 (define_insn_and_split "divsi_inv_fp"
3131   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3132         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3133                 (match_operand:SI 2 "register_operand" "rf")))
3134    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3135    (clobber (match_operand:SI 4 "register_operand" "=r"))
3136    (clobber (match_operand:SI 5 "register_operand" "=r"))
3137    (clobber (match_operand:DF 6 "register_operand" "=r"))
3138    (clobber (match_operand:DF 7 "register_operand" "=r"))
3139    (clobber (match_operand:DF 8 "register_operand" "=r"))]
3140   "TARGET_SHMEDIA_FPU"
3141   "#"
3142   "&& (reload_in_progress || reload_completed)"
3143   [(set (match_dup 0) (match_dup 3))]
3144   ""
3145   [(set_attr "highpart" "must_split")])
3147 ;; If a matching group of divide-by-inverse instructions is in the same
3148 ;; basic block after gcse & loop optimizations, we want to transform them
3149 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3150 (define_insn_and_split "*divsi_inv_fp_combine"
3151   [(set (match_operand:SI 0 "register_operand" "=f")
3152         (div:SI (match_operand:SI 1 "register_operand" "f")
3153                 (match_operand:SI 2 "register_operand" "f")))
3154    (use (unspec:SI [(match_dup 1)
3155                     (match_operand:SI 3 "" "")
3156                     (unspec:SI [(match_operand:SI 4 "" "")
3157                                 (match_dup 3)
3158                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3159                     (match_operand:DI 6 "" "")
3160                     (const_int 0)
3161                     (const_int 0)] UNSPEC_DIV_INV_M3))
3162    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3163    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3164    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3165    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3166    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3167   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3168   "#"
3169   "&& 1"
3170   [(set (match_dup 9) (float:DF (match_dup 1)))
3171    (set (match_dup 10) (float:DF (match_dup 2)))
3172    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3173    (set (match_dup 8)
3174         (fix:SI (match_dup 11)))
3175    (set (match_dup 0) (match_dup 8))]
3177   if (! fp_arith_reg_operand (operands[1], SImode))
3178     {
3179       emit_move_insn (operands[7], operands[1]);
3180       operands[1] = operands[7];
3181     }
3182   if (! fp_arith_reg_operand (operands[2], SImode))
3183     {
3184       emit_move_insn (operands[8], operands[2]);
3185       operands[2] = operands[8];
3186     }
3188   [(set_attr "highpart" "must_split")])
3190 ;; -------------------------------------------------------------------------
3191 ;; Multiplication instructions
3192 ;; -------------------------------------------------------------------------
3194 (define_insn "umulhisi3_i"
3195   [(set (reg:SI MACL_REG)
3196         (mult:SI (zero_extend:SI
3197                   (match_operand:HI 0 "arith_reg_operand" "r"))
3198                  (zero_extend:SI
3199                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
3200   "TARGET_SH1"
3201   "mulu.w       %1,%0"
3202   [(set_attr "type" "smpy")])
3204 (define_insn "mulhisi3_i"
3205   [(set (reg:SI MACL_REG)
3206         (mult:SI (sign_extend:SI
3207                   (match_operand:HI 0 "arith_reg_operand" "r"))
3208                  (sign_extend:SI
3209                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
3210   "TARGET_SH1"
3211   "muls.w       %1,%0"
3212   [(set_attr "type" "smpy")])
3214 (define_expand "mulhisi3"
3215   [(set (reg:SI MACL_REG)
3216         (mult:SI (sign_extend:SI
3217                   (match_operand:HI 1 "arith_reg_operand" ""))
3218                  (sign_extend:SI
3219                   (match_operand:HI 2 "arith_reg_operand" ""))))
3220    (set (match_operand:SI 0 "arith_reg_operand" "")
3221         (reg:SI MACL_REG))]
3222   "TARGET_SH1"
3224   rtx insn, macl;
3226   macl = gen_rtx_REG (SImode, MACL_REG);
3227   start_sequence ();
3228   emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3229   insn = get_insns ();  
3230   end_sequence ();
3231   /* expand_binop can't find a suitable code in umul_widen_optab to
3232      make a REG_EQUAL note from, so make one here.
3233      See also smulsi3_highpart.
3234      ??? Alternatively, we could put this at the calling site of expand_binop,
3235      i.e. expand_expr.  */
3236   /* Use emit_libcall_block for loop invariant code motion and to make
3237      a REG_EQUAL note.  */
3238   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3240   DONE;
3243 (define_expand "umulhisi3"
3244   [(set (reg:SI MACL_REG)
3245         (mult:SI (zero_extend:SI
3246                   (match_operand:HI 1 "arith_reg_operand" ""))
3247                  (zero_extend:SI
3248                   (match_operand:HI 2 "arith_reg_operand" ""))))
3249    (set (match_operand:SI 0 "arith_reg_operand" "")
3250         (reg:SI MACL_REG))]
3251   "TARGET_SH1"
3253   rtx insn, macl;
3255   macl = gen_rtx_REG (SImode, MACL_REG);
3256   start_sequence ();
3257   emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3258   insn = get_insns ();  
3259   end_sequence ();
3260   /* expand_binop can't find a suitable code in umul_widen_optab to
3261      make a REG_EQUAL note from, so make one here.
3262      See also smulsi3_highpart.
3263      ??? Alternatively, we could put this at the calling site of expand_binop,
3264      i.e. expand_expr.  */
3265   /* Use emit_libcall_block for loop invariant code motion and to make
3266      a REG_EQUAL note.  */
3267   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3269   DONE;
3272 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3273 ;; a call to a routine which clobbers known registers.
3274 (define_insn ""
3275   [(set (match_operand:SI 1 "register_operand" "=z")
3276         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3277    (clobber (reg:SI MACL_REG))
3278    (clobber (reg:SI T_REG))
3279    (clobber (reg:SI PR_REG))
3280    (clobber (reg:SI R3_REG))
3281    (clobber (reg:SI R2_REG))
3282    (clobber (reg:SI R1_REG))
3283    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3284   "TARGET_SH1"
3285   "jsr  @%0%#"
3286   [(set_attr "type" "sfunc")
3287    (set_attr "needs_delay_slot" "yes")])
3289 (define_expand "mulsi3_call"
3290   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3291    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3292    (parallel[(set (match_operand:SI 0 "register_operand" "")
3293                   (mult:SI (reg:SI R4_REG)
3294                            (reg:SI R5_REG)))
3295              (clobber (reg:SI MACL_REG))
3296              (clobber (reg:SI T_REG))
3297              (clobber (reg:SI PR_REG))
3298              (clobber (reg:SI R3_REG))
3299              (clobber (reg:SI R2_REG))
3300              (clobber (reg:SI R1_REG))
3301              (use (match_operand:SI 3 "register_operand" ""))])]
3302   "TARGET_SH1"
3303   "")
3305 (define_insn "mul_r"
3306   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3307         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3308                  (match_operand:SI 2 "arith_reg_operand" "z")))]
3309   "TARGET_SH2A"
3310   "mulr %2,%0"
3311   [(set_attr "type" "dmpy")])
3313 (define_insn "mul_l"
3314   [(set (reg:SI MACL_REG)
3315         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3316                  (match_operand:SI 1 "arith_reg_operand" "r")))]
3317   "TARGET_SH2"
3318   "mul.l        %1,%0"
3319   [(set_attr "type" "dmpy")])
3321 (define_expand "mulsi3"
3322   [(set (reg:SI MACL_REG)
3323         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
3324                   (match_operand:SI 2 "arith_reg_operand" "")))
3325    (set (match_operand:SI 0 "arith_reg_operand" "")
3326         (reg:SI MACL_REG))]
3327   "TARGET_SH1"
3329   if (!TARGET_SH2)
3330     {
3331       /* The address must be set outside the libcall,
3332          since it goes into a pseudo.  */
3333       rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3334       rtx addr = force_reg (SImode, sym);
3335       rtx insns = gen_mulsi3_call (operands[0], operands[1],
3336                                    operands[2], addr);
3337       emit_insn (insns);
3338     }
3339   else
3340     {
3341       rtx macl = gen_rtx_REG (SImode, MACL_REG);
3343       emit_insn (gen_mul_l (operands[1], operands[2]));
3344       /* consec_sets_giv can only recognize the first insn that sets a
3345          giv as the giv insn.  So we must tag this also with a REG_EQUAL
3346          note.  */
3347       emit_insn (gen_movsi_i ((operands[0]), macl));
3348     }
3349   DONE;
3352 (define_insn "mulsidi3_i"
3353   [(set (reg:SI MACH_REG)
3354         (truncate:SI
3355          (lshiftrt:DI
3356           (mult:DI
3357            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3358            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3359           (const_int 32))))
3360    (set (reg:SI MACL_REG)
3361         (mult:SI (match_dup 0)
3362                  (match_dup 1)))]
3363   "TARGET_SH2"
3364   "dmuls.l      %1,%0"
3365   [(set_attr "type" "dmpy")])
3367 (define_expand "mulsidi3"
3368   [(set (match_operand:DI 0 "arith_reg_dest" "")
3369         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3370                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3371   "TARGET_SH2 || TARGET_SHMEDIA"
3373   if (TARGET_SH2)
3374     {
3375       emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3376       DONE;
3377     }
3380 (define_insn "mulsidi3_media"
3381   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3382         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3383                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3384   "TARGET_SHMEDIA"
3385   "muls.l       %1, %2, %0"
3386   [(set_attr "type" "dmpy_media")
3387    (set_attr "highpart" "ignore")])
3389 (define_insn_and_split "mulsidi3_compact"
3390   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3391         (mult:DI
3392          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3393          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3394    (clobber (reg:SI MACH_REG))
3395    (clobber (reg:SI MACL_REG))]
3396   "TARGET_SH2"
3397   "#"
3398   "&& 1"
3399   [(const_int 0)]
3401   rtx low_dst = gen_lowpart (SImode, operands[0]);
3402   rtx high_dst = gen_highpart (SImode, operands[0]);
3404   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3406   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3407   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3408   /* We need something to tag the possible REG_EQUAL notes on to.  */
3409   emit_move_insn (operands[0], operands[0]);
3410   DONE;
3413 (define_insn "umulsidi3_i"
3414   [(set (reg:SI MACH_REG)
3415         (truncate:SI
3416          (lshiftrt:DI
3417           (mult:DI
3418            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3419            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3420           (const_int 32))))
3421    (set (reg:SI MACL_REG)
3422         (mult:SI (match_dup 0)
3423                  (match_dup 1)))]
3424   "TARGET_SH2"
3425   "dmulu.l      %1,%0"
3426   [(set_attr "type" "dmpy")])
3428 (define_expand "umulsidi3"
3429   [(set (match_operand:DI 0 "arith_reg_dest" "")
3430         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3431                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3432   "TARGET_SH2 || TARGET_SHMEDIA"
3434   if (TARGET_SH2)
3435     {
3436       emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3437       DONE;
3438     }
3441 (define_insn "umulsidi3_media"
3442   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3443         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3444                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3445   "TARGET_SHMEDIA"
3446   "mulu.l       %1, %2, %0"
3447   [(set_attr "type" "dmpy_media")
3448    (set_attr "highpart" "ignore")])
3450 (define_insn_and_split "umulsidi3_compact"
3451   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3452         (mult:DI
3453          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3454          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3455    (clobber (reg:SI MACH_REG))
3456    (clobber (reg:SI MACL_REG))]
3457   "TARGET_SH2"
3458   "#"
3459   "&& 1"
3460   [(const_int 0)]
3462   rtx low_dst = gen_lowpart (SImode, operands[0]);
3463   rtx high_dst = gen_highpart (SImode, operands[0]);
3465   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3467   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3468   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3469   /* We need something to tag the possible REG_EQUAL notes on to.  */
3470   emit_move_insn (operands[0], operands[0]);
3471   DONE;
3474 (define_insn "smulsi3_highpart_i"
3475   [(set (reg:SI MACH_REG)
3476         (truncate:SI
3477          (lshiftrt:DI
3478           (mult:DI
3479            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3480            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3481           (const_int 32))))
3482    (clobber (reg:SI MACL_REG))]
3483   "TARGET_SH2"
3484   "dmuls.l      %1,%0"
3485   [(set_attr "type" "dmpy")])
3487 (define_expand "smulsi3_highpart"
3488   [(parallel
3489     [(set (reg:SI MACH_REG)
3490           (truncate:SI
3491            (lshiftrt:DI
3492             (mult:DI
3493              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3494              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3495             (const_int 32))))
3496     (clobber (reg:SI MACL_REG))])
3497    (set (match_operand:SI 0 "arith_reg_operand" "")
3498         (reg:SI MACH_REG))]
3499   "TARGET_SH2"
3501   rtx insn, mach;
3503   mach = gen_rtx_REG (SImode, MACH_REG);
3504   start_sequence ();
3505   emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3506   insn = get_insns ();  
3507   end_sequence ();
3508   /* expand_binop can't find a suitable code in mul_highpart_optab to
3509      make a REG_EQUAL note from, so make one here.
3510      See also {,u}mulhisi.
3511      ??? Alternatively, we could put this at the calling site of expand_binop,
3512      i.e. expand_mult_highpart.  */
3513   /* Use emit_libcall_block for loop invariant code motion and to make
3514      a REG_EQUAL note.  */
3515   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3517   DONE;
3520 (define_insn "umulsi3_highpart_i"
3521   [(set (reg:SI MACH_REG)
3522         (truncate:SI
3523          (lshiftrt:DI
3524           (mult:DI
3525            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3526            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3527           (const_int 32))))
3528    (clobber (reg:SI MACL_REG))]
3529   "TARGET_SH2"
3530   "dmulu.l      %1,%0"
3531   [(set_attr "type" "dmpy")])
3533 (define_expand "umulsi3_highpart"
3534   [(parallel
3535     [(set (reg:SI MACH_REG)
3536           (truncate:SI
3537            (lshiftrt:DI
3538             (mult:DI
3539              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3540              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3541             (const_int 32))))
3542     (clobber (reg:SI MACL_REG))])
3543    (set (match_operand:SI 0 "arith_reg_operand" "")
3544         (reg:SI MACH_REG))]
3545   "TARGET_SH2"
3547   rtx insn, mach;
3549   mach = gen_rtx_REG (SImode, MACH_REG);
3550   start_sequence ();
3551   emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3552   insn = get_insns ();  
3553   end_sequence ();
3554   /* Use emit_libcall_block for loop invariant code motion and to make
3555      a REG_EQUAL note.  */
3556   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3558   DONE;
3561 (define_insn_and_split "muldi3"
3562   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3563         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3564                  (match_operand:DI 2 "arith_reg_operand" "r")))
3565    (clobber (match_scratch:DI 3 "=&r"))
3566    (clobber (match_scratch:DI 4 "=r"))]
3567   "TARGET_SHMEDIA"
3568   "#"
3569   "reload_completed"
3570   [(const_int 0)]
3572   rtx op3_v2si, op2_v2si;
3574   op3_v2si = operands[3];
3575   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3576     {
3577       op3_v2si = XEXP (op3_v2si, 0);
3578       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3579     }
3580   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3581   op2_v2si = operands[2];
3582   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3583     {
3584       op2_v2si = XEXP (op2_v2si, 0);
3585       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3586     }
3587   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3588   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3589   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3590   emit_insn (gen_umulsidi3_media (operands[4],
3591                                  sh_gen_truncate (SImode, operands[1], 0),
3592                                  sh_gen_truncate (SImode, operands[2], 0)));
3593   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3594   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3595   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3596   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3597   DONE;
3600 ;; -------------------------------------------------------------------------
3601 ;; Logical operations
3602 ;; -------------------------------------------------------------------------
3604 (define_expand "andsi3"
3605   [(set (match_operand:SI 0 "arith_reg_operand" "")
3606         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3607                 (match_operand:SI 2 "logical_and_operand" "")))]
3608   ""
3610   /* If it is possible to turn the and insn into a zero extension
3611      already, redundant zero extensions will be folded, which results
3612      in better code.  
3613      Ideally the splitter of *andsi_compact would be enough, if redundant
3614      zero extensions were detected after the combine pass, which does not
3615      happen at the moment.  */
3616   if (TARGET_SH1)
3617     {
3618       if (satisfies_constraint_Jmb (operands[2]))
3619         {
3620           emit_insn (gen_zero_extendqisi2 (operands[0],
3621                                            gen_lowpart (QImode, operands[1])));
3622           DONE;
3623         }
3624       else if (satisfies_constraint_Jmw (operands[2]))
3625         {
3626           emit_insn (gen_zero_extendhisi2 (operands[0],
3627                                            gen_lowpart (HImode, operands[1])));
3628           DONE;
3629         }
3630     }
3633 (define_insn_and_split "*andsi_compact"
3634   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3635         (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3636                 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3637   "TARGET_SH1"
3638   "@
3639         extu.b  %1,%0
3640         extu.w  %1,%0
3641         and     %2,%0
3642         and     %2,%0"
3643   "&& 1"
3644  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3646   if (satisfies_constraint_Jmb (operands[2]))
3647     operands[1] = gen_lowpart (QImode, operands[1]);
3648   else if (satisfies_constraint_Jmw (operands[2]))
3649     operands[1] = gen_lowpart (HImode, operands[1]);
3650   else
3651     FAIL;
3653   [(set_attr "type" "arith")])
3655 (define_insn "*andsi3_media"
3656   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3657         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3658                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3659   "TARGET_SHMEDIA"
3660   "@
3661         and     %1, %2, %0
3662         andi    %1, %2, %0"
3663   [(set_attr "type" "arith_media")])
3665 (define_insn "*andsi3_bclr"
3666   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3667         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3668                 (match_operand:SI 2 "const_int_operand" "Psz")))]
3669   "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3670   "bclr %W2,%0"
3671   [(set_attr "type" "arith")])
3673 (define_insn_and_split "anddi3"
3674   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3675         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3676                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3677   "TARGET_SHMEDIA"
3678   "@
3679         and     %1, %2, %0
3680         andi    %1, %2, %0
3681         #"
3682   "reload_completed
3683    && ! logical_operand (operands[2], DImode)"
3684   [(const_int 0)]
3686   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3687     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3688   else
3689     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3690   DONE;
3692   [(set_attr "type" "arith_media")])
3694 (define_insn "andcsi3"
3695   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3696         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3697                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3698   "TARGET_SHMEDIA"
3699   "andc %1,%2,%0"
3700   [(set_attr "type" "arith_media")])
3702 (define_insn "andcdi3"
3703   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3704         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3705                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3706   "TARGET_SHMEDIA"
3707   "andc %1,%2,%0"
3708   [(set_attr "type" "arith_media")])
3710 (define_expand "iorsi3"
3711   [(set (match_operand:SI 0 "arith_reg_operand" "")
3712         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3713                 (match_operand:SI 2 "logical_operand" "")))]
3714   ""
3715   "")
3717 (define_insn "*iorsi3_compact"
3718   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3719         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3720                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3721   "TARGET_SH1
3722    && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3723   "or   %2,%0"
3724   [(set_attr "type" "arith")])
3726 (define_insn "*iorsi3_media"
3727   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3728         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3729                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3730   "TARGET_SHMEDIA"
3731   "@
3732         or      %1, %2, %0
3733         ori     %1, %2, %0"
3734   [(set_attr "type" "arith_media")])
3736 (define_insn "*iorsi3_bset"
3737   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3738         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3739         (match_operand:SI 2 "const_int_operand" "Pso")))]
3740   "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3741   "bset %V2,%0"
3742   [(set_attr "type" "arith")])
3744 (define_insn "iordi3"
3745   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3746         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3747                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3748   "TARGET_SHMEDIA"
3749   "@
3750         or      %1, %2, %0
3751         ori     %1, %2, %0"
3752   [(set_attr "type" "arith_media")])
3754 (define_insn_and_split "*logical_sidi3"
3755   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3756         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3757                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3758                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3759   "TARGET_SHMEDIA"
3760   "#"
3761   "&& reload_completed"
3762   [(set (match_dup 0) (match_dup 3))]
3764   operands[3]
3765     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3766                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3767                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3770 (define_insn_and_split "*logical_sidisi3"
3771   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3772         (truncate:SI (sign_extend:DI
3773                         (match_operator:SI 3 "logical_operator"
3774                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3775                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3776   "TARGET_SHMEDIA"
3777   "#"
3778   "&& 1"
3779   [(set (match_dup 0) (match_dup 3))])
3781 (define_insn_and_split "*logical_sidi3_2"
3782   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3783         (sign_extend:DI (truncate:SI (sign_extend:DI
3784                         (match_operator:SI 3 "logical_operator"
3785                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3786                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3787   "TARGET_SHMEDIA"
3788   "#"
3789   "&& 1"
3790   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3792 (define_expand "xorsi3"
3793   [(set (match_operand:SI 0 "arith_reg_operand" "")
3794         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3795                 (match_operand:SI 2 "xor_operand" "")))]
3796   ""
3797   "")
3799 (define_insn "*xorsi3_compact"
3800   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3801         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3802                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3803   "TARGET_SH1"
3804   "xor  %2,%0"
3805   [(set_attr "type" "arith")])
3807 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3808 ;; of results where one of the inputs is a T bit store.  Notice that this
3809 ;; pattern must not match during reload.  If reload picks this pattern it
3810 ;; will be impossible to split it afterwards.
3811 (define_insn_and_split "*logical_op_t"
3812   [(set (match_operand:SI 0 "arith_reg_dest")
3813         (match_operator:SI 3 "logical_operator"
3814           [(match_operand:SI 1 "arith_reg_operand")
3815            (match_operand:SI 2 "t_reg_operand")]))]
3816   "TARGET_SH1 && can_create_pseudo_p ()"
3817   "#"
3818   "&& 1"
3819   [(set (match_dup 4) (reg:SI T_REG))
3820    (set (match_dup 0) (match_dup 3))]
3822   operands[4] = gen_reg_rtx (SImode);
3823   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3824                                 operands[1], operands[4]);
3827 (define_insn "*xorsi3_media"
3828   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3829         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3830                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3831   "TARGET_SHMEDIA"
3832   "@
3833         xor     %1, %2, %0
3834         xori    %1, %2, %0"
3835   [(set_attr "type" "arith_media")])
3837 (define_insn "xordi3"
3838   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3839         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3840                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3841   "TARGET_SHMEDIA"
3842   "@
3843         xor     %1, %2, %0
3844         xori    %1, %2, %0"
3845   [(set_attr "type" "arith_media")])
3847 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3848 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3849 (define_split
3850   [(set (match_operand:DI 0 "arith_reg_dest" "")
3851         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3852                           [(match_operand 1 "any_register_operand" "")
3853                            (match_operand 2 "any_register_operand" "")])))]
3854   "TARGET_SHMEDIA"
3855   [(set (match_dup 5) (match_dup 4))
3856    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3858   enum machine_mode inmode = GET_MODE (operands[1]);
3859   int offset = 0;
3861   if (GET_CODE (operands[0]) == SUBREG)
3862     {
3863       offset = SUBREG_BYTE (operands[0]);
3864       operands[0] = SUBREG_REG (operands[0]);
3865     }
3866   gcc_assert (REG_P (operands[0]));
3867   if (TARGET_BIG_ENDIAN)
3868     offset += 8 - GET_MODE_SIZE (inmode);
3869   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3872 ;; -------------------------------------------------------------------------
3873 ;; Shifts and rotates
3874 ;; -------------------------------------------------------------------------
3876 (define_expand "rotldi3"
3877   [(set (match_operand:DI 0 "arith_reg_dest" "")
3878         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3879                    (match_operand:HI 2 "mextr_bit_offset" "")))]
3880   "TARGET_SHMEDIA"
3882   if (! mextr_bit_offset (operands[2], HImode))
3883     FAIL;
3886 (define_insn "rotldi3_mextr"
3887   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3888         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3889                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3890   "TARGET_SHMEDIA"
3892   static char templ[16];
3893   sprintf (templ, "mextr%d      %%1,%%1,%%0",
3894            8 - (int) (INTVAL (operands[2]) >> 3));
3895   return templ;
3897   [(set_attr "type" "arith_media")])
3899 (define_expand "rotrdi3"
3900   [(set (match_operand:DI 0 "arith_reg_dest" "")
3901         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
3902                      (match_operand:HI 2 "mextr_bit_offset" "")))]
3903   "TARGET_SHMEDIA"
3905   if (! mextr_bit_offset (operands[2], HImode))
3906     FAIL;
3909 (define_insn "rotrdi3_mextr"
3910   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3911         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3912                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3913   "TARGET_SHMEDIA"
3915   static char templ[16];
3916   sprintf (templ, "mextr%d      %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
3917   return templ;
3919   [(set_attr "type" "arith_media")])
3921 (define_split
3922   [(set (match_operand:DI 0 "arith_reg_dest" "")
3923         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3924                                          "ua_address_operand" "")))
3925                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3926                            (const_int 8))))
3927    (clobber (match_operand:DI 3 "register_operand" ""))]
3928   "TARGET_SHMEDIA"
3929   [(match_dup 4) (match_dup 5)]
3931   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3932                  (operands[3], operands[1]));
3933   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3934                               GEN_INT (56), GEN_INT (8));
3937 (define_expand "rotrsi3"
3938   [(set (match_operand:SI 0 "arith_reg_dest")
3939         (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
3940                      (match_operand:SI 2 "const_int_operand")))]
3941   "TARGET_SH1"
3943   HOST_WIDE_INT ival = INTVAL (operands[2]);
3944   if (ival == 1)
3945     {
3946       emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
3947       DONE;
3948     }
3950   FAIL;
3953 (define_insn "rotrsi3_1"
3954   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3955         (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3956                      (const_int 1)))
3957    (set (reg:SI T_REG)
3958         (and:SI (match_dup 1) (const_int 1)))]
3959   "TARGET_SH1"
3960   "rotr %0"
3961   [(set_attr "type" "arith")])
3963 ;; A slimplified version of rotr for combine.
3964 (define_insn "*rotrsi3_1"
3965   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3966         (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3967                      (const_int 1)))
3968    (clobber (reg:SI T_REG))]
3969   "TARGET_SH1"
3970   "rotr %0"
3971   [(set_attr "type" "arith")])
3973 (define_insn "rotlsi3_1"
3974   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3975         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3976                    (const_int 1)))
3977    (set (reg:SI T_REG)
3978         (lshiftrt:SI (match_dup 1) (const_int 31)))]
3979   "TARGET_SH1"
3980   "rotl %0"
3981   [(set_attr "type" "arith")])
3983 ;; A simplified version of rotl for combine.
3984 (define_insn "*rotlsi3_1"
3985   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3986         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3987                    (const_int 1)))
3988    (clobber (reg:SI T_REG))]
3989   "TARGET_SH1"
3990   "rotl %0"
3991   [(set_attr "type" "arith")])
3993 (define_insn "rotlsi3_31"
3994   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3995         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3996                    (const_int 31)))
3997    (clobber (reg:SI T_REG))]
3998   "TARGET_SH1"
3999   "rotr %0"
4000   [(set_attr "type" "arith")])
4002 (define_insn "rotlsi3_16"
4003   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4004         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4005                    (const_int 16)))]
4006   "TARGET_SH1"
4007   "swap.w       %1,%0"
4008   [(set_attr "type" "arith")])
4010 (define_expand "rotlsi3"
4011   [(set (match_operand:SI 0 "arith_reg_dest")
4012         (rotate:SI (match_operand:SI 1 "arith_reg_operand")
4013                    (match_operand:SI 2 "const_int_operand")))]
4014   "TARGET_SH1"
4016   static const char rot_tab[] = {
4017     000, 000, 000, 000, 000, 000, 010, 001,
4018     001, 001, 011, 013, 003, 003, 003, 003,
4019     003, 003, 003, 003, 003, 013, 012, 002,
4020     002, 002, 010, 000, 000, 000, 000, 000,
4021   };
4023   int count = INTVAL (operands[2]);
4024   int choice = rot_tab[count];
4025   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4026     FAIL;
4027   choice &= 7;
4028   switch (choice)
4029     {
4030     case 0:
4031       emit_move_insn (operands[0], operands[1]);
4032       count -= (count & 16) * 2;
4033       break;
4034     case 3:
4035      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4036      count -= 16;
4037      break;
4038     case 1:
4039     case 2:
4040       {
4041         rtx parts[2];
4042         parts[0] = gen_reg_rtx (SImode);
4043         parts[1] = gen_reg_rtx (SImode);
4044         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4045         emit_move_insn (parts[choice-1], operands[1]);
4046         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4047         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4048         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4049         count = (count & ~16) - 8;
4050       }
4051     }
4053   for (; count > 0; count--)
4054     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4055   for (; count < 0; count++)
4056     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4058   DONE;
4061 (define_insn "rotlhi3_8"
4062   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4063         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4064                    (const_int 8)))]
4065   "TARGET_SH1"
4066   "swap.b       %1,%0"
4067   [(set_attr "type" "arith")])
4069 (define_expand "rotlhi3"
4070   [(set (match_operand:HI 0 "arith_reg_operand")
4071         (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4072                    (match_operand:HI 2 "const_int_operand")))]
4073   "TARGET_SH1"
4075   if (INTVAL (operands[2]) != 8)
4076     FAIL;
4079 ;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4080 ;; They can also be used to implement things like
4081 ;;      bool t = a == b;
4082 ;;      int x0 = (y >> 1) | (t << 31);  // rotcr
4083 ;;      int x1 = (y << 1) | t;          // rotcl
4084 (define_insn "rotcr"
4085   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4086         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4087                              (const_int 1))
4088                 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4089                            (const_int 31))))
4090    (set (reg:SI T_REG)
4091         (and:SI (match_dup 1) (const_int 1)))]
4092   "TARGET_SH1"
4093   "rotcr        %0"
4094   [(set_attr "type" "arith")])
4096 (define_insn "rotcl"
4097   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4098         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4099                            (const_int 1))
4100                 (match_operand:SI 2 "t_reg_operand")))
4101    (set (reg:SI T_REG)
4102         (lshiftrt:SI (match_dup 1) (const_int 31)))]
4103   "TARGET_SH1"
4104   "rotcl        %0"
4105   [(set_attr "type" "arith")])
4107 ;; Simplified rotcr version for combine, which allows arbitrary shift
4108 ;; amounts for the reg.  If the shift amount is '1' rotcr can be used
4109 ;; directly.  Otherwise we have to insert a shift in between.
4110 (define_insn_and_split "*rotcr"
4111   [(set (match_operand:SI 0 "arith_reg_dest")
4112         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4113                              (match_operand:SI 2 "const_int_operand"))
4114                 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4115                            (const_int 31))))
4116    (clobber (reg:SI T_REG))]
4117   "TARGET_SH1"
4118   "#"
4119   "&& can_create_pseudo_p ()"
4120   [(const_int 0)]
4122   if (INTVAL (operands[2]) > 1)
4123     {
4124       const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4125       rtx prev_set_t_insn = NULL_RTX;
4126       rtx tmp_t_reg = NULL_RTX;
4128       /* If we're going to emit a shift sequence that clobbers the T_REG,
4129          try to find the previous insn that sets the T_REG and emit the 
4130          shift insn before that insn, to remove the T_REG dependency.
4131          If the insn that sets the T_REG cannot be found, store the T_REG
4132          in a temporary reg and restore it after the shift.  */
4133       if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4134           && ! sh_dynamicalize_shift_p (shift_count))
4135         {
4136           prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4138           /* Skip the nott insn, which was probably inserted by the splitter
4139              of *rotcr_neg_t.  Don't use one of the recog functions
4140              here during insn splitting, since that causes problems in later
4141              passes.  */
4142           if (prev_set_t_insn != NULL_RTX)
4143             {
4144               rtx pat = PATTERN (prev_set_t_insn);
4145               if (GET_CODE (pat) == SET
4146                   && t_reg_operand (XEXP (pat, 0), SImode)
4147                   && negt_reg_operand (XEXP (pat, 1), SImode))
4148               prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4149             }
4151           if (! (prev_set_t_insn != NULL_RTX
4152                  && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4153                  && ! reg_referenced_p (get_t_reg_rtx (),
4154                                         PATTERN (prev_set_t_insn))))
4155             {
4156               prev_set_t_insn = NULL_RTX;
4157               tmp_t_reg = gen_reg_rtx (SImode);
4158               emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4159             } 
4160         }
4162       rtx shift_result = gen_reg_rtx (SImode);
4163       rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4164       operands[1] = shift_result;
4166       /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4167       if (prev_set_t_insn != NULL_RTX)
4168         emit_insn_before (shift_insn, prev_set_t_insn);
4169       else
4170         emit_insn (shift_insn);
4172       /* Restore T_REG if it has been saved before.  */
4173       if (tmp_t_reg != NULL_RTX)
4174         emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4175     }
4177   /* For the rotcr insn to work, operands[3] must be in T_REG.
4178      If it is not we can get it there by shifting it right one bit.
4179      In this case T_REG is not an input for this insn, thus we don't have to
4180      pay attention as of where to insert the shlr insn.  */
4181   if (! t_reg_operand (operands[3], SImode))
4182     {
4183       /* We don't care about the shifted result here, only the T_REG.  */
4184       emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4185       operands[3] = get_t_reg_rtx ();
4186     }
4188   emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4189   DONE;
4192 ;; If combine tries the same as above but with swapped operands, split
4193 ;; it so that it will try the pattern above.
4194 (define_split
4195   [(set (match_operand:SI 0 "arith_reg_dest")
4196         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4197                            (const_int 31))
4198                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4199                              (match_operand:SI 3 "const_int_operand"))))]
4200   "TARGET_SH1 && can_create_pseudo_p ()"
4201   [(parallel [(set (match_dup 0)
4202                    (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4203                            (ashift:SI (match_dup 1) (const_int 31))))
4204               (clobber (reg:SI T_REG))])])
4206 ;; Basically the same as the rotcr pattern above, but for rotcl.
4207 ;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4208 (define_insn_and_split "*rotcl"
4209   [(set (match_operand:SI 0 "arith_reg_dest")
4210         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4211                            (match_operand:SI 2 "const_int_operand"))
4212                 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4213                         (const_int 1))))
4214    (clobber (reg:SI T_REG))]
4215   "TARGET_SH1"
4216   "#"
4217   "&& can_create_pseudo_p ()"
4218   [(const_int 0)]
4220   gcc_assert (INTVAL (operands[2]) > 0);
4222   if (INTVAL (operands[2]) > 1)
4223     {
4224       const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4225       rtx prev_set_t_insn = NULL_RTX;
4226       rtx tmp_t_reg = NULL_RTX;
4228       /* If we're going to emit a shift sequence that clobbers the T_REG,
4229          try to find the previous insn that sets the T_REG and emit the 
4230          shift insn before that insn, to remove the T_REG dependency.
4231          If the insn that sets the T_REG cannot be found, store the T_REG
4232          in a temporary reg and restore it after the shift.  */
4233       if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4234           && ! sh_dynamicalize_shift_p (shift_count))
4235         {
4236           prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4238           /* Skip the nott insn, which was probably inserted by the splitter
4239              of *rotcl_neg_t.  Don't use one of the recog functions
4240              here during insn splitting, since that causes problems in later
4241              passes.  */
4242           if (prev_set_t_insn != NULL_RTX)
4243             {
4244               rtx pat = PATTERN (prev_set_t_insn);
4245               if (GET_CODE (pat) == SET
4246                   && t_reg_operand (XEXP (pat, 0), SImode)
4247                   && negt_reg_operand (XEXP (pat, 1), SImode))
4248               prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4249             }
4251           if (! (prev_set_t_insn != NULL_RTX
4252                  && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4253                  && ! reg_referenced_p (get_t_reg_rtx (),
4254                                         PATTERN (prev_set_t_insn))))
4255             {
4256               prev_set_t_insn = NULL_RTX;
4257               tmp_t_reg = gen_reg_rtx (SImode);
4258               emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4259             } 
4260         }
4262       rtx shift_result = gen_reg_rtx (SImode);
4263       rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4264       operands[1] = shift_result;
4266       /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4267       if (prev_set_t_insn != NULL_RTX)
4268         emit_insn_before (shift_insn, prev_set_t_insn);
4269       else
4270         emit_insn (shift_insn);
4272       /* Restore T_REG if it has been saved before.  */
4273       if (tmp_t_reg != NULL_RTX)
4274         emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4275     }
4277   /* For the rotcl insn to work, operands[3] must be in T_REG.
4278      If it is not we can get it there by shifting it right one bit.
4279      In this case T_REG is not an input for this insn, thus we don't have to
4280      pay attention as of where to insert the shlr insn.  */
4281   if (! t_reg_operand (operands[3], SImode))
4282     {
4283       /* We don't care about the shifted result here, only the T_REG.  */
4284       emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4285       operands[3] = get_t_reg_rtx ();
4286     }
4288   emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4289   DONE;
4292 ;; rotcl combine pattern variations
4293 (define_insn_and_split "*rotcl"
4294   [(set (match_operand:SI 0 "arith_reg_dest")
4295         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4296                            (match_operand:SI 2 "const_int_operand"))
4297                 (match_operand:SI 3 "t_reg_operand")))
4298    (clobber (reg:SI T_REG))]
4299   "TARGET_SH1"
4300   "#"
4301   "&& can_create_pseudo_p ()"
4302   [(parallel [(set (match_dup 0)
4303                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4304                            (and:SI (match_dup 3) (const_int 1))))
4305               (clobber (reg:SI T_REG))])])
4307 (define_insn_and_split "*rotcl"
4308   [(set (match_operand:SI 0 "arith_reg_dest")
4309         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4310                         (const_int 1))
4311                 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4312                            (match_operand:SI 3 "const_int_operand"))))
4313    (clobber (reg:SI T_REG))]
4314   "TARGET_SH1"
4315   "#"
4316   "&& can_create_pseudo_p ()"
4317   [(parallel [(set (match_dup 0)
4318                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4319                            (and:SI (match_dup 1) (const_int 1))))
4320               (clobber (reg:SI T_REG))])])
4322 (define_insn_and_split "*rotcl"
4323   [(set (match_operand:SI 0 "arith_reg_dest")
4324         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4325                            (match_operand:SI 2 "const_int_operand"))
4326                 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4327                              (const_int 31))))
4328    (clobber (reg:SI T_REG))]
4329   "TARGET_SH1"
4330   "#"
4331   "&& can_create_pseudo_p ()"
4332   [(parallel [(set (match_dup 0)
4333                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4334                            (and:SI (reg:SI T_REG) (const_int 1))))
4335               (clobber (reg:SI T_REG))])]
4337   /* We don't care about the result of the left shift, only the T_REG.  */
4338   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4341 (define_insn_and_split "*rotcl"
4342   [(set (match_operand:SI 0 "arith_reg_dest")
4343         (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4344                              (const_int 31))
4345                 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4346                            (match_operand:SI 2 "const_int_operand"))))
4347    (clobber (reg:SI T_REG))]
4348   "TARGET_SH1"
4349   "#"
4350   "&& can_create_pseudo_p ()"
4351   [(parallel [(set (match_dup 0)
4352                    (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4353                            (and:SI (reg:SI T_REG) (const_int 1))))
4354               (clobber (reg:SI T_REG))])]
4356   /* We don't care about the result of the left shift, only the T_REG.  */
4357   emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4360 ;; rotcr combine bridge pattern which will make combine try out more
4361 ;; complex patterns.
4362 (define_insn_and_split "*rotcr"
4363   [(set (match_operand:SI 0 "arith_reg_dest")
4364         (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4365   "TARGET_SH1"
4366   "#"
4367   "&& 1"
4368   [(set (match_dup 0) (match_dup 1))
4369    (parallel [(set (match_dup 0)
4370                    (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4371                            (ashift:SI (match_dup 1) (const_int 31))))
4372               (set (reg:SI T_REG)
4373                    (and:SI (match_dup 0) (const_int 1)))])])
4375 (define_insn_and_split "*rotcr"
4376   [(set (match_operand:SI 0 "arith_reg_dest")
4377         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4378                         (const_int -2147483648)) ;; 0xffffffff80000000
4379                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4380                              (const_int 1))))
4381    (clobber (reg:SI T_REG))]
4382   "TARGET_SH1"
4383   "#"
4384   "&& can_create_pseudo_p ()"
4385   [(const_int 0)]
4387   rtx tmp = gen_reg_rtx (SImode);
4388   emit_insn (gen_shll (tmp, operands[1]));
4389   emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4390   DONE;
4393 ;; rotcr combine patterns for rotating in the negated T_REG value.
4394 (define_insn_and_split "*rotcr_neg_t"
4395   [(set (match_operand:SI 0 "arith_reg_dest")
4396         (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4397                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4398                              (match_operand:SI 3 "const_int_operand"))))
4399    (clobber (reg:SI T_REG))]
4400   "TARGET_SH1"
4401   "#"
4402   "&& can_create_pseudo_p ()"
4403   [(parallel [(set (match_dup 0)
4404                    (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4405                            (ashift:SI (reg:SI T_REG) (const_int 31))))
4406               (clobber (reg:SI T_REG))])]
4408   emit_insn (gen_nott (get_t_reg_rtx ()));
4411 (define_insn_and_split "*rotcr_neg_t"
4412   [(set (match_operand:SI 0 "arith_reg_dest")
4413         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4414                              (match_operand:SI 2 "const_int_operand"))
4415                 (match_operand:SI 3 "negt_reg_shl31_operand")))
4416    (clobber (reg:SI T_REG))]
4417   "TARGET_SH1"
4418   "#"
4419   "&& can_create_pseudo_p ()"
4420   [(parallel [(set (match_dup 0)
4421                    (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4422                            (ashift:SI (reg:SI T_REG) (const_int 31))))
4423               (clobber (reg:SI T_REG))])]
4425   emit_insn (gen_nott (get_t_reg_rtx ()));
4428 ;; rotcl combine patterns for rotating in the negated T_REG value.
4429 ;; For some strange reason these have to be specified as splits which combine
4430 ;; will pick up.  If they are specified as insn_and_split like the
4431 ;; *rotcr_neg_t patterns above, combine would recognize them successfully
4432 ;; but not emit them on non-SH2A targets.
4433 (define_split
4434   [(set (match_operand:SI 0 "arith_reg_dest")
4435         (ior:SI (match_operand:SI 1 "negt_reg_operand")
4436                 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4437                            (match_operand:SI 3 "const_int_operand"))))]
4438   "TARGET_SH1"
4439   [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4440    (parallel [(set (match_dup 0)
4441                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4442                            (and:SI (reg:SI T_REG) (const_int 1))))
4443               (clobber (reg:SI T_REG))])])
4445 (define_split
4446   [(set (match_operand:SI 0 "arith_reg_dest")
4447         (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4448                            (match_operand:SI 3 "const_int_operand"))
4449                 (match_operand:SI 1 "negt_reg_operand")))]
4450   "TARGET_SH1"
4451   [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4452    (parallel [(set (match_dup 0)
4453                    (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4454                            (and:SI (reg:SI T_REG) (const_int 1))))
4455               (clobber (reg:SI T_REG))])])
4457 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4458 ;; SImode shift left
4460 (define_expand "ashlsi3"
4461   [(set (match_operand:SI 0 "arith_reg_operand" "")
4462         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4463                    (match_operand:SI 2 "shift_count_operand" "")))]
4464   ""
4466   if (TARGET_SHMEDIA)
4467     {
4468        if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4469         {
4470           operands[2] = GEN_INT (-INTVAL (operands[2]));
4471           emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4472           DONE;
4473         }
4474       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4475       DONE;
4476     }
4477   if (TARGET_DYNSHIFT
4478       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4479       operands[2] = force_reg (SImode, operands[2]);
4481   /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
4482       expanded here.  */
4483   if (CONST_INT_P (operands[2])
4484       && sh_ashlsi_clobbers_t_reg_p (operands[2])
4485       && ! sh_dynamicalize_shift_p (operands[2]))
4486     {
4487       emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4488                                            operands[2]));
4489       DONE;
4490     }
4492   /* Expand a library call for the dynamic shift.  */
4493   if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4494     {
4495       emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4496       rtx funcaddr = gen_reg_rtx (Pmode);
4497       function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4498       emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4500       DONE;
4501     }
4504 (define_insn "ashlsi3_k"
4505   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4506         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4507                    (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4508   "TARGET_SH1"
4509   "@
4510         add     %0,%0
4511         shll%O2 %0"
4512   [(set_attr "type" "arith")])
4514 (define_insn_and_split "ashlsi3_d"
4515   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4516         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4517                    (match_operand:SI 2 "shift_count_operand" "r")))]
4518   "TARGET_DYNSHIFT"
4519   "shld %2,%0"
4520   "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4521    && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4522   [(const_int 0)]
4524   if (satisfies_constraint_P27 (operands[2]))
4525     {
4526       emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4527       DONE;
4528     }
4529   else if (! satisfies_constraint_P27 (operands[2]))
4530     {
4531       /* This must happen before reload, otherwise the constant will be moved
4532          into a register due to the "r" constraint, after which this split
4533          cannot be done anymore.
4534          Unfortunately the move insn will not always be eliminated.
4535          Also, here we must not create a shift sequence that clobbers the
4536          T_REG.  */
4537       emit_move_insn (operands[0], operands[1]);
4538       gen_shifty_op (ASHIFT, operands);
4539       DONE;
4540     }
4542   FAIL;
4544   [(set_attr "type" "dyn_shift")])
4546 ;; If dynamic shifts are not available use a library function.
4547 ;; By specifying the pattern we reduce the number of call clobbered regs.
4548 ;; In order to make combine understand the truncation of the shift amount
4549 ;; operand we have to allow it to use pseudo regs for the shift operands.
4550 (define_insn "ashlsi3_d_call"
4551   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4552         (ashift:SI (reg:SI R4_REG)
4553                    (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4554                            (const_int 31))))
4555    (use (match_operand:SI 2 "arith_reg_operand" "r"))
4556    (clobber (reg:SI T_REG))
4557    (clobber (reg:SI PR_REG))]
4558   "TARGET_SH1 && !TARGET_DYNSHIFT"
4559   "jsr  @%2%#"
4560   [(set_attr "type" "sfunc")
4561    (set_attr "needs_delay_slot" "yes")])
4563 (define_insn_and_split "ashlsi3_n"
4564   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4565         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4566                    (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4567   "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4568   "#"
4569   "&& (reload_completed
4570        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4571   [(const_int 0)]
4573   if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4574     {
4575       /* If this pattern was picked and dynamic shifts are supported, switch
4576          to dynamic shift pattern before reload.  */
4577       operands[2] = force_reg (SImode, operands[2]);
4578       emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4579     }
4580   else
4581     gen_shifty_op (ASHIFT, operands);
4583   DONE;
4586 (define_insn_and_split "ashlsi3_n_clobbers_t"
4587   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4588         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4589                    (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4590    (clobber (reg:SI T_REG))]
4591   "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4592   "#"
4593   "&& (reload_completed || INTVAL (operands[2]) == 31
4594        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4595   [(const_int 0)]
4597   if (INTVAL (operands[2]) == 31)
4598     {
4599       /* If the shift amount is 31 we split into a different sequence before
4600          reload so that it gets a chance to allocate R0 for the sequence.
4601          If it fails to do so (due to pressure on R0), it will take one insn
4602          more for the and.  */
4603       emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4604       emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4605     }
4606   else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4607     {
4608       /* If this pattern was picked and dynamic shifts are supported, switch
4609          to dynamic shift pattern before reload.  */
4610       operands[2] = force_reg (SImode, operands[2]);
4611       emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4612     }
4613   else
4614     gen_shifty_op (ASHIFT, operands);
4616   DONE;
4619 (define_insn "shll"
4620   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4621         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4622    (set (reg:SI T_REG)
4623         (lt:SI (match_dup 1) (const_int 0)))]
4624   "TARGET_SH1"
4625   "shll %0"
4626   [(set_attr "type" "arith")])
4628 (define_insn "*ashlsi_c_void"
4629   [(set (reg:SI T_REG)
4630         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4631    (clobber (match_scratch:SI 1 "=0"))]
4632   "TARGET_SH1 && cse_not_expected"
4633   "shll %0"
4634   [(set_attr "type" "arith")])
4636 (define_peephole2
4637   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4638    (set (reg:SI T_REG)
4639         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4640   "TARGET_SH1
4641    && peep2_reg_dead_p (2, operands[0])
4642    && peep2_reg_dead_p (2, operands[1])"
4643   [(const_int 0)]
4645   emit_insn (gen_shll (operands[1], operands[1]));
4646   DONE;
4649 (define_insn "ashlsi3_media"
4650   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4651         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4652                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
4653   "TARGET_SHMEDIA"
4654   "@
4655         shlld.l %1, %2, %0
4656         shlli.l %1, %2, %0"
4657   [(set_attr "type" "arith_media")
4658    (set_attr "highpart" "ignore")])
4660 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4661 ;; HImode shift left
4663 (define_expand "ashlhi3"
4664   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4665                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4666                               (match_operand:SI 2 "nonmemory_operand" "")))
4667               (clobber (reg:SI T_REG))])]
4668   "TARGET_SH1"
4670   if (!CONST_INT_P (operands[2]))
4671     FAIL;
4672   /* It may be possible to call gen_ashlhi3 directly with more generic
4673      operands.  Make sure operands[1] is a HImode register here.  */
4674   if (!arith_reg_operand (operands[1], HImode))
4675     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4678 (define_insn "ashlhi3_k"
4679   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4680         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4681                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
4682   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4683   "@
4684         add     %0,%0
4685         shll%O2 %0"
4686   [(set_attr "type" "arith")])
4688 (define_insn_and_split "*ashlhi3_n"
4689   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4690         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4691                    (match_operand:HI 2 "const_int_operand" "n")))
4692    (clobber (reg:SI T_REG))]
4693   "TARGET_SH1"
4694   "#"
4695   "&& reload_completed"
4696   [(use (reg:SI R0_REG))]
4698   gen_shifty_hi_op (ASHIFT, operands);
4699   DONE;
4702 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4703 ;; DImode shift left
4705 (define_expand "ashldi3"
4706   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4707                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4708                               (match_operand:DI 2 "immediate_operand" "")))
4709               (clobber (reg:SI T_REG))])]
4710   ""
4712   if (TARGET_SHMEDIA)
4713     {
4714        if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4715         {
4716           operands[2] = GEN_INT (-INTVAL (operands[2]));
4717           emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4718           DONE;
4719         }
4720       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4721       DONE;
4722     }
4723   if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4724     {
4725       emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4726       DONE;
4727     }
4728   else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4729     {
4730       emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4731       DONE;
4732     }
4733   else
4734     FAIL;
4737 ;; Expander for DImode shift left with SImode operations.
4738 (define_expand "ashldi3_std"
4739   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4740         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4741                    (match_operand:DI 2 "const_int_operand" "n")))]
4742   "TARGET_SH1 && INTVAL (operands[2]) < 32"
4744   rtx low_src = gen_lowpart (SImode, operands[1]);
4745   rtx high_src = gen_highpart (SImode, operands[1]);
4746   rtx dst = gen_reg_rtx (DImode);
4747   rtx low_dst = gen_lowpart (SImode, dst);
4748   rtx high_dst = gen_highpart (SImode, dst);
4749   rtx tmp0 = gen_reg_rtx (SImode);
4750   rtx tmp1 = gen_reg_rtx (SImode);
4752   emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4753   emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
4754   emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
4755   emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4756   emit_move_insn (operands[0], dst);
4757   DONE;
4760 (define_insn_and_split "ashldi3_k"
4761   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4762         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4763                    (const_int 1)))
4764    (clobber (reg:SI T_REG))]
4765   "TARGET_SH1"
4766   "#"
4767   "&& reload_completed"
4768   [(const_int 0)]
4770   rtx high = gen_highpart (SImode, operands[0]);
4771   rtx low = gen_lowpart (SImode, operands[0]);
4772   emit_insn (gen_shll (low, low));
4773   emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4774   DONE;
4777 (define_insn "ashldi3_media"
4778   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4779         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4780                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
4781   "TARGET_SHMEDIA"
4782   "@
4783         shlld   %1, %2, %0
4784         shlli   %1, %2, %0"
4785   [(set_attr "type" "arith_media")])
4787 (define_insn "*ashldisi3_media"
4788   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4789         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4790                    (match_operand:DI 2 "const_int_operand" "n")))]
4791   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4792   "shlli.l      %1, %2, %0"
4793   [(set_attr "type" "arith_media")
4794    (set_attr "highpart" "ignore")])
4796 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4797 ;; SImode arithmetic shift right
4799 ;; We can't do HImode right shifts correctly unless we start out with an
4800 ;; explicit zero / sign extension; doing that would result in worse overall
4801 ;; code, so just let the machine independent code widen the mode.
4802 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4804 (define_expand "ashrsi3"
4805   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4806                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4807                                 (match_operand:SI 2 "nonmemory_operand" "")))
4808               (clobber (reg:SI T_REG))])]
4809   ""
4811   if (TARGET_SHMEDIA)
4812     {
4813       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4814         {
4815           operands[2] = GEN_INT (-INTVAL (operands[2]));
4816           emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4817           DONE;
4818         }
4819       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4820       DONE;
4821     }
4822   if (expand_ashiftrt (operands))
4823     DONE;
4824   else
4825     FAIL;
4828 (define_insn "shar"
4829   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4830         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4831                      (const_int 1)))
4832    (set (reg:SI T_REG)
4833         (and:SI (match_dup 1) (const_int 1)))]
4834   "TARGET_SH1"
4835   "shar %0"
4836   [(set_attr "type" "arith")])
4838 (define_insn "ashrsi3_k"
4839   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4840         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4841                      (match_operand:SI 2 "const_int_operand" "M")))
4842    (clobber (reg:SI T_REG))]
4843   "TARGET_SH1 && INTVAL (operands[2]) == 1"
4844   "shar %0"
4845   [(set_attr "type" "arith")])
4847 (define_insn_and_split "ashrsi2_16"
4848   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4849         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4850                      (const_int 16)))]
4851   "TARGET_SH1"
4852   "#"
4853   "&& 1"
4854   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4855    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4857   operands[2] = gen_lowpart (HImode, operands[0]);
4860 (define_insn_and_split "ashrsi2_31"
4861   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4862         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4863                      (const_int 31)))
4864    (clobber (reg:SI T_REG))]
4865   "TARGET_SH1"
4866   "#"
4867   "&& 1"
4868   [(const_int 0)]
4870   emit_insn (gen_shll (operands[0], operands[1]));
4871   emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
4872   DONE;
4875 (define_insn "ashrsi3_d"
4876   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4877         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4878                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4879   "TARGET_DYNSHIFT"
4880   "shad %2,%0"
4881   [(set_attr "type" "dyn_shift")])
4883 (define_insn "ashrsi3_n"
4884   [(set (reg:SI R4_REG)
4885         (ashiftrt:SI (reg:SI R4_REG)
4886                      (match_operand:SI 0 "const_int_operand" "i")))
4887    (clobber (reg:SI T_REG))
4888    (clobber (reg:SI PR_REG))
4889    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
4890   "TARGET_SH1"
4891   "jsr  @%1%#"
4892   [(set_attr "type" "sfunc")
4893    (set_attr "needs_delay_slot" "yes")])
4895 (define_insn "ashrsi3_media"
4896   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4897         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4898                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
4899   "TARGET_SHMEDIA"
4900   "@
4901         shard.l %1, %2, %0
4902         shari.l %1, %2, %0"
4903   [(set_attr "type" "arith_media")
4904    (set_attr "highpart" "ignore")])
4906 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4907 ;; DImode arithmetic shift right
4909 (define_expand "ashrdi3"
4910   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4911                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4912                                 (match_operand:DI 2 "immediate_operand" "")))
4913               (clobber (reg:SI T_REG))])]
4914   ""
4916   if (TARGET_SHMEDIA)
4917     {
4918       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4919         {
4920           operands[2] = GEN_INT (-INTVAL (operands[2]));
4921           emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4922           DONE;
4923         }
4924       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4925       DONE;
4926     }
4927   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4928     FAIL;
4931 (define_insn_and_split "ashrdi3_k"
4932   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4933         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4934                      (const_int 1)))
4935    (clobber (reg:SI T_REG))]
4936   "TARGET_SH1"
4937   "#"
4938   "&& reload_completed"
4939   [(const_int 0)]
4941   rtx high = gen_highpart (SImode, operands[0]);
4942   rtx low = gen_lowpart (SImode, operands[0]);
4943   emit_insn (gen_shar (high, high));
4944   emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
4945   DONE;
4948 (define_insn "ashrdi3_media"
4949   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4950         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4951                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4952   "TARGET_SHMEDIA
4953    && (arith_reg_dest (operands[0], DImode)
4954        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4955   "@
4956         shard   %1, %2, %0
4957         shari   %1, %2, %0"
4958   [(set_attr "type" "arith_media")])
4960 (define_insn "*ashrdisi3_media"
4961   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4962         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4963                      (match_operand:DI 2 "const_int_operand" "n")))]
4964   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4965   "shari.l      %1, %2, %0"
4966   [(set_attr "type" "arith_media")
4967    (set_attr "highpart" "ignore")])
4969 (define_insn "ashrdisi3_media_high"
4970   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4971         (truncate:SI
4972            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4973                         (match_operand:DI 2 "const_int_operand" "n"))))]
4974   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4975   "shari        %1, %2, %0"
4976   [(set_attr "type" "arith_media")])
4978 (define_insn "ashrdisi3_media_opaque"
4979   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4980         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4981                     (match_operand:DI 2 "const_int_operand" "n")]
4982          UNSPEC_ASHIFTRT))]
4983   "TARGET_SHMEDIA"
4984   "shari        %1, %2, %0"
4985   [(set_attr "type" "arith_media")])
4987 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4988 ;; SImode logical shift right
4990 (define_expand "lshrsi3"
4991   [(set (match_operand:SI 0 "arith_reg_dest" "")
4992         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4993                      (match_operand:SI 2 "shift_count_operand" "")))]
4994   ""
4996   if (TARGET_SHMEDIA)
4997     {
4998       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4999         {
5000           operands[2] = GEN_INT (-INTVAL (operands[2]));
5001           emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5002           DONE;
5003         }
5004       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5005       DONE;
5006     }
5008   /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5009      here, otherwise the pattern will never match due to the shift amount reg
5010      negation.  */
5011   if (TARGET_DYNSHIFT
5012       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5013     {
5014       rtx neg_count = force_reg (SImode,
5015                                  gen_int_mode (- INTVAL (operands[2]), SImode));
5016       emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5017       DONE;
5018     }
5020   if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5021     {
5022       rtx neg_count = gen_reg_rtx (SImode);
5023       emit_insn (gen_negsi2 (neg_count, operands[2]));
5024       emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5025       DONE;
5026     }
5028   /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5029      expanded here.  */
5030   if (CONST_INT_P (operands[2])
5031       && sh_lshrsi_clobbers_t_reg_p (operands[2])
5032       && ! sh_dynamicalize_shift_p (operands[2]))
5033     {
5034       emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5035                  operands[2]));
5036       DONE;
5037     }
5039   /* Expand a library call for the dynamic shift.  */
5040   if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5041     {
5042       emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5043       rtx funcaddr = gen_reg_rtx (Pmode);
5044       function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
5045       emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
5046       DONE;
5047     }
5050 (define_insn "lshrsi3_k"
5051   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5052         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5053                      (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5054   "TARGET_SH1"
5055   "shlr%O2      %0"
5056   [(set_attr "type" "arith")])
5058 (define_insn_and_split "lshrsi3_d"
5059   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5060         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5061                      (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5062   "TARGET_DYNSHIFT"
5063   "shld %2,%0"
5064   "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5065    && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5066   [(const_int 0)]
5068   if (satisfies_constraint_P27 (operands[2]))
5069     {
5070       /* This will not be done for a shift amount of 1, because it would
5071          clobber the T_REG.  */
5072       emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5073       DONE;
5074     }
5075   else if (! satisfies_constraint_P27 (operands[2]))
5076     {
5077       /* This must happen before reload, otherwise the constant will be moved
5078          into a register due to the "r" constraint, after which this split
5079          cannot be done anymore.
5080          Unfortunately the move insn will not always be eliminated.
5081          Also, here we must not create a shift sequence that clobbers the
5082          T_REG.  */
5083       emit_move_insn (operands[0], operands[1]);
5084       gen_shifty_op (LSHIFTRT, operands);
5085       DONE;
5086     }
5088   FAIL;
5090   [(set_attr "type" "dyn_shift")])
5092 ;; If dynamic shifts are not available use a library function.
5093 ;; By specifying the pattern we reduce the number of call clobbered regs.
5094 ;; In order to make combine understand the truncation of the shift amount
5095 ;; operand we have to allow it to use pseudo regs for the shift operands.
5096 (define_insn "lshrsi3_d_call"
5097   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5098         (lshiftrt:SI (reg:SI R4_REG)
5099                      (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5100                              (const_int 31))))
5101    (use (match_operand:SI 2 "arith_reg_operand" "r"))
5102    (clobber (reg:SI T_REG))
5103    (clobber (reg:SI PR_REG))]
5104   "TARGET_SH1 && !TARGET_DYNSHIFT"
5105   "jsr  @%2%#"
5106   [(set_attr "type" "sfunc")
5107    (set_attr "needs_delay_slot" "yes")])
5109 (define_insn_and_split "lshrsi3_n"
5110   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5111         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5112                      (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5113   "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5114   "#"
5115   "&& (reload_completed
5116        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5117   [(const_int 0)]
5119   if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5120     {
5121       /* If this pattern was picked and dynamic shifts are supported, switch
5122          to dynamic shift pattern before reload.  */
5123       operands[2] = force_reg (SImode,
5124                                gen_int_mode (- INTVAL (operands[2]), SImode));
5125       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5126     }
5127   else
5128     gen_shifty_op (LSHIFTRT, operands);
5130   DONE;
5133 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5134 ;; the shlr pattern.
5135 (define_insn_and_split "lshrsi3_n_clobbers_t"
5136   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5137         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5138                      (match_operand:SI 2 "not_p27_rshift_count_operand")))
5139    (clobber (reg:SI T_REG))]
5140   "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5141   "#"
5142   "&& (reload_completed || INTVAL (operands[2]) == 31
5143        || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5144   [(const_int 0)]
5146   if (INTVAL (operands[2]) == 31)
5147     {
5148       emit_insn (gen_shll (operands[0], operands[1]));
5149       emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5150     }
5151   else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5152     {
5153       /* If this pattern was picked and dynamic shifts are supported, switch
5154          to dynamic shift pattern before reload.  */
5155       operands[2] = force_reg (SImode,
5156                                gen_int_mode (- INTVAL (operands[2]), SImode));
5157       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5158     }
5159   else
5160     gen_shifty_op (LSHIFTRT, operands);
5162   DONE;
5165 (define_insn "shlr"
5166   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5167         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5168                      (const_int 1)))
5169    (set (reg:SI T_REG)
5170         (and:SI (match_dup 1) (const_int 1)))]
5171   "TARGET_SH1"
5172   "shlr %0"
5173   [(set_attr "type" "arith")])
5175 (define_insn "lshrsi3_media"
5176   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5177         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5178                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
5179   "TARGET_SHMEDIA"
5180   "@
5181         shlrd.l %1, %2, %0
5182         shlri.l %1, %2, %0"
5183   [(set_attr "type" "arith_media")
5184    (set_attr "highpart" "ignore")])
5186 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5187 ;; DImode logical shift right
5189 (define_expand "lshrdi3"
5190   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5191                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5192                                (match_operand:DI 2 "immediate_operand" "")))
5193              (clobber (reg:SI T_REG))])]
5194   ""
5196   if (TARGET_SHMEDIA)
5197     {
5198       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5199         {
5200           operands[2] = GEN_INT (-INTVAL (operands[2]));
5201           emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5202           DONE;
5203         }
5204       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5205       DONE;
5206     }
5207   if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5208     FAIL;
5211 (define_insn_and_split "lshrdi3_k"
5212   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5213         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5214                      (const_int 1)))
5215    (clobber (reg:SI T_REG))]
5216   "TARGET_SH1"
5217   "#"
5218   "&& reload_completed"
5219   [(const_int 0)]
5221   rtx high = gen_highpart (SImode, operands[0]);
5222   rtx low = gen_lowpart (SImode, operands[0]);
5223   emit_insn (gen_shlr (high, high));
5224   emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5225   DONE;
5228 (define_insn "lshrdi3_media"
5229   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5230         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5231                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
5232   "TARGET_SHMEDIA
5233    && (arith_reg_dest (operands[0], DImode)
5234        || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5235   "@
5236         shlrd   %1, %2, %0
5237         shlri   %1, %2, %0"
5238   [(set_attr "type" "arith_media")])
5240 (define_insn "*lshrdisi3_media"
5241   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5242         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5243                      (match_operand:DI 2 "const_int_operand" "n")))]
5244   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5245   "shlri.l      %1, %2, %0"
5246   [(set_attr "type" "arith_media")
5247    (set_attr "highpart" "ignore")])
5249 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5250 ;; Combined left/right shifts
5252 (define_split
5253   [(set (match_operand:SI 0 "register_operand" "")
5254         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5255                            (match_operand:SI 2 "const_int_operand" ""))
5256                 (match_operand:SI 3 "const_int_operand" "")))]
5257   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5258   [(use (reg:SI R0_REG))]
5260   if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5261     FAIL;
5262   DONE;
5265 (define_split
5266   [(set (match_operand:SI 0 "register_operand" "")
5267         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5268                            (match_operand:SI 2 "const_int_operand" ""))
5269                 (match_operand:SI 3 "const_int_operand" "")))
5270    (clobber (reg:SI T_REG))]
5271   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5272   [(use (reg:SI R0_REG))]
5274   if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5275     FAIL;
5276   DONE;
5279 (define_insn ""
5280   [(set (match_operand:SI 0 "register_operand" "=r")
5281         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5282                            (match_operand:SI 2 "const_int_operand" "n"))
5283                 (match_operand:SI 3 "const_int_operand" "n")))
5284    (clobber (reg:SI T_REG))]
5285   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5286   "#"
5287   [(set (attr "length")
5288         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5289                (const_string "4")
5290                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5291                (const_string "6")
5292                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5293                (const_string "8")
5294                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5295                (const_string "10")
5296                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5297                (const_string "12")
5298                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5299                (const_string "14")
5300                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5301                (const_string "16")]
5302               (const_string "18")))
5303    (set_attr "type" "arith")])
5305 (define_insn ""
5306   [(set (match_operand:SI 0 "register_operand" "=z")
5307         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5308                            (match_operand:SI 2 "const_int_operand" "n"))
5309                 (match_operand:SI 3 "const_int_operand" "n")))
5310    (clobber (reg:SI T_REG))]
5311   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5312   "#"
5313   [(set (attr "length")
5314         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5315                (const_string "4")
5316                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5317                (const_string "6")
5318                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5319                (const_string "8")]
5320               (const_string "10")))
5321    (set_attr "type" "arith")])
5323 ;; shift left / and combination with a scratch register: The combine pass
5324 ;; does not accept the individual instructions, even though they are
5325 ;; cheap.  But it needs a precise description so that it is usable after
5326 ;; reload.
5327 (define_insn "and_shl_scratch"
5328   [(set (match_operand:SI 0 "register_operand" "=r,&r")
5329         (lshiftrt:SI
5330          (ashift:SI
5331           (and:SI
5332            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5333                         (match_operand:SI 2 "const_int_operand" "N,n"))
5334            (match_operand:SI 3 "" "0,r"))
5335           (match_operand:SI 4 "const_int_operand" "n,n"))
5336          (match_operand:SI 5 "const_int_operand" "n,n")))
5337    (clobber (reg:SI T_REG))]
5338   "TARGET_SH1"
5339   "#"
5340   [(set (attr "length")
5341         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5342                (const_string "4")
5343                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5344                (const_string "6")
5345                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5346                (const_string "8")
5347                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5348                (const_string "10")]
5349               (const_string "12")))
5350    (set_attr "type" "arith")])
5352 (define_split
5353   [(set (match_operand:SI 0 "register_operand" "")
5354         (lshiftrt:SI
5355          (ashift:SI
5356           (and:SI
5357            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5358                         (match_operand:SI 2 "const_int_operand" ""))
5359            (match_operand:SI 3 "register_operand" ""))
5360           (match_operand:SI 4 "const_int_operand" ""))
5361          (match_operand:SI 5 "const_int_operand" "")))
5362    (clobber (reg:SI T_REG))]
5363   "TARGET_SH1"
5364   [(use (reg:SI R0_REG))]
5366   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5368   if (INTVAL (operands[2]))
5369     {
5370       gen_shifty_op (LSHIFTRT, operands);
5371     }
5372   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5373   operands[2] = operands[4];
5374   gen_shifty_op (ASHIFT, operands);
5375   if (INTVAL (operands[5]))
5376     {
5377       operands[2] = operands[5];
5378       gen_shifty_op (LSHIFTRT, operands);
5379     }
5380   DONE;
5383 ;; signed left/right shift combination.
5384 (define_split
5385   [(set (match_operand:SI 0 "register_operand" "")
5386         (sign_extract:SI
5387          (ashift:SI (match_operand:SI 1 "register_operand" "")
5388                     (match_operand:SI 2 "const_int_operand" ""))
5389          (match_operand:SI 3 "const_int_operand" "")
5390          (const_int 0)))
5391    (clobber (reg:SI T_REG))]
5392   "TARGET_SH1"
5393   [(use (reg:SI R0_REG))]
5395   if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5396     FAIL;
5397   DONE;
5400 (define_insn "shl_sext_ext"
5401   [(set (match_operand:SI 0 "register_operand" "=r")
5402         (sign_extract:SI
5403          (ashift:SI (match_operand:SI 1 "register_operand" "0")
5404                     (match_operand:SI 2 "const_int_operand" "n"))
5405          (match_operand:SI 3 "const_int_operand" "n")
5406          (const_int 0)))
5407    (clobber (reg:SI T_REG))]
5408   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5409   "#"
5410   [(set (attr "length")
5411         (cond [(match_test "shl_sext_length (insn)")
5412                (const_string "2")
5413                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5414                (const_string "4")
5415                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5416                (const_string "6")
5417                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5418                (const_string "8")
5419                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5420                (const_string "10")
5421                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5422                (const_string "12")
5423                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5424                (const_string "14")
5425                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5426                (const_string "16")]
5427               (const_string "18")))
5428     (set_attr "type" "arith")])
5430 (define_insn "shl_sext_sub"
5431   [(set (match_operand:SI 0 "register_operand" "=z")
5432         (sign_extract:SI
5433          (ashift:SI (match_operand:SI 1 "register_operand" "0")
5434                     (match_operand:SI 2 "const_int_operand" "n"))
5435          (match_operand:SI 3 "const_int_operand" "n")
5436          (const_int 0)))
5437    (clobber (reg:SI T_REG))]
5438   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5439   "#"
5440   [(set (attr "length")
5441         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5442                (const_string "6")
5443                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5444                (const_string "8")
5445                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5446                (const_string "10")
5447                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5448                (const_string "12")]
5449               (const_string "14")))
5450     (set_attr "type" "arith")])
5452 ;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5453 ;; shifts by 16, and allow the xtrct instruction to be generated from C
5454 ;; source.
5455 (define_insn "xtrct_left"
5456   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5457         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5458                            (const_int 16))
5459                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5460                              (const_int 16))))]
5461   "TARGET_SH1"
5462   "xtrct        %1,%0"
5463   [(set_attr "type" "arith")])
5465 (define_insn "xtrct_right"
5466   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5467         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5468                              (const_int 16))
5469                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5470                            (const_int 16))))]
5471   "TARGET_SH1"
5472   "xtrct        %2,%0"
5473   [(set_attr "type" "arith")])
5475 ;; -------------------------------------------------------------------------
5476 ;; Unary arithmetic
5477 ;; -------------------------------------------------------------------------
5479 (define_insn "negc"
5480   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5481         (neg:SI (plus:SI (reg:SI T_REG)
5482                          (match_operand:SI 1 "arith_reg_operand" "r"))))
5483    (set (reg:SI T_REG)
5484         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5485                (const_int 0)))]
5486   "TARGET_SH1"
5487   "negc %1,%0"
5488   [(set_attr "type" "arith")])
5490 ;; A simplified version of the negc insn, where the exact value of the
5491 ;; T bit doesn't matter.  This is easier for combine to pick up.
5492 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5493 ;; extra patterns for this case.
5494 (define_insn "*negc"
5495   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5496         (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5497                   (match_operand:SI 2 "t_reg_operand" "")))
5498    (clobber (reg:SI T_REG))]
5499   "TARGET_SH1"
5500   "negc %1,%0"
5501   [(set_attr "type" "arith")])
5503 (define_insn "*negdi_media"
5504   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5505         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5506   "TARGET_SHMEDIA"
5507   "sub  r63, %1, %0"
5508   [(set_attr "type" "arith_media")])
5510 ;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
5511 ;; can be combined.
5512 (define_expand "negdi2"
5513   [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5514                    (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5515               (clobber (reg:SI T_REG))])]
5516   "TARGET_SH1")
5518 (define_insn_and_split "*negdi2"
5519   [(set (match_operand:DI 0 "arith_reg_dest")
5520         (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5521    (clobber (reg:SI T_REG))]
5522   "TARGET_SH1"
5523   "#"
5524   "&& can_create_pseudo_p ()"
5525   [(const_int 0)]
5527   emit_insn (gen_clrt ());
5528   emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5529                        gen_lowpart (SImode, operands[1])));
5530   emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5531                        gen_highpart (SImode, operands[1])));
5532   DONE;
5535 (define_insn "negsi2"
5536   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5537         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5538   "TARGET_SH1"
5539   "neg  %1,%0"
5540   [(set_attr "type" "arith")])
5542 (define_insn_and_split "one_cmplsi2"
5543   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5544         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5545   "TARGET_SH1"
5546   "not  %1,%0"
5547   "&& can_create_pseudo_p ()"
5548   [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5549    (set (match_dup 0) (reg:SI T_REG))]
5551 /* PR 54685
5552    If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5553    sequence:
5555      (set (reg0) (not:SI (reg0) (reg1)))
5556      (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5557                 (clobber (reg:SI T_REG))])
5559    ... match and combine the sequence manually in the split pass after the
5560    combine pass.  Notice that combine does try the target pattern of this
5561    split, but if the pattern is added it interferes with other patterns, in
5562    particular with the div0s comparisons.
5563    This could also be done with a peephole but doing it here before register
5564    allocation can save one temporary.
5565    When we're here, the not:SI pattern obviously has been matched already
5566    and we only have to see whether the following insn is the left shift.  */
5568   rtx i = next_nonnote_insn_bb (curr_insn);
5569   if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5570     FAIL;
5572   rtx p = PATTERN (i);
5573   if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5574     FAIL;
5576   rtx p0 = XVECEXP (p, 0, 0);
5577   rtx p1 = XVECEXP (p, 0, 1);
5579   if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
5580       GET_CODE (p0) == SET
5581       && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5582       && REG_P (XEXP (XEXP (p0, 1), 0))
5583       && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5584       && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5585       && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5587       /* (clobber (reg:SI T_REG))  */
5588       && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5589       && REGNO (XEXP (p1, 0)) == T_REG)
5590     {
5591       operands[0] = XEXP (p0, 0);
5592       set_insn_deleted (i);
5593     }
5594   else
5595     FAIL;
5597   [(set_attr "type" "arith")])
5599 (define_expand "one_cmpldi2"
5600   [(set (match_operand:DI 0 "arith_reg_dest" "")
5601         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5602                 (const_int -1)))]
5603   "TARGET_SHMEDIA" "")
5605 (define_expand "abs<mode>2"
5606   [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5607                    (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5608               (clobber (reg:SI T_REG))])]
5609   "TARGET_SH1")
5611 (define_insn_and_split "*abs<mode>2"
5612   [(set (match_operand:SIDI 0 "arith_reg_dest")
5613         (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5614    (clobber (reg:SI T_REG))]
5615   "TARGET_SH1"
5616   "#"
5617   "&& can_create_pseudo_p ()"
5618   [(const_int 0)]
5620   if (<MODE>mode == SImode)
5621     emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5622   else
5623     {
5624       rtx high_src = gen_highpart (SImode, operands[1]);
5625       emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5626     }
5628   emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5629                                  const1_rtx));
5630   DONE;
5633 (define_insn_and_split "*negabs<mode>2"
5634   [(set (match_operand:SIDI 0 "arith_reg_dest")
5635         (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5636    (clobber (reg:SI T_REG))]
5637   "TARGET_SH1"
5638   "#"
5639   "&& can_create_pseudo_p ()"
5640   [(const_int 0)]
5642   if (<MODE>mode == SImode)
5643     emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5644   else
5645     {
5646       rtx high_src = gen_highpart (SImode, operands[1]);
5647       emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5648     }
5650   emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5651                                  const0_rtx));
5652   DONE;
5655 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
5656 ;; This can be used as some kind of conditional execution, which is useful
5657 ;; for abs.
5658 ;; Actually the instruction scheduling should decide whether to use a
5659 ;; zero-offset branch or not for any generic case involving a single
5660 ;; instruction on SH4 202.
5661 (define_insn_and_split "negsi_cond"
5662   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5663         (if_then_else
5664           (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5665           (match_operand:SI 1 "arith_reg_operand" "0,0")
5666           (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5667   "TARGET_SH1 && TARGET_ZDCBRANCH"
5669   static const char* alt[] =
5670   {
5671        "bt      0f"     "\n"
5672     "   neg     %2,%0"  "\n"
5673     "0:",
5675        "bf      0f"     "\n"
5676     "   neg     %2,%0"  "\n"
5677     "0:"
5678   };
5679   return alt[which_alternative];
5681   "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5682   [(const_int 0)]
5684   rtx skip_neg_label = gen_label_rtx ();
5686   emit_move_insn (operands[0], operands[1]);
5688   emit_jump_insn (INTVAL (operands[3])
5689                   ? gen_branch_true (skip_neg_label)
5690                   : gen_branch_false (skip_neg_label));
5692   emit_label_after (skip_neg_label,
5693                     emit_insn (gen_negsi2 (operands[0], operands[1])));
5694   DONE;
5696   [(set_attr "type" "arith") ;; poor approximation
5697    (set_attr "length" "4")])
5699 (define_insn_and_split "negdi_cond"
5700   [(set (match_operand:DI 0 "arith_reg_dest")
5701         (if_then_else
5702           (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5703           (match_operand:DI 1 "arith_reg_operand")
5704           (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5705    (clobber (reg:SI T_REG))]
5706   "TARGET_SH1"
5707   "#"
5708   "&& can_create_pseudo_p ()"
5709   [(const_int 0)]
5711   rtx skip_neg_label = gen_label_rtx ();
5713   emit_move_insn (operands[0], operands[1]);
5715   emit_jump_insn (INTVAL (operands[3]) 
5716                   ? gen_branch_true (skip_neg_label)
5717                   : gen_branch_false (skip_neg_label));
5719   if (!INTVAL (operands[3]))
5720     emit_insn (gen_clrt ());
5722   emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5723                        gen_lowpart (SImode, operands[1])));
5724   emit_label_after (skip_neg_label,
5725                     emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5726                                          gen_highpart (SImode, operands[1]))));
5727   DONE;
5730 (define_expand "bswapsi2"
5731   [(set (match_operand:SI 0 "arith_reg_dest" "")
5732         (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5733   "TARGET_SH1"
5735   if (! can_create_pseudo_p ())
5736     FAIL;
5737   else
5738     {
5739       rtx tmp0 = gen_reg_rtx (SImode);
5740       rtx tmp1 = gen_reg_rtx (SImode);
5742       emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5743       emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5744       emit_insn (gen_swapbsi2 (operands[0], tmp1));
5745       DONE;
5746     }
5749 (define_insn "swapbsi2"
5750   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5751         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5752                         (const_int -65536)) ;; 0xFFFF0000
5753                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5754                                 (const_int 65280))
5755                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5756                                 (const_int 255)))))]
5757   "TARGET_SH1"
5758   "swap.b       %1,%0"
5759   [(set_attr "type" "arith")])
5761 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5762 ;; partial byte swap expressions such as...
5763 ;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5764 ;; ...which are currently not handled by the tree optimizers.
5765 ;; The combine pass will not initially try to combine the full expression,
5766 ;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
5767 ;; pattern acts as an intermediate pattern that will eventually lead combine
5768 ;; to the swapbsi2 pattern above.
5769 ;; As a side effect this also improves code that does (x & 0xFF) << 8
5770 ;; or (x << 8) & 0xFF00.
5771 (define_insn_and_split "*swapbisi2_and_shl8"
5772   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5773         (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5774                                    (const_int 8))
5775                         (const_int 65280))
5776                 (match_operand:SI 2 "arith_reg_operand" "r")))]
5777   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5778   "#"
5779   "&& can_create_pseudo_p ()"
5780   [(const_int 0)]
5782   rtx tmp0 = gen_reg_rtx (SImode);
5783   rtx tmp1 = gen_reg_rtx (SImode);
5785   emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5786   emit_insn (gen_swapbsi2 (tmp1, tmp0));
5787   emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5788   DONE;
5791 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5792 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5793 (define_insn_and_split "*swapbhisi2"
5794   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5795         (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5796                                    (const_int 8))
5797                         (const_int 65280))
5798                 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5799   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5800   "#"
5801   "&& can_create_pseudo_p ()"
5802   [(const_int 0)]
5804   rtx tmp = gen_reg_rtx (SImode);
5806   emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5807   emit_insn (gen_swapbsi2 (operands[0], tmp));
5808   DONE;
5811 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
5812 ;;   swap.b  r4,r4
5813 ;;   mov     r4,r0
5815 ;; which can be simplified to...
5816 ;;   swap.b  r4,r0
5817 (define_peephole2
5818   [(set (match_operand:SI 0 "arith_reg_dest" "")
5819         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5820                         (const_int -65536)) ;; 0xFFFF0000
5821                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5822                                 (const_int 65280))
5823                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5824                                 (const_int 255)))))
5825    (set (match_operand:SI 2 "arith_reg_dest" "")
5826         (match_dup 0))]
5827   "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5828   [(set (match_dup 2)
5829         (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5830                         (const_int -65536)) ;; 0xFFFF0000
5831                 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5832                                 (const_int 65280))
5833                         (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5834                                 (const_int 255)))))])
5836 ;; -------------------------------------------------------------------------
5837 ;; Zero extension instructions
5838 ;; -------------------------------------------------------------------------
5840 (define_insn "zero_extendsidi2"
5841   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5842         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5843   "TARGET_SHMEDIA"
5844   "addz.l       %1, r63, %0"
5845   [(set_attr "type" "arith_media")
5846    (set_attr "highpart" "extend")])
5848 (define_insn "zero_extendhidi2"
5849   [(set (match_operand:DI 0 "register_operand" "=r,r")
5850         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5851   "TARGET_SHMEDIA"
5852   "@
5853         #
5854         ld%M1.uw        %m1, %0"
5855   [(set_attr "type" "*,load_media")
5856    (set (attr "highpart")
5857         (cond [(match_test "sh_contains_memref_p (insn)")
5858                (const_string "user")]
5859               (const_string "ignore")))])
5861 (define_split
5862   [(set (match_operand:DI 0 "register_operand" "")
5863         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5864   "TARGET_SHMEDIA && reload_completed"
5865   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5866    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
5868   if (GET_CODE (operands[1]) == TRUNCATE)
5869     operands[1] = XEXP (operands[1], 0);
5872 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
5873 ;; reload the entire truncate expression.
5874 (define_insn_and_split "*loaddi_trunc"
5875   [(set (match_operand 0 "any_register_operand" "=r")
5876         (truncate (match_operand:DI 1 "memory_operand" "m")))]
5877   "TARGET_SHMEDIA && reload_completed"
5878   "#"
5879   "TARGET_SHMEDIA && reload_completed"
5880   [(set (match_dup 0) (match_dup 1))]
5882   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5885 (define_insn "zero_extendqidi2"
5886   [(set (match_operand:DI 0 "register_operand" "=r,r")
5887         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5888   "TARGET_SHMEDIA"
5889   "@
5890         andi    %1, 255, %0
5891         ld%M1.ub        %m1, %0"
5892   [(set_attr "type" "arith_media,load_media")
5893    (set (attr "highpart")
5894         (cond [(match_test "sh_contains_memref_p (insn)")
5895                (const_string "user")]
5896               (const_string "ignore")))])
5898 (define_expand "zero_extend<mode>si2"
5899   [(set (match_operand:SI 0 "arith_reg_dest")
5900         (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
5902 (define_insn_and_split "*zero_extend<mode>si2_compact"
5903   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5904         (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5905   "TARGET_SH1"
5906   "extu.<bw>    %1,%0"
5907   "&& can_create_pseudo_p ()"
5908   [(set (match_dup 0) (match_dup 2))]
5910   /* Sometimes combine fails to combine a T bit or negated T bit store to a
5911      reg with a following zero extension.  In the split pass after combine,
5912      try to figure out how the extended reg was set.  If it originated from
5913      the T bit we can replace the zero extension with a reg move, which will
5914      be eliminated.  Notice that this also helps the *cbranch_t splitter when
5915      it tries to post-combine tests and conditional branches, as it does not
5916      check for zero extensions.  */
5917   operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5918   if (operands[2] == NULL_RTX)
5919     FAIL;
5921   [(set_attr "type" "arith")])
5923 (define_insn "*zero_extendhisi2_media"
5924   [(set (match_operand:SI 0 "register_operand" "=r,r")
5925         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5926   "TARGET_SHMEDIA"
5927   "@
5928         #
5929         ld%M1.uw        %m1, %0"
5930   [(set_attr "type" "arith_media,load_media")
5931    (set (attr "highpart")
5932         (cond [(match_test "sh_contains_memref_p (insn)")
5933                (const_string "user")]
5934               (const_string "ignore")))])
5936 (define_split
5937   [(set (match_operand:SI 0 "register_operand" "")
5938         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
5939   "TARGET_SHMEDIA && reload_completed"
5940   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5941    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5943   rtx op1 = operands[1];
5945   if (GET_CODE (op1) == TRUNCATE)
5946     op1 = XEXP (op1, 0);
5947   operands[2]
5948     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5949                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
5952 (define_insn "*zero_extendqisi2_media"
5953   [(set (match_operand:SI 0 "register_operand" "=r,r")
5954         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5955   "TARGET_SHMEDIA"
5956   "@
5957         andi    %1, 255, %0
5958         ld%M1.ub        %m1, %0"
5959   [(set_attr "type" "arith_media,load_media")
5960    (set (attr "highpart")
5961         (cond [(match_test "sh_contains_memref_p (insn)")
5962                (const_string "user")]
5963               (const_string "ignore")))])
5965 (define_insn "zero_extendqihi2"
5966   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5967         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
5968   "TARGET_SH1"
5969   "extu.b       %1,%0"
5970   [(set_attr "type" "arith")])
5972 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
5973 ;; They could also be used for simple memory addresses like @Rn by setting
5974 ;; the displacement value to zero.  However, doing so too early results in
5975 ;; missed opportunities for other optimizations such as post-inc or index
5976 ;; addressing loads.
5977 ;; Although the 'zero_extend_movu_operand' predicate does not allow simple
5978 ;; register addresses (an address without a displacement, index, post-inc),
5979 ;; zero-displacement addresses might be generated during reload, wich are
5980 ;; simplified to simple register addresses in turn.  Thus, we have to
5981 ;; provide the Sdd and Sra alternatives in the patterns.
5982 (define_insn "*zero_extend<mode>si2_disp_mem"
5983   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5984         (zero_extend:SI
5985           (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
5986   "TARGET_SH2A"
5987   "@
5988         movu.<bw>       %1,%0
5989         movu.<bw>       @(0,%t1),%0"
5990   [(set_attr "type" "load")
5991    (set_attr "length" "4")])
5993 ;; Convert the zero extending loads in sequences such as:
5994 ;;      movu.b  @(1,r5),r0      movu.w  @(2,r5),r0
5995 ;;      mov.b   r0,@(1,r4)      mov.b   r0,@(1,r4)
5997 ;; back to sign extending loads like:
5998 ;;      mov.b   @(1,r5),r0      mov.w   @(2,r5),r0
5999 ;;      mov.b   r0,@(1,r4)      mov.b   r0,@(1,r4)
6001 ;; if the extension type is irrelevant.  The sign extending mov.{b|w} insn
6002 ;; is only 2 bytes in size if the displacement is {K04|K05}.
6003 ;; If the displacement is greater it doesn't matter, so we convert anyways.
6004 (define_peephole2
6005   [(set (match_operand:SI 0 "arith_reg_dest" "")
6006         (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6007    (set (match_operand 2 "nonimmediate_operand" "")
6008         (match_operand 3 "arith_reg_operand" ""))]
6009   "TARGET_SH2A
6010    && REGNO (operands[0]) == REGNO (operands[3])
6011    && peep2_reg_dead_p (2, operands[0])
6012    && GET_MODE_SIZE (GET_MODE (operands[2]))
6013       <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6014   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6015    (set (match_dup 2) (match_dup 3))])
6017 ;; Fold sequences such as
6018 ;;      mov.b   @r3,r7
6019 ;;      extu.b  r7,r7
6020 ;; into
6021 ;;      movu.b  @(0,r3),r7
6022 ;; This does not reduce the code size but the number of instructions is
6023 ;; halved, which results in faster code.
6024 (define_peephole2
6025   [(set (match_operand:SI 0 "arith_reg_dest" "")
6026         (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6027    (set (match_operand:SI 2 "arith_reg_dest" "")
6028         (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6029   "TARGET_SH2A
6030    && GET_MODE (operands[1]) == GET_MODE (operands[3])
6031    && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6032    && REGNO (operands[0]) == REGNO (operands[3])
6033    && (REGNO (operands[2]) == REGNO (operands[0])
6034        || peep2_reg_dead_p (2, operands[0]))"
6035   [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6037   operands[4]
6038     = replace_equiv_address (operands[1],
6039                              gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6040                                            const0_rtx));
6043 ;; -------------------------------------------------------------------------
6044 ;; Sign extension instructions
6045 ;; -------------------------------------------------------------------------
6047 ;; ??? This should be a define expand.
6048 ;; ??? Or perhaps it should be dropped?
6050 ;; convert_move generates good code for SH[1-4].
6051 (define_insn "extendsidi2"
6052   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6053         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6054   "TARGET_SHMEDIA"
6055   "@
6056         add.l   %1, r63, %0
6057         ld%M1.l %m1, %0
6058         fmov.sl %1, %0"
6059   [(set_attr "type" "arith_media,load_media,fpconv_media")
6060    (set (attr "highpart")
6061         (cond [(match_test "sh_contains_memref_p (insn)")
6062                (const_string "user")]
6063               (const_string "extend")))])
6065 (define_insn "extendhidi2"
6066   [(set (match_operand:DI 0 "register_operand" "=r,r")
6067         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6068   "TARGET_SHMEDIA"
6069   "@
6070         #
6071         ld%M1.w %m1, %0"
6072   [(set_attr "type" "*,load_media")
6073    (set (attr "highpart")
6074         (cond [(match_test "sh_contains_memref_p (insn)")
6075                (const_string "user")]
6076               (const_string "ignore")))])
6078 (define_split
6079   [(set (match_operand:DI 0 "register_operand" "")
6080         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6081   "TARGET_SHMEDIA && reload_completed"
6082   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6083    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6085   if (GET_CODE (operands[1]) == TRUNCATE)
6086     operands[1] = XEXP (operands[1], 0);
6089 (define_insn "extendqidi2"
6090   [(set (match_operand:DI 0 "register_operand" "=r,r")
6091         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6092   "TARGET_SHMEDIA"
6093   "@
6094         #
6095         ld%M1.b %m1, %0"
6096   [(set_attr "type" "*,load_media")
6097    (set (attr "highpart")
6098         (cond [(match_test "sh_contains_memref_p (insn)")
6099                (const_string "user")]
6100               (const_string "ignore")))])
6102 (define_split
6103   [(set (match_operand:DI 0 "register_operand" "")
6104         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6105   "TARGET_SHMEDIA && reload_completed"
6106   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6107    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6109   if (GET_CODE (operands[1]) == TRUNCATE)
6110     operands[1] = XEXP (operands[1], 0);
6113 (define_expand "extend<mode>si2"
6114   [(set (match_operand:SI 0 "arith_reg_dest")
6115         (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6117 (define_insn "*extendhisi2_media"
6118   [(set (match_operand:SI 0 "register_operand" "=r,r")
6119         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6120   "TARGET_SHMEDIA"
6121   "@
6122         #
6123         ld%M1.w %m1, %0"
6124   [(set_attr "type" "arith_media,load_media")
6125    (set (attr "highpart")
6126         (cond [(match_test "sh_contains_memref_p (insn)")
6127                (const_string "user")]
6128               (const_string "ignore")))])
6130 (define_split
6131   [(set (match_operand:SI 0 "register_operand" "")
6132         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6133   "TARGET_SHMEDIA && reload_completed"
6134   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6135    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6137   rtx op1 = operands[1];
6138   if (GET_CODE (op1) == TRUNCATE)
6139     op1 = XEXP (op1, 0);
6140   operands[2]
6141     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6142                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6145 (define_insn_and_split "*extend<mode>si2_compact_reg"
6146   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6147         (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6148   "TARGET_SH1"
6149   "exts.<bw>    %1,%0"
6150   "&& can_create_pseudo_p ()"
6151   [(set (match_dup 0) (match_dup 2))]
6153   /* Sometimes combine fails to combine a T bit or negated T bit store to a
6154      reg with a following sign extension.  In the split pass after combine,
6155      try to figure the extended reg was set.  If it originated from the T
6156      bit we can replace the sign extension with a reg move, which will be
6157      eliminated.  */
6158   operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6159   if (operands[2] == NULL_RTX)
6160     FAIL;
6162   [(set_attr "type" "arith")])
6164 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6165 ;; See movqi insns.
6166 (define_insn "*extend<mode>si2_compact_mem_disp"
6167   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6168         (sign_extend:SI
6169           (mem:QIHI
6170             (plus:SI
6171               (match_operand:SI 1 "arith_reg_operand" "%r,r")
6172               (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6173   "TARGET_SH1 && ! TARGET_SH2A
6174    && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6175   "@
6176         mov.<bw>        @(%O2,%1),%0
6177         mov.<bw>        @%1,%0"
6178   [(set_attr "type" "load")])
6180 (define_insn "*extend<mode>si2_compact_mem_disp"
6181   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6182         (sign_extend:SI
6183           (mem:QIHI
6184             (plus:SI
6185               (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6186               (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6187   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6188   "@
6189         mov.<bw>        @(%O2,%1),%0
6190         mov.<bw>        @%1,%0
6191         mov.<bw>        @(%O2,%1),%0"
6192   [(set_attr "type" "load")
6193    (set_attr "length" "2,2,4")])
6195 ;; The *_snd patterns will take care of other QImode/HImode addressing
6196 ;; modes than displacement addressing.  They must be defined _after_ the
6197 ;; displacement addressing patterns.  Otherwise the displacement addressing
6198 ;; patterns will not be picked.
6199 (define_insn "*extend<mode>si2_compact_snd"
6200   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6201         (sign_extend:SI
6202           (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6203   "TARGET_SH1"
6204   "mov.<bw>     %1,%0"
6205   [(set_attr "type" "load")])
6207 (define_insn "*extendqisi2_media"
6208   [(set (match_operand:SI 0 "register_operand" "=r,r")
6209         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6210   "TARGET_SHMEDIA"
6211   "@
6212         #
6213         ld%M1.b %m1, %0"
6214   [(set_attr "type" "arith_media,load_media")
6215    (set (attr "highpart")
6216         (cond [(match_test "sh_contains_memref_p (insn)")
6217                (const_string "user")]
6218               (const_string "ignore")))])
6220 (define_split
6221   [(set (match_operand:SI 0 "register_operand" "")
6222         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6223   "TARGET_SHMEDIA && reload_completed"
6224   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6225    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6227   rtx op1 = operands[1];
6228   if (GET_CODE (op1) == TRUNCATE)
6229     op1 = XEXP (op1, 0);
6230   operands[2]
6231     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6232                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
6235 (define_expand "extendqihi2"
6236   [(set (match_operand:HI 0 "arith_reg_dest")
6237         (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))]
6238   "TARGET_SH1")
6240 (define_insn "*extendqihi2_compact_reg"
6241   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6242         (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6243   "TARGET_SH1"
6244   "exts.b       %1,%0"
6245   [(set_attr "type" "arith")])
6247 ;; It would seem useful to combine the truncXi patterns into the movXi
6248 ;; patterns, but unary operators are ignored when matching constraints,
6249 ;; so we need separate patterns.
6250 (define_insn "truncdisi2"
6251   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6252         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6253   "TARGET_SHMEDIA"
6254   "@
6255         add.l   %1, r63, %0
6256         st%M0.l %m0, %1
6257         fst%M0.s        %m0, %T1
6258         fmov.ls %1, %0
6259         fmov.sl %T1, %0
6260         fmov.s  %T1, %0"
6261   [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6262                      fpconv_media,fmove_media")
6263    (set (attr "highpart")
6264         (cond [(match_test "sh_contains_memref_p (insn)")
6265                (const_string "user")]
6266               (const_string "extend")))])
6268 (define_insn "truncdihi2"
6269   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6270         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6271   "TARGET_SHMEDIA"
6273   static const char* alt[] =
6274   {
6275        "shlli   %1,48,%0"       "\n"
6276     "   shlri   %0,48,%0",
6278        "st%M0.w %m0, %1"
6279   };
6280   return alt[which_alternative];
6282   [(set_attr "type"   "arith_media,store_media")
6283    (set_attr "length" "8,4")
6284    (set (attr "highpart")
6285         (cond [(match_test "sh_contains_memref_p (insn)")
6286                (const_string "user")]
6287               (const_string "extend")))])
6289 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6290 ; Because we use zero extension, we can't provide signed QImode compares
6291 ; using a simple compare or conditional branch insn.
6292 (define_insn "truncdiqi2"
6293   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6294         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6295   "TARGET_SHMEDIA"
6296   "@
6297         andi    %1, 255, %0
6298         st%M0.b %m0, %1"
6299   [(set_attr "type"   "arith_media,store")
6300    (set (attr "highpart")
6301         (cond [(match_test "sh_contains_memref_p (insn)")
6302                (const_string "user")]
6303               (const_string "extend")))])
6305 ;; -------------------------------------------------------------------------
6306 ;; Move instructions
6307 ;; -------------------------------------------------------------------------
6309 ;; define push and pop so it is easy for sh.c
6310 ;; We can't use push and pop on SHcompact because the stack must always
6311 ;; be 8-byte aligned.
6312 (define_expand "push"
6313   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6314         (match_operand:SI 0 "register_operand" "r,l,x"))]
6315   "TARGET_SH1 && ! TARGET_SH5"
6316   "")
6318 (define_expand "pop"
6319   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6320         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6321   "TARGET_SH1 && ! TARGET_SH5"
6322   "")
6324 (define_expand "push_e"
6325   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6326                    (match_operand:SF 0 "" ""))
6327               (use (reg:PSI FPSCR_REG))
6328               (clobber (scratch:SI))])]
6329   "TARGET_SH1 && ! TARGET_SH5"
6330   "")
6332 (define_insn "push_fpul"
6333   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6334   "TARGET_SH2E && ! TARGET_SH5"
6335   "sts.l        fpul,@-r15"
6336   [(set_attr "type" "fstore")
6337    (set_attr "late_fp_use" "yes")
6338    (set_attr "hit_stack" "yes")])
6340 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6341 ;; so use that.
6342 (define_expand "push_4"
6343   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6344                    (match_operand:DF 0 "" ""))
6345               (use (reg:PSI FPSCR_REG))
6346               (clobber (scratch:SI))])]
6347   "TARGET_SH1 && ! TARGET_SH5"
6348   "")
6350 (define_expand "pop_e"
6351   [(parallel [(set (match_operand:SF 0 "" "")
6352               (mem:SF (post_inc:SI (reg:SI SP_REG))))
6353               (use (reg:PSI FPSCR_REG))
6354               (clobber (scratch:SI))])]
6355   "TARGET_SH1 && ! TARGET_SH5"
6356   "")
6358 (define_insn "pop_fpul"
6359   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6360   "TARGET_SH2E && ! TARGET_SH5"
6361   "lds.l        @r15+,fpul"
6362   [(set_attr "type" "load")
6363    (set_attr "hit_stack" "yes")])
6365 (define_expand "pop_4"
6366   [(parallel [(set (match_operand:DF 0 "" "")
6367                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
6368               (use (reg:PSI FPSCR_REG))
6369               (clobber (scratch:SI))])]
6370   "TARGET_SH1 && ! TARGET_SH5"
6371   "")
6373 (define_expand "push_fpscr"
6374   [(const_int 0)]
6375   "TARGET_SH2E"
6377   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
6378                                                  gen_rtx_PRE_DEC (Pmode,
6379                                                           stack_pointer_rtx)),
6380                                         get_fpscr_rtx ()));
6381   add_reg_note (insn, REG_INC, stack_pointer_rtx);
6382   DONE;
6385 (define_expand "pop_fpscr"
6386   [(const_int 0)]
6387   "TARGET_SH2E"
6389   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
6390                                         gen_frame_mem (PSImode,
6391                                                  gen_rtx_POST_INC (Pmode,
6392                                                           stack_pointer_rtx))));
6393   add_reg_note (insn, REG_INC, stack_pointer_rtx);
6394   DONE;
6397 ;; The clrt and sett patterns can happen as the result of optimization and
6398 ;; insn expansion.
6399 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6400 ;; In this case they might not disappear completely, because the T reg is
6401 ;; a fixed hard reg.
6402 ;; When DImode operations that use the T reg as carry/borrow are split into
6403 ;; individual SImode operations, the T reg is usually cleared before the
6404 ;; first SImode insn.
6405 (define_insn "clrt"
6406   [(set (reg:SI T_REG) (const_int 0))]
6407   "TARGET_SH1"
6408   "clrt"
6409   [(set_attr "type" "mt_group")])
6411 (define_insn "sett"
6412   [(set (reg:SI T_REG) (const_int 1))]
6413   "TARGET_SH1"
6414   "sett"
6415   [(set_attr "type" "mt_group")])
6417 ;; Use the combine pass to transform sequences such as
6418 ;;      mov     r5,r0
6419 ;;      add     #1,r0
6420 ;;      shll2   r0
6421 ;;      mov.l   @(r0,r4),r0
6422 ;; into
6423 ;;      shll2   r5
6424 ;;      add     r4,r5
6425 ;;      mov.l   @(4,r5),r0
6427 ;; See also PR 39423.
6428 ;; Notice that these patterns have a T_REG clobber, because the shift
6429 ;; sequence that will be split out might clobber the T_REG.  Ideally, the
6430 ;; clobber would be added conditionally, depending on the result of
6431 ;; sh_ashlsi_clobbers_t_reg_p.  When splitting out the shifts we must go
6432 ;; through the ashlsi3 expander in order to get the right shift insn --
6433 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6434 ;; FIXME: Combine never tries this kind of patterns for DImode.
6435 (define_insn_and_split "*movsi_index_disp_load"
6436   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6437         (match_operand:SI 1 "mem_index_disp_operand" "m"))
6438    (clobber (reg:SI T_REG))]
6439   "TARGET_SH1"
6440   "#"
6441   "&& can_create_pseudo_p ()"
6442   [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6443    (set (match_dup 0) (match_dup 7))]
6445   rtx mem = operands[1];
6446   rtx plus0_rtx = XEXP (mem, 0);
6447   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6448   rtx mult_rtx = XEXP (plus1_rtx, 0);
6450   operands[1] = XEXP (mult_rtx, 0);
6451   operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6452   operands[3] = XEXP (plus1_rtx, 1);
6453   operands[4] = XEXP (plus0_rtx, 1);
6454   operands[5] = gen_reg_rtx (SImode);
6455   operands[6] = gen_reg_rtx (SImode);
6456   operands[7] =
6457     replace_equiv_address (mem,
6458                            gen_rtx_PLUS (SImode, operands[6], operands[4]));
6460   emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6463 (define_insn_and_split "*movhi_index_disp_load"
6464   [(set (match_operand:SI 0 "arith_reg_dest")
6465         (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6466    (clobber (reg:SI T_REG))]
6467   "TARGET_SH1"
6468   "#"
6469   "&& can_create_pseudo_p ()"
6470   [(const_int 0)]
6472   rtx mem = operands[1];
6473   rtx plus0_rtx = XEXP (mem, 0);
6474   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6475   rtx mult_rtx = XEXP (plus1_rtx, 0);
6477   rtx op_1 = XEXP (mult_rtx, 0);
6478   rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6479   rtx op_3 = XEXP (plus1_rtx, 1);
6480   rtx op_4 = XEXP (plus0_rtx, 1);
6481   rtx op_5 = gen_reg_rtx (SImode);
6482   rtx op_6 = gen_reg_rtx (SImode);
6483   rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6485   emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6486   emit_insn (gen_addsi3 (op_6, op_5, op_3));
6488   if (<CODE> == SIGN_EXTEND)
6489     {
6490       emit_insn (gen_extendhisi2 (operands[0], op_7));
6491       DONE;
6492     }
6493   else if (<CODE> == ZERO_EXTEND)
6494     {
6495       /* On SH2A the movu.w insn can be used for zero extending loads.  */
6496       if (TARGET_SH2A)
6497         emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6498       else
6499         {
6500           emit_insn (gen_extendhisi2 (operands[0], op_7));
6501           emit_insn (gen_zero_extendhisi2 (operands[0],
6502                                            gen_lowpart (HImode, operands[0])));
6503         }
6504       DONE;
6505     }
6506   else
6507     FAIL;
6510 (define_insn_and_split "*mov<mode>_index_disp_store"
6511   [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6512         (match_operand:HISI 1 "arith_reg_operand" "r"))
6513    (clobber (reg:SI T_REG))]
6514   "TARGET_SH1"
6515   "#"
6516   "&& can_create_pseudo_p ()"
6517   [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6518    (set (match_dup 7) (match_dup 1))]
6520   rtx mem = operands[0];
6521   rtx plus0_rtx = XEXP (mem, 0);
6522   rtx plus1_rtx = XEXP (plus0_rtx, 0);
6523   rtx mult_rtx = XEXP (plus1_rtx, 0);
6525   operands[0] = XEXP (mult_rtx, 0);
6526   operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6527   operands[3] = XEXP (plus1_rtx, 1);
6528   operands[4] = XEXP (plus0_rtx, 1);
6529   operands[5] = gen_reg_rtx (SImode);
6530   operands[6] = gen_reg_rtx (SImode);
6531   operands[7] =
6532     replace_equiv_address (mem,
6533                            gen_rtx_PLUS (SImode, operands[6], operands[4]));
6535   emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6538 ;; t/r must come after r/r, lest reload will try to reload stuff like
6539 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6540 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6541 (define_insn "movsi_i"
6542   [(set (match_operand:SI 0 "general_movdst_operand"
6543             "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6544         (match_operand:SI 1 "general_movsrc_operand"
6545          "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6546   "TARGET_SH1
6547    && ! TARGET_SH2E
6548    && ! TARGET_SH2A
6549    && (register_operand (operands[0], SImode)
6550        || register_operand (operands[1], SImode))"
6551   "@
6552         mov.l   %1,%0
6553         mov     %1,%0
6554         mov     %1,%0
6555         mov.l   %1,%0
6556         sts     %1,%0
6557         sts     %1,%0
6558         mov.l   %1,%0
6559         sts.l   %1,%0
6560         sts.l   %1,%0
6561         lds     %1,%0
6562         lds     %1,%0
6563         lds.l   %1,%0
6564         lds.l   %1,%0
6565         fake    %1,%0"
6566   [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
6567                      pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6568    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6570 ;; t/r must come after r/r, lest reload will try to reload stuff like
6571 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6572 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
6573 ;; will require a reload.
6574 ;; ??? We can't include f/f because we need the proper FPSCR setting when
6575 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6576 (define_insn "movsi_ie"
6577   [(set (match_operand:SI 0 "general_movdst_operand"
6578             "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6579         (match_operand:SI 1 "general_movsrc_operand"
6580          "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6581   "(TARGET_SH2E || TARGET_SH2A)
6582    && (register_operand (operands[0], SImode)
6583        || register_operand (operands[1], SImode))"
6584   "@
6585         mov.l   %1,%0
6586         mov     %1,%0
6587         mov     %1,%0
6588         movi20  %1,%0
6589         movi20s %1,%0
6590         mov.l   %1,%0
6591         sts     %1,%0
6592         sts     %1,%0
6593         mov.l   %1,%0
6594         sts.l   %1,%0
6595         sts.l   %1,%0
6596         lds     %1,%0
6597         lds     %1,%0
6598         lds.l   %1,%0
6599         lds.l   %1,%0
6600         lds.l   %1,%0
6601         sts.l   %1,%0
6602         fake    %1,%0
6603         lds     %1,%0
6604         sts     %1,%0
6605         fsts    fpul,%0
6606         flds    %1,fpul
6607         fmov    %1,%0
6608         ! move optimized away"
6609   [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
6610                      mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
6611                      pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6612    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6613    (set_attr_alternative "length"
6614      [(const_int 2)
6615       (const_int 2)
6616       (const_int 2)
6617       (const_int 4)
6618       (const_int 4)
6619       (if_then_else
6620         (match_test "TARGET_SH2A")
6621         (const_int 4) (const_int 2))
6622       (const_int 2)
6623       (const_int 2)
6624       (if_then_else
6625         (match_test "TARGET_SH2A")
6626         (const_int 4) (const_int 2))
6627       (const_int 2)
6628       (const_int 2)
6629       (const_int 2)
6630       (const_int 2)
6631       (const_int 2)
6632       (const_int 2)
6633       (const_int 2)
6634       (const_int 2)
6635       (const_int 2)
6636       (const_int 2)
6637       (const_int 2)
6638       (const_int 2)
6639       (const_int 2)
6640       (const_int 2)
6641       (const_int 0)])])
6643 (define_insn "movsi_i_lowpart"
6644   [(set (strict_low_part
6645           (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6646         (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6647    "TARGET_SH1
6648     && (register_operand (operands[0], SImode)
6649         || register_operand (operands[1], SImode))"
6650   "@
6651         mov.l   %1,%0
6652         mov     %1,%0
6653         mov     %1,%0
6654         mov.l   %1,%0
6655         sts     %1,%0
6656         sts     %1,%0
6657         mov.l   %1,%0
6658         fake    %1,%0"
6659   [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6661 (define_insn_and_split "load_ra"
6662   [(set (match_operand:SI 0 "general_movdst_operand" "")
6663         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6664   "TARGET_SH1"
6665   "#"
6666   "&& ! currently_expanding_to_rtl"
6667   [(set (match_dup 0) (match_dup 1))]
6669   if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6670     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6673 ;; The '?'s in the following constraints may not reflect the time taken
6674 ;; to perform the move. They are there to discourage the use of floating-
6675 ;; point registers for storing integer values.
6676 (define_insn "*movsi_media"
6677   [(set (match_operand:SI 0 "general_movdst_operand"
6678                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6679         (match_operand:SI 1 "general_movsrc_operand"
6680          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6681   "TARGET_SHMEDIA_FPU
6682    && (register_operand (operands[0], SImode)
6683        || sh_register_operand (operands[1], SImode)
6684        || GET_CODE (operands[1]) == TRUNCATE)"
6685   "@
6686         add.l   %1, r63, %0
6687         movi    %1, %0
6688         #
6689         ld%M1.l %m1, %0
6690         st%M0.l %m0, %N1
6691         fld%M1.s        %m1, %0
6692         fst%M0.s        %m0, %1
6693         fmov.ls %N1, %0
6694         fmov.sl %1, %0
6695         fmov.s  %1, %0
6696         ptabs   %1, %0
6697         gettr   %1, %0
6698         pt      %1, %0"
6699   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,
6700                        fload_media,fstore_media,fload_media,fpconv_media,
6701                        fmove_media,ptabs_media,gettr_media,pt_media")
6702    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6703    (set (attr "highpart")
6704         (cond [(match_test "sh_contains_memref_p (insn)")
6705                (const_string "user")]
6706               (const_string "ignore")))])
6708 (define_insn "*movsi_media_nofpu"
6709   [(set (match_operand:SI 0 "general_movdst_operand"
6710                 "=r,r,r,r,m,*b,r,*b")
6711         (match_operand:SI 1 "general_movsrc_operand"
6712          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6713   "TARGET_SHMEDIA
6714    && (register_operand (operands[0], SImode)
6715        || sh_register_operand (operands[1], SImode)
6716        || GET_CODE (operands[1]) == TRUNCATE)"
6717   "@
6718         add.l   %1, r63, %0
6719         movi    %1, %0
6720         #
6721         ld%M1.l %m1, %0
6722         st%M0.l %m0, %N1
6723         ptabs   %1, %0
6724         gettr   %1, %0
6725         pt      %1, %0"
6726   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6727                      ptabs_media,gettr_media,pt_media")
6728    (set_attr "length" "4,4,8,4,4,4,4,12")
6729    (set (attr "highpart")
6730         (cond [(match_test "sh_contains_memref_p (insn)")
6731                (const_string "user")]
6732               (const_string "ignore")))])
6734 (define_expand "movsi_const"
6735   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6736         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6737                               (const_int 16)] UNSPEC_EXTRACT_S16)))
6738    (set (match_dup 0)
6739         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
6740                 (const:SI (unspec:SI [(match_dup 1)
6741                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
6742   "TARGET_SHMEDIA && reload_completed
6743    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6745   if (GET_CODE (operands[1]) == LABEL_REF
6746       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6747     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6748   else if (GOTOFF_P (operands[1]))
6749     {
6750       rtx unspec = XEXP (operands[1], 0);
6752       if (! UNSPEC_GOTOFF_P (unspec))
6753         {
6754           unspec = XEXP (unspec, 0);
6755           if (! UNSPEC_GOTOFF_P (unspec))
6756             abort ();
6757         }
6758       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6759           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6760         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6761     }
6764 (define_expand "movsi_const_16bit"
6765   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6766         (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6767                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
6768   "TARGET_SHMEDIA && flag_pic && reload_completed
6769    && GET_CODE (operands[1]) == SYMBOL_REF"
6770   "")
6772 (define_split
6773   [(set (match_operand:SI 0 "arith_reg_dest" "")
6774         (match_operand:SI 1 "immediate_operand" ""))]
6775   "TARGET_SHMEDIA && reload_completed
6776    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6777   [(const_int 0)]
6779   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6781   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6783   DONE;
6786 (define_split
6787   [(set (match_operand:SI 0 "register_operand" "")
6788         (match_operand:SI 1 "immediate_operand" ""))]
6789   "TARGET_SHMEDIA && reload_completed
6790    && ((CONST_INT_P (operands[1])
6791         && ! satisfies_constraint_I16 (operands[1]))
6792        || GET_CODE (operands[1]) == CONST_DOUBLE)"
6793   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6795 (define_expand "movsi"
6796   [(set (match_operand:SI 0 "general_movdst_operand" "")
6797         (match_operand:SI 1 "general_movsrc_operand" ""))]
6798   ""
6800   prepare_move_operands (operands, SImode);
6803 (define_expand "ic_invalidate_line"
6804   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6805                                 (match_dup 1)] UNSPEC_ICACHE)
6806               (clobber (scratch:SI))])]
6807   "TARGET_HARD_SH4 || TARGET_SH5"
6809   if (TARGET_SHMEDIA)
6810     {
6811       emit_insn (gen_ic_invalidate_line_media (operands[0]));
6812       DONE;
6813     }
6814   else if (TARGET_SHCOMPACT)
6815     {
6816       operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6817       operands[1] = force_reg (Pmode, operands[1]);
6818       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6819       DONE;
6820     }
6821   else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
6822     {
6823       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6824       DONE;
6825     }
6826   operands[0] = force_reg (Pmode, operands[0]);
6827   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6828                                                                Pmode)));
6831 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
6832 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6833 ;; the requirement *1*00 for associative address writes.  The alignment of
6834 ;; %0 implies that its least significant bit is cleared,
6835 ;; thus we clear the V bit of a matching entry if there is one.
6836 (define_insn "ic_invalidate_line_i"
6837   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6838                      (match_operand:SI 1 "register_operand" "r")]
6839                      UNSPEC_ICACHE)
6840    (clobber (match_scratch:SI 2 "=&r"))]
6841   "TARGET_HARD_SH4"
6843   return       "ocbwb   @%0"    "\n"
6844          "      extu.w  %0,%2"  "\n"
6845          "      or      %1,%2"  "\n"
6846          "      mov.l   %0,@%2";
6848   [(set_attr "length" "8")
6849    (set_attr "type" "cwb")])
6851 (define_insn "ic_invalidate_line_sh4a"
6852   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6853                     UNSPEC_ICACHE)]
6854   "TARGET_SH4A_ARCH || TARGET_SH4_300"
6856   return       "ocbwb   @%0"    "\n"
6857          "      synco"          "\n"
6858          "      icbi    @%0";
6860   [(set_attr "length" "16")     ;; FIXME: Why 16 and not 6?  Looks like typo.
6861    (set_attr "type" "cwb")])
6863 ;; ??? could make arg 0 an offsettable memory operand to allow to save
6864 ;; an add in the code that calculates the address.
6865 (define_insn "ic_invalidate_line_media"
6866   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
6867                     UNSPEC_ICACHE)]
6868   "TARGET_SHMEDIA"
6870   return       "ocbwb   %0,0"   "\n"
6871          "      synco"          "\n"
6872          "      icbi    %0,0"   "\n"
6873          "      synci";
6875   [(set_attr "length" "16")
6876    (set_attr "type" "invalidate_line_media")])
6878 (define_insn "ic_invalidate_line_compact"
6879   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6880                      (match_operand:SI 1 "register_operand" "r")]
6881                     UNSPEC_ICACHE)
6882    (clobber (reg:SI PR_REG))]
6883   "TARGET_SHCOMPACT"
6884   "jsr @%1%#"
6885   [(set_attr "type" "sfunc")
6886    (set_attr "needs_delay_slot" "yes")])
6888 (define_expand "initialize_trampoline"
6889   [(match_operand:SI 0 "" "")
6890    (match_operand:SI 1 "" "")
6891    (match_operand:SI 2 "" "")]
6892   "TARGET_SHCOMPACT"
6894   rtx sfun, tramp;
6896   tramp = force_reg (Pmode, operands[0]);
6897   sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
6898                                             SFUNC_STATIC));
6899   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6900   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6902   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6903   DONE;
6906 (define_insn "initialize_trampoline_compact"
6907   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6908                      (match_operand:SI 1 "register_operand" "r")
6909                      (reg:SI R2_REG) (reg:SI R3_REG)]
6910                     UNSPEC_INIT_TRAMP)
6912    (clobber (reg:SI PR_REG))]
6913   "TARGET_SHCOMPACT"
6914   "jsr @%1%#"
6915   [(set_attr "type" "sfunc")
6916    (set_attr "needs_delay_slot" "yes")])
6918 (define_expand "movhi"
6919   [(set (match_operand:HI 0 "general_movdst_operand" "")
6920         (match_operand:HI 1 "general_movsrc_operand" ""))]
6921   ""
6923   prepare_move_operands (operands, HImode);
6926 (define_expand "movqi"
6927   [(set (match_operand:QI 0 "general_operand" "")
6928         (match_operand:QI 1 "general_operand" ""))]
6929   ""
6931   prepare_move_operands (operands, QImode);
6934 ;; Specifying the displacement addressing load / store patterns separately
6935 ;; before the generic movqi / movhi pattern allows controlling the order
6936 ;; in which load / store insns are selected in a more fine grained way.
6937 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
6938 ;; "enabled" attribute as it is done in other targets.
6939 (define_insn "*mov<mode>_store_mem_disp04"
6940   [(set (mem:QIHI
6941           (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
6942                    (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
6943         (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
6944   "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
6945   "@
6946         mov.<bw>        %2,@(%O1,%0)
6947         mov.<bw>        %2,@%0"
6948   [(set_attr "type" "store")])
6950 (define_insn "*mov<mode>_store_mem_disp12"
6951   [(set (mem:QIHI
6952           (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
6953                    (match_operand:SI 1 "const_int_operand" "<disp12>")))
6954         (match_operand:QIHI 2 "arith_reg_operand" "r"))]
6955   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
6956   "mov.<bw>     %2,@(%O1,%0)"
6957   [(set_attr "type" "store")
6958    (set_attr "length" "4")])
6960 (define_insn "*mov<mode>_load_mem_disp04"
6961   [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
6962         (mem:QIHI
6963           (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
6964                    (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
6965   "TARGET_SH1 && ! TARGET_SH2A
6966    && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6967   "@
6968         mov.<bw>        @(%O2,%1),%0
6969         mov.<bw>        @%1,%0"
6970   [(set_attr "type" "load")])
6972 (define_insn "*mov<mode>_load_mem_disp12"
6973   [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
6974         (mem:QIHI
6975           (plus:SI
6976             (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6977             (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
6978   "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6979   "@
6980         mov.<bw>        @(%O2,%1),%0
6981         mov.<bw>        @%1,%0
6982         mov.<bw>        @(%O2,%1),%0"
6983   [(set_attr "type" "load")
6984    (set_attr "length" "2,2,4")])
6986 ;; The order of the constraint alternatives is important here.
6987 ;; Q/r has to come first, otherwise PC relative loads might wrongly get
6988 ;; placed into delay slots.  Since there is no QImode PC relative load, the
6989 ;; Q constraint and general_movsrc_operand will reject it for QImode.
6990 ;; The Snd alternatives should come before Sdd in order to avoid a preference
6991 ;; of using r0 als the register operand for addressing modes other than
6992 ;; displacement addressing.
6993 ;; The Sdd alternatives allow only r0 as register operand, even though on
6994 ;; SH2A any register could be allowed by switching to a 32 bit insn.
6995 ;; Generally sticking to the r0 is preferrable, since it generates smaller
6996 ;; code.  Obvious r0 reloads can then be eliminated with a peephole on SH2A.
6997 (define_insn "*mov<mode>"
6998   [(set (match_operand:QIHI 0 "general_movdst_operand"
6999                               "=r,r,r,Snd,r,  Sdd,z,  r,l")
7000         (match_operand:QIHI 1 "general_movsrc_operand"
7001                                "Q,r,i,r,  Snd,z,  Sdd,l,r"))]
7002   "TARGET_SH1
7003    && (arith_reg_operand (operands[0], <MODE>mode)
7004        || arith_reg_operand (operands[1], <MODE>mode))"
7005   "@
7006         mov.<bw>        %1,%0
7007         mov     %1,%0
7008         mov     %1,%0
7009         mov.<bw>        %1,%0
7010         mov.<bw>        %1,%0
7011         mov.<bw>        %1,%0
7012         mov.<bw>        %1,%0
7013         sts     %1,%0
7014         lds     %1,%0"
7015   [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset")
7016    (set (attr "length")
7017         (cond [(and (match_operand 0 "displacement_mem_operand")
7018                     (not (match_operand 0 "short_displacement_mem_operand")))
7019                (const_int 4)
7020                (and (match_operand 1 "displacement_mem_operand")
7021                     (not (match_operand 1 "short_displacement_mem_operand")))
7022                (const_int 4)]
7023               (const_int 2)))])
7025 (define_insn "*movqi_media"
7026   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7027         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7028   "TARGET_SHMEDIA
7029    && (arith_reg_operand (operands[0], QImode)
7030        || extend_reg_or_0_operand (operands[1], QImode))"
7031   "@
7032         add.l   %1, r63, %0
7033         movi    %1, %0
7034         ld%M1.ub        %m1, %0
7035         st%M0.b %m0, %N1"
7036   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7037    (set (attr "highpart")
7038         (cond [(match_test "sh_contains_memref_p (insn)")
7039                (const_string "user")]
7040               (const_string "ignore")))])
7042 (define_expand "reload_inqi"
7043   [(set (match_operand:SI 2 "" "=&r")
7044         (match_operand:QI 1 "inqhi_operand" ""))
7045    (set (match_operand:QI 0 "arith_reg_operand" "=r")
7046         (truncate:QI (match_dup 3)))]
7047   "TARGET_SHMEDIA"
7049   rtx inner = XEXP (operands[1], 0);
7050   int regno = REGNO (inner);
7052   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7053   operands[1] = gen_rtx_REG (SImode, regno);
7054   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7057 (define_insn "*movhi_media"
7058   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
7059         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7060   "TARGET_SHMEDIA
7061    && (arith_reg_operand (operands[0], HImode)
7062        || arith_reg_or_0_operand (operands[1], HImode))"
7063   "@
7064         add.l   %1, r63, %0
7065         movi    %1, %0
7066         #
7067         ld%M1.w %m1, %0
7068         st%M0.w %m0, %N1"
7069   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7070    (set (attr "highpart")
7071         (cond [(match_test "sh_contains_memref_p (insn)")
7072                (const_string "user")]
7073               (const_string "ignore")))])
7075 (define_split
7076   [(set (match_operand:HI 0 "register_operand" "")
7077         (match_operand:HI 1 "immediate_operand" ""))]
7078   "TARGET_SHMEDIA && reload_completed
7079    && ! satisfies_constraint_I16 (operands[1])"
7080   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7082 (define_expand "reload_inhi"
7083   [(set (match_operand:SI 2 "" "=&r")
7084         (match_operand:HI 1 "inqhi_operand" ""))
7085    (set (match_operand:HI 0 "arith_reg_operand" "=r")
7086         (truncate:HI (match_dup 3)))]
7087   "TARGET_SHMEDIA"
7089   rtx inner = XEXP (operands[1], 0);
7090   int regno = REGNO (inner);
7092   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7093   operands[1] = gen_rtx_REG (SImode, regno);
7094   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7097 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7098 ;; compiled with -m2 -ml -O3 -funroll-loops
7099 (define_insn "*movdi_i"
7100   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7101         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7102   "TARGET_SH1
7103    && (arith_reg_operand (operands[0], DImode)
7104        || arith_reg_operand (operands[1], DImode))"
7106   return output_movedouble (insn, operands, DImode);
7108   [(set_attr "length" "4")
7109    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7111 ;; If the output is a register and the input is memory or a register, we have
7112 ;; to be careful and see which word needs to be loaded first.
7113 (define_split
7114   [(set (match_operand:DI 0 "general_movdst_operand" "")
7115         (match_operand:DI 1 "general_movsrc_operand" ""))]
7116   "TARGET_SH1 && reload_completed"
7117   [(set (match_dup 2) (match_dup 3))
7118    (set (match_dup 4) (match_dup 5))]
7120   int regno;
7122   if ((MEM_P (operands[0])
7123        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7124       || (MEM_P (operands[1])
7125           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7126     FAIL;
7128   switch (GET_CODE (operands[0]))
7129     {
7130     case REG:
7131       regno = REGNO (operands[0]);
7132       break;
7133     case SUBREG:
7134       regno = subreg_regno (operands[0]);
7135       break;
7136     case MEM:
7137       regno = -1;
7138       break;
7139     default:
7140       gcc_unreachable ();
7141     }
7143   if (regno == -1
7144       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7145     {
7146       operands[2] = operand_subword (operands[0], 0, 0, DImode);
7147       operands[3] = operand_subword (operands[1], 0, 0, DImode);
7148       operands[4] = operand_subword (operands[0], 1, 0, DImode);
7149       operands[5] = operand_subword (operands[1], 1, 0, DImode);
7150     }
7151   else
7152     {
7153       operands[2] = operand_subword (operands[0], 1, 0, DImode);
7154       operands[3] = operand_subword (operands[1], 1, 0, DImode);
7155       operands[4] = operand_subword (operands[0], 0, 0, DImode);
7156       operands[5] = operand_subword (operands[1], 0, 0, DImode);
7157     }
7159   if (operands[2] == 0 || operands[3] == 0
7160       || operands[4] == 0 || operands[5] == 0)
7161     FAIL;
7164 ;; The '?'s in the following constraints may not reflect the time taken
7165 ;; to perform the move. They are there to discourage the use of floating-
7166 ;; point registers for storing integer values.
7167 (define_insn "*movdi_media"
7168   [(set (match_operand:DI 0 "general_movdst_operand"
7169                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7170         (match_operand:DI 1 "general_movsrc_operand"
7171          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7172   "TARGET_SHMEDIA_FPU
7173    && (register_operand (operands[0], DImode)
7174        || sh_register_operand (operands[1], DImode))"
7175   "@
7176         add     %1, r63, %0
7177         movi    %1, %0
7178         #
7179         ld%M1.q %m1, %0
7180         st%M0.q %m0, %N1
7181         fld%M1.d        %m1, %0
7182         fst%M0.d        %m0, %1
7183         fmov.qd %N1, %0
7184         fmov.dq %1, %0
7185         fmov.d  %1, %0
7186         ptabs   %1, %0
7187         gettr   %1, %0
7188         pt      %1, %0"
7189   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7190                      fload_media,fstore_media,fload_media,dfpconv_media,
7191                      fmove_media,ptabs_media,gettr_media,pt_media")
7192    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7194 (define_insn "*movdi_media_nofpu"
7195   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7196         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7197   "TARGET_SHMEDIA
7198    && (register_operand (operands[0], DImode)
7199        || sh_register_operand (operands[1], DImode))"
7200   "@
7201         add     %1, r63, %0
7202         movi    %1, %0
7203         #
7204         ld%M1.q %m1, %0
7205         st%M0.q %m0, %N1
7206         ptabs   %1, %0
7207         gettr   %1, %0
7208         pt      %1, %0"
7209   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7210                      ptabs_media,gettr_media,pt_media")
7211    (set_attr "length" "4,4,16,4,4,4,4,*")])
7213 (define_insn "*movdi_media_I16"
7214   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7215         (match_operand:DI 1 "const_int_operand" "I16"))]
7216   "TARGET_SHMEDIA && reload_completed"
7217   "movi %1, %0"
7218   [(set_attr "type" "arith_media")
7219    (set_attr "length" "4")])
7221 (define_split
7222   [(set (match_operand:DI 0 "arith_reg_dest" "")
7223         (match_operand:DI 1 "immediate_operand" ""))]
7224   "TARGET_SHMEDIA && reload_completed
7225    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7226   [(set (match_dup 0) (match_dup 1))]
7228   rtx insn;
7230   if (TARGET_SHMEDIA64)
7231     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7232   else
7233     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7235   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7237   DONE;
7240 (define_expand "movdi_const"
7241   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7242         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7243                               (const_int 48)] UNSPEC_EXTRACT_S16)))
7244    (set (match_dup 0)
7245         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7246                 (const:DI (unspec:DI [(match_dup 1)
7247                                       (const_int 32)] UNSPEC_EXTRACT_U16))))
7248    (set (match_dup 0)
7249         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7250                 (const:DI (unspec:DI [(match_dup 1)
7251                                       (const_int 16)] UNSPEC_EXTRACT_U16))))
7252    (set (match_dup 0)
7253         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7254                 (const:DI (unspec:DI [(match_dup 1)
7255                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
7256   "TARGET_SHMEDIA64 && reload_completed
7257    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7259   sh_mark_label (operands[1], 4);
7262 (define_expand "movdi_const_32bit"
7263   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7264         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7265                               (const_int 16)] UNSPEC_EXTRACT_S16)))
7266    (set (match_dup 0)
7267         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7268                 (const:DI (unspec:DI [(match_dup 1)
7269                                       (const_int 0)] UNSPEC_EXTRACT_U16))))]
7270   "TARGET_SHMEDIA32 && reload_completed
7271    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7273   sh_mark_label (operands[1], 2);
7276 (define_expand "movdi_const_16bit"
7277   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7278         (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7279                               (const_int 0)] UNSPEC_EXTRACT_S16)))]
7280   "TARGET_SHMEDIA && flag_pic && reload_completed
7281    && GET_CODE (operands[1]) == SYMBOL_REF"
7282   "")
7284 (define_split
7285   [(set (match_operand:DI 0 "ext_dest_operand" "")
7286         (match_operand:DI 1 "immediate_operand" ""))]
7287   "TARGET_SHMEDIA && reload_completed
7288    && CONST_INT_P (operands[1])
7289    && ! satisfies_constraint_I16 (operands[1])"
7290   [(set (match_dup 0) (match_dup 2))
7291    (match_dup 1)]
7293   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7294   unsigned HOST_WIDE_INT low = val;
7295   unsigned HOST_WIDE_INT high = val;
7296   unsigned HOST_WIDE_INT sign;
7297   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7299   /* Zero-extend the 16 least-significant bits.  */
7300   low &= 0xffff;
7302   /* Arithmetic shift right the word by 16 bits.  */
7303   high >>= 16;
7304   if (GET_CODE (operands[0]) == SUBREG
7305       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7306     {
7307       high &= 0xffff;
7308       high ^= 0x8000;
7309       high -= 0x8000;
7310     }
7311   else
7312     {
7313       sign = 1;
7314       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7315       high ^= sign;
7316       high -= sign;
7317     }
7318   do
7319     {
7320       /* If we can't generate the constant with a two-insn movi / shori
7321          sequence, try some other strategies.  */
7322       if (! CONST_OK_FOR_I16 (high))
7323         {
7324           /* Try constant load / left shift.  We know VAL != 0.  */
7325           val2 = val ^ (val-1);
7326           if (val2 > 0x1ffff)
7327             {
7328               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7330               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7331                   || (! CONST_OK_FOR_I16 (high >> 16)
7332                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7333                 {
7334                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7335                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
7336                                                    GEN_INT (trailing_zeroes));
7337                   break;
7338                 }
7339             }
7340           /* Try constant load / right shift.  */
7341           val2 = (val >> 15) + 1;
7342           if (val2 == (val2 & -val2))
7343             {
7344               int shift = 49 - exact_log2 (val2);
7346               val2 = trunc_int_for_mode (val << shift, DImode);
7347               if (CONST_OK_FOR_I16 (val2))
7348                 {
7349                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7350                                                    GEN_INT (shift));
7351                   break;
7352                 }
7353             }
7354           /* Try mperm.w .  */
7355           val2 = val & 0xffff;
7356           if ((val >> 16 & 0xffff) == val2
7357               && (val >> 32 & 0xffff) == val2
7358               && (val >> 48 & 0xffff) == val2)
7359             {
7360               val2 = (HOST_WIDE_INT) val >> 48;
7361               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7362               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7363               break;
7364             }
7365           /* Try movi / mshflo.l  */
7366           val2 = (HOST_WIDE_INT) val >> 32;
7367           if (val2 == ((unsigned HOST_WIDE_INT)
7368                         trunc_int_for_mode (val, SImode)))
7369             {
7370               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7371                                              operands[0]);
7372               break;
7373             }
7374           /* Try movi / mshflo.l w/ r63.  */
7375           val2 = val + ((HOST_WIDE_INT) -1 << 32);
7376           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7377             {
7378               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7379                                              const0_rtx);
7380               break;
7381             }
7382         }
7383       val2 = high;
7384       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7385     }
7386   while (0);
7387   operands[2] = GEN_INT (val2);
7390 (define_split
7391   [(set (match_operand:DI 0 "ext_dest_operand" "")
7392         (match_operand:DI 1 "immediate_operand" ""))]
7393   "TARGET_SHMEDIA && reload_completed
7394    && GET_CODE (operands[1]) == CONST_DOUBLE"
7395   [(set (match_dup 0) (match_dup 2))
7396   (set (match_dup 0)
7397        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7399   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7400   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7401   unsigned HOST_WIDE_INT val = low;
7402   unsigned HOST_WIDE_INT sign;
7404   /* Zero-extend the 16 least-significant bits.  */
7405   val &= 0xffff;
7406   operands[1] = GEN_INT (val);
7408   /* Arithmetic shift right the double-word by 16 bits.  */
7409   low >>= 16;
7410   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7411   high >>= 16;
7412   sign = 1;
7413   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7414   high ^= sign;
7415   high -= sign;
7417   /* This will only be true if high is a sign-extension of low, i.e.,
7418      it must be either 0 or (unsigned)-1, and be zero iff the
7419      most-significant bit of low is set.  */
7420   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7421     operands[2] = GEN_INT (low);
7422   else
7423     operands[2] = immed_double_const (low, high, DImode);
7426 (define_insn "shori_media"
7427   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7428         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7429                            (const_int 16))
7430                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7431   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7432   "@
7433         shori   %u2, %0
7434         #"
7435   [(set_attr "type" "arith_media,*")])
7437 (define_insn "*shori_media_si"
7438   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7439         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7440                            (const_int 16))
7441                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7442   "TARGET_SHMEDIA"
7443   "shori        %u2, %0")
7445 (define_expand "movdi"
7446   [(set (match_operand:DI 0 "general_movdst_operand" "")
7447         (match_operand:DI 1 "general_movsrc_operand" ""))]
7448   ""
7450   prepare_move_operands (operands, DImode);
7453 (define_insn "movdf_media"
7454   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7455         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7456   "TARGET_SHMEDIA_FPU
7457    && (register_operand (operands[0], DFmode)
7458        || sh_register_operand (operands[1], DFmode))"
7459   "@
7460         fmov.d  %1, %0
7461         fmov.qd %N1, %0
7462         fmov.dq %1, %0
7463         add     %1, r63, %0
7464         #
7465         fld%M1.d        %m1, %0
7466         fst%M0.d        %m0, %1
7467         ld%M1.q %m1, %0
7468         st%M0.q %m0, %N1"
7469   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7470                      fload_media,fstore_media,load_media,store_media")])
7472 (define_insn "movdf_media_nofpu"
7473   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7474         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7475   "TARGET_SHMEDIA
7476    && (register_operand (operands[0], DFmode)
7477        || sh_register_operand (operands[1], DFmode))"
7478   "@
7479         add     %1, r63, %0
7480         #
7481         ld%M1.q %m1, %0
7482         st%M0.q %m0, %N1"
7483   [(set_attr "type" "arith_media,*,load_media,store_media")])
7485 (define_split
7486   [(set (match_operand:DF 0 "arith_reg_dest" "")
7487         (match_operand:DF 1 "immediate_operand" ""))]
7488   "TARGET_SHMEDIA && reload_completed"
7489   [(set (match_dup 3) (match_dup 2))]
7491   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7492   long values[2];
7493   REAL_VALUE_TYPE value;
7495   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7496   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7498   if (HOST_BITS_PER_WIDE_INT >= 64)
7499     operands[2] = immed_double_const ((unsigned long) values[endian]
7500                                       | ((HOST_WIDE_INT) values[1 - endian]
7501                                          << 32), 0, DImode);
7502   else
7503     {
7504       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7505       operands[2] = immed_double_const (values[endian], values[1 - endian],
7506                                         DImode);
7507     }
7509   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7512 ;; FIXME: This should be a define_insn_and_split.
7513 (define_insn "movdf_k"
7514   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7515         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7516   "TARGET_SH1
7517    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7518        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7519        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7520        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7521    && (arith_reg_operand (operands[0], DFmode)
7522        || arith_reg_operand (operands[1], DFmode))"
7524   return output_movedouble (insn, operands, DFmode);
7526   [(set_attr "length" "4")
7527    (set_attr "type" "move,pcload,load,store")])
7529 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7530 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
7531 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
7532 ;; the d/m/c/X alternative, which is split later into single-precision
7533 ;; instructions.  And when not optimizing, no splits are done before fixing
7534 ;; up pcloads, so we need usable length information for that.
7535 (define_insn "movdf_i4"
7536   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7537         (match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
7538    (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
7539    (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
7540   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7541    && (arith_reg_operand (operands[0], DFmode)
7542        || arith_reg_operand (operands[1], DFmode))"
7543   {
7544     switch (which_alternative)
7545     {
7546     case 0:
7547       if (TARGET_FMOVD)
7548         return "fmov    %1,%0";
7549       else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7550         return         "fmov    %R1,%R0"        "\n"
7551                "        fmov    %S1,%S0";
7552       else
7553         return         "fmov    %S1,%S0"        "\n"
7554                "        fmov    %R1,%R0";
7555     case 3:
7556     case 4:
7557       return "fmov.d    %1,%0";
7558     default:
7559       return "#";
7560     }
7561   }
7562   [(set_attr_alternative "length"
7563      [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7564       (const_int 4)
7565       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7566       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7567       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7568       (const_int 4)
7569       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7570       ;; We can't use 4-byte push/pop on SHcompact, so we have to
7571       ;; increment or decrement r15 explicitly.
7572       (if_then_else
7573        (match_test "TARGET_SHCOMPACT")
7574        (const_int 10) (const_int 8))
7575       (if_then_else
7576        (match_test "TARGET_SHCOMPACT")
7577        (const_int 10) (const_int 8))])
7578    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7579    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7580    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7581                                            (const_string "double")
7582                                            (const_string "none")))])
7584 ;; Moving DFmode between fp/general registers through memory
7585 ;; (the top of the stack) is faster than moving through fpul even for
7586 ;; little endian.  Because the type of an instruction is important for its
7587 ;; scheduling,  it is beneficial to split these operations, rather than
7588 ;; emitting them in one single chunk, even if this will expose a stack
7589 ;; use that will prevent scheduling of other stack accesses beyond this
7590 ;; instruction.
7591 (define_split
7592   [(set (match_operand:DF 0 "register_operand" "")
7593         (match_operand:DF 1 "register_operand" ""))
7594    (use (match_operand:PSI 2 "fpscr_operand" ""))
7595    (clobber (match_scratch:SI 3 "=X"))]
7596   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7597    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7598   [(const_int 0)]
7600   rtx insn, tos;
7602   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7603     {
7604       emit_move_insn (stack_pointer_rtx,
7605                       plus_constant (Pmode, stack_pointer_rtx, -8));
7606       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7607     }
7608   else
7609     tos = gen_tmp_stack_mem (DFmode,
7610                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7611   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
7612   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7613     add_reg_note (insn, REG_INC, stack_pointer_rtx);
7614   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7615     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7616   else
7617     tos = gen_tmp_stack_mem (DFmode,
7618                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7619   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
7620   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7621     emit_move_insn (stack_pointer_rtx,
7622                     plus_constant (Pmode, stack_pointer_rtx, 8));
7623   else
7624     add_reg_note (insn, REG_INC, stack_pointer_rtx);
7625   DONE;
7628 ;; local-alloc sometimes allocates scratch registers even when not required,
7629 ;; so we must be prepared to handle these.
7631 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7632 (define_split
7633   [(set (match_operand:DF 0 "general_movdst_operand" "")
7634         (match_operand:DF 1 "general_movsrc_operand"  ""))
7635    (use (match_operand:PSI 2 "fpscr_operand" ""))
7636    (clobber (match_scratch:SI 3 ""))]
7637   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7638    && reload_completed
7639    && true_regnum (operands[0]) < 16
7640    && true_regnum (operands[1]) < 16"
7641   [(set (match_dup 0) (match_dup 1))]
7643   /* If this was a reg <-> mem operation with base + index reg addressing,
7644      we have to handle this in a special way.  */
7645   rtx mem = operands[0];
7646   int store_p = 1;
7647   if (! memory_operand (mem, DFmode))
7648     {
7649       mem = operands[1];
7650       store_p = 0;
7651     }
7652   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7653     mem = SUBREG_REG (mem);
7654   if (MEM_P (mem))
7655     {
7656       rtx addr = XEXP (mem, 0);
7657       if (GET_CODE (addr) == PLUS
7658           && REG_P (XEXP (addr, 0))
7659           && REG_P (XEXP (addr, 1)))
7660         {
7661           int offset;
7662           rtx reg0 = gen_rtx_REG (Pmode, 0);
7663           rtx regop = operands[store_p], word0 ,word1;
7665           if (GET_CODE (regop) == SUBREG)
7666             alter_subreg (&regop, true);
7667           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7668             offset = 2;
7669           else
7670             offset = 4;
7671           mem = copy_rtx (mem);
7672           PUT_MODE (mem, SImode);
7673           word0 = gen_rtx_SUBREG (SImode, regop, 0);
7674           alter_subreg (&word0, true);
7675           word1 = gen_rtx_SUBREG (SImode, regop, 4);
7676           alter_subreg (&word1, true);
7677           if (store_p || ! refers_to_regno_p (REGNO (word0),
7678                                               REGNO (word0) + 1, addr, 0))
7679             {
7680               emit_insn (store_p
7681                          ? gen_movsi_ie (mem, word0)
7682                          : gen_movsi_ie (word0, mem));
7683               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7684               mem = copy_rtx (mem);
7685               emit_insn (store_p
7686                          ? gen_movsi_ie (mem, word1)
7687                          : gen_movsi_ie (word1, mem));
7688               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7689             }
7690           else
7691             {
7692               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7693               emit_insn (gen_movsi_ie (word1, mem));
7694               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7695               mem = copy_rtx (mem);
7696               emit_insn (gen_movsi_ie (word0, mem));
7697             }
7698           DONE;
7699         }
7700     }
7703 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7704 (define_split
7705   [(set (match_operand:DF 0 "register_operand" "")
7706         (match_operand:DF 1 "memory_operand"  ""))
7707    (use (match_operand:PSI 2 "fpscr_operand" ""))
7708    (clobber (reg:SI R0_REG))]
7709   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7710   [(parallel [(set (match_dup 0) (match_dup 1))
7711               (use (match_dup 2))
7712               (clobber (scratch:SI))])]
7713   "")
7715 (define_expand "reload_indf__frn"
7716   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7717                    (match_operand:DF 1 "immediate_operand" "FQ"))
7718               (use (reg:PSI FPSCR_REG))
7719               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7720   "TARGET_SH1"
7721   "")
7723 (define_expand "reload_outdf__RnFRm"
7724   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7725                    (match_operand:DF 1 "register_operand" "af,r"))
7726               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7727   "TARGET_SH1"
7728   "")
7730 ;; Simplify no-op moves.
7731 (define_split
7732   [(set (match_operand:SF 0 "register_operand" "")
7733         (match_operand:SF 1 "register_operand" ""))
7734    (use (match_operand:PSI 2 "fpscr_operand" ""))
7735    (clobber (match_scratch:SI 3 ""))]
7736   "TARGET_SH2E && reload_completed
7737    && true_regnum (operands[0]) == true_regnum (operands[1])"
7738   [(set (match_dup 0) (match_dup 0))]
7739   "")
7741 ;; fmovd substitute post-reload splits
7742 (define_split
7743   [(set (match_operand:DF 0 "register_operand" "")
7744         (match_operand:DF 1 "register_operand" ""))
7745    (use (match_operand:PSI 2 "fpscr_operand" ""))
7746    (clobber (match_scratch:SI 3 ""))]
7747   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7748    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7749    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7750   [(const_int 0)]
7752   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7753   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7754                            gen_rtx_REG (SFmode, src), operands[2]));
7755   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7756                            gen_rtx_REG (SFmode, src + 1), operands[2]));
7757   DONE;
7760 (define_split
7761   [(set (match_operand:DF 0 "register_operand" "")
7762         (mem:DF (match_operand:SI 1 "register_operand" "")))
7763    (use (match_operand:PSI 2 "fpscr_operand" ""))
7764    (clobber (match_scratch:SI 3 ""))]
7765   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7766    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7767    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7768   [(const_int 0)]
7770   int regno = true_regnum (operands[0]);
7771   rtx insn;
7772   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7773   rtx mem2
7774     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7775   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7776                                                regno + SH_REG_MSW_OFFSET),
7777                                   mem2, operands[2]));
7778   add_reg_note (insn, REG_INC, operands[1]);
7779   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7780                                                regno + SH_REG_LSW_OFFSET),
7781                                   change_address (mem, SFmode, NULL_RTX),
7782                                   operands[2]));
7783   DONE;
7786 (define_split
7787   [(set (match_operand:DF 0 "register_operand" "")
7788         (match_operand:DF 1 "memory_operand" ""))
7789    (use (match_operand:PSI 2 "fpscr_operand" ""))
7790    (clobber (match_scratch:SI 3 ""))]
7791   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7792    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7793   [(const_int 0)]
7795   int regno = true_regnum (operands[0]);
7796   rtx addr, insn;
7797   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7798   rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7799   rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7801   operands[1] = copy_rtx (mem2);
7802   addr = XEXP (mem2, 0);
7804   switch (GET_CODE (addr))
7805     {
7806     case REG:
7807       /* This is complicated.  If the register is an arithmetic register
7808          we can just fall through to the REG+DISP case below.  Otherwise
7809          we have to use a combination of POST_INC and REG addressing...  */
7810       if (! arith_reg_operand (operands[1], SFmode))
7811         {
7812           XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7813           insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7814           add_reg_note (insn, REG_INC, XEXP (addr, 0));
7815           
7816           emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7818           /* If we have modified the stack pointer, the value that we have
7819              read with post-increment might be modified by an interrupt,
7820              so write it back.  */
7821           if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7822             emit_insn (gen_push_e (reg0));
7823           else
7824             emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
7825                                    GEN_INT (-4)));
7826           break;
7827         }
7828       /* Fall through.  */
7830     case PLUS:
7831       emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7832       operands[1] = copy_rtx (operands[1]);
7833       XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7834       emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7835       break;
7837     case POST_INC:
7838       insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7839       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7841       insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7842       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7843       break;
7845     default:
7846       debug_rtx (addr);
7847       gcc_unreachable ();
7848     }
7850   DONE;
7853 (define_split
7854   [(set (match_operand:DF 0 "memory_operand" "")
7855         (match_operand:DF 1 "register_operand" ""))
7856    (use (match_operand:PSI 2 "fpscr_operand" ""))
7857    (clobber (match_scratch:SI 3 ""))]
7858   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7859    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7860   [(const_int 0)]
7862   int regno = true_regnum (operands[1]);
7863   rtx insn, addr;
7864   rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
7865   rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
7867   operands[0] = copy_rtx (operands[0]);
7868   PUT_MODE (operands[0], SFmode);
7869   addr = XEXP (operands[0], 0);
7871   switch (GET_CODE (addr))
7872     {
7873     case REG:
7874       /* This is complicated.  If the register is an arithmetic register
7875          we can just fall through to the REG+DISP case below.  Otherwise
7876          we have to use a combination of REG and PRE_DEC addressing...  */
7877       if (! arith_reg_operand (operands[0], SFmode))
7878         {
7879           emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7880           emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7882           operands[0] = copy_rtx (operands[0]);
7883           XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7884           
7885           insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7886           add_reg_note (insn, REG_INC, XEXP (addr, 0));
7887           break;
7888         }
7889       /* Fall through.  */
7891     case PLUS:
7892       /* Since REG+DISP addressing has already been decided upon by gcc
7893          we can rely upon it having chosen an arithmetic register as the
7894          register component of the address.  Just emit the lower numbered
7895          register first, to the lower address, then the higher numbered
7896          register to the higher address.  */
7897       emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7899       operands[0] = copy_rtx (operands[0]);
7900       XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7902       emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7903       break;
7905     case PRE_DEC:
7906       /* This is easy.  Output the word to go to the higher address
7907          first (ie the word in the higher numbered register) then the
7908          word to go to the lower address.  */
7910       insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7911       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7913       insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7914       add_reg_note (insn, REG_INC, XEXP (addr, 0));
7915       break;
7917     default:
7918       /* FAIL; */
7919       debug_rtx (addr);
7920       gcc_unreachable ();
7921     }
7923   DONE;
7926 ;; If the output is a register and the input is memory or a register, we have
7927 ;; to be careful and see which word needs to be loaded first.
7928 (define_split
7929   [(set (match_operand:DF 0 "general_movdst_operand" "")
7930         (match_operand:DF 1 "general_movsrc_operand" ""))]
7931   "TARGET_SH1 && reload_completed"
7932   [(set (match_dup 2) (match_dup 3))
7933    (set (match_dup 4) (match_dup 5))]
7935   int regno;
7937   if ((MEM_P (operands[0])
7938        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7939       || (MEM_P (operands[1])
7940           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7941     FAIL;
7943   switch (GET_CODE (operands[0]))
7944     {
7945     case REG:
7946       regno = REGNO (operands[0]);
7947       break;
7948     case SUBREG:
7949       regno = subreg_regno (operands[0]);
7950       break;
7951     case MEM:
7952       regno = -1;
7953       break;
7954     default:
7955       gcc_unreachable ();
7956     }
7958   if (regno == -1
7959       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7960     {
7961       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
7962       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
7963       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
7964       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
7965     }
7966   else
7967     {
7968       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
7969       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
7970       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
7971       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
7972     }
7974   if (operands[2] == 0 || operands[3] == 0
7975       || operands[4] == 0 || operands[5] == 0)
7976     FAIL;
7979 (define_expand "movdf"
7980   [(set (match_operand:DF 0 "general_movdst_operand" "")
7981         (match_operand:DF 1 "general_movsrc_operand" ""))]
7982   ""
7984   prepare_move_operands (operands, DFmode);
7985   if (TARGET_SHMEDIA)
7986     {
7987       if (TARGET_SHMEDIA_FPU)
7988         emit_insn (gen_movdf_media (operands[0], operands[1]));
7989       else
7990         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
7991       DONE;
7992     }
7993   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
7994     {
7995       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
7996       DONE;
7997     }
8000 ;;This is incompatible with the way gcc uses subregs.
8001 ;;(define_insn "movv2sf_i"
8002 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8003 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8004 ;;  "TARGET_SHMEDIA_FPU
8005 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
8006 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
8007 ;;  "@
8008 ;;      #
8009 ;;      fld%M1.p        %m1, %0
8010 ;;      fst%M0.p        %m0, %1"
8011 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
8012 (define_insn_and_split "movv2sf_i"
8013   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8014         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8015   "TARGET_SHMEDIA_FPU"
8016   "#"
8017   "TARGET_SHMEDIA_FPU && reload_completed"
8018   [(set (match_dup 0) (match_dup 1))]
8020   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8021   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8024 (define_expand "movv2sf"
8025   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8026         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
8027   "TARGET_SHMEDIA_FPU"
8029   prepare_move_operands (operands, V2SFmode);
8032 (define_expand "addv2sf3"
8033   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8034    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8035    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8036   "TARGET_SHMEDIA_FPU"
8038   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8039   DONE;
8042 (define_expand "subv2sf3"
8043   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8044    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8045    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8046   "TARGET_SHMEDIA_FPU"
8048   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8049   DONE;
8052 (define_expand "mulv2sf3"
8053   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8054    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8055    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8056   "TARGET_SHMEDIA_FPU"
8058   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8059   DONE;
8062 (define_expand "divv2sf3"
8063   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8064    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8065    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8066   "TARGET_SHMEDIA_FPU"
8068   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8069   DONE;
8072 (define_insn_and_split "*movv4sf_i"
8073   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8074         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8075   "TARGET_SHMEDIA_FPU"
8076   "#"
8077   "&& reload_completed"
8078   [(const_int 0)]
8080   for (int i = 0; i < 4/2; i++)
8081     {
8082       rtx x, y;
8084       if (MEM_P (operands[0]))
8085         x = adjust_address (operands[0], V2SFmode,
8086                             i * GET_MODE_SIZE (V2SFmode));
8087       else
8088         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8090       if (MEM_P (operands[1]))
8091         y = adjust_address (operands[1], V2SFmode,
8092                             i * GET_MODE_SIZE (V2SFmode));
8093       else
8094         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8096       emit_insn (gen_movv2sf_i (x, y));
8097     }
8099   DONE;
8101   [(set_attr "length" "8")])
8103 (define_expand "movv4sf"
8104   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8105         (match_operand:V4SF 1 "general_operand" ""))]
8106   "TARGET_SHMEDIA_FPU"
8108   prepare_move_operands (operands, V4SFmode);
8111 (define_insn_and_split "*movv16sf_i"
8112   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8113         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8114   "TARGET_SHMEDIA_FPU"
8115   "#"
8116   "&& reload_completed"
8117   [(const_int 0)]
8119   for (int i = 0; i < 16/2; i++)
8120     {
8121       rtx x, y;
8123       if (MEM_P (operands[0]))
8124         x = adjust_address (operands[0], V2SFmode,
8125                             i * GET_MODE_SIZE (V2SFmode));
8126       else
8127         {
8128           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8129           alter_subreg (&x, true);
8130         }
8132       if (MEM_P (operands[1]))
8133         y = adjust_address (operands[1], V2SFmode,
8134                             i * GET_MODE_SIZE (V2SFmode));
8135       else
8136         {
8137           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8138           alter_subreg (&y, true);
8139         }
8141       emit_insn (gen_movv2sf_i (x, y));
8142     }
8144   DONE;
8146   [(set_attr "length" "32")])
8148 (define_expand "movv16sf"
8149   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8150         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8151   "TARGET_SHMEDIA_FPU"
8153   prepare_move_operands (operands, V16SFmode);
8156 (define_insn "movsf_media"
8157   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8158         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8159   "TARGET_SHMEDIA_FPU
8160    && (register_operand (operands[0], SFmode)
8161        || sh_register_operand (operands[1], SFmode))"
8162   "@
8163         fmov.s  %1, %0
8164         fmov.ls %N1, %0
8165         fmov.sl %1, %0
8166         add.l   %1, r63, %0
8167         #
8168         fld%M1.s        %m1, %0
8169         fst%M0.s        %m0, %1
8170         ld%M1.l %m1, %0
8171         st%M0.l %m0, %N1"
8172   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8173    (set (attr "highpart")
8174         (cond [(match_test "sh_contains_memref_p (insn)")
8175                (const_string "user")]
8176               (const_string "ignore")))])
8178 (define_insn "movsf_media_nofpu"
8179   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8180         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8181   "TARGET_SHMEDIA
8182    && (register_operand (operands[0], SFmode)
8183        || sh_register_operand (operands[1], SFmode))"
8184   "@
8185         add.l   %1, r63, %0
8186         #
8187         ld%M1.l %m1, %0
8188         st%M0.l %m0, %N1"
8189   [(set_attr "type" "arith_media,*,load_media,store_media")
8190    (set (attr "highpart")
8191         (cond [(match_test "sh_contains_memref_p (insn)")
8192                (const_string "user")]
8193               (const_string "ignore")))])
8195 (define_split
8196   [(set (match_operand:SF 0 "arith_reg_dest" "")
8197         (match_operand:SF 1 "immediate_operand" ""))]
8198   "TARGET_SHMEDIA && reload_completed
8199    && ! FP_REGISTER_P (true_regnum (operands[0]))"
8200   [(set (match_dup 3) (match_dup 2))]
8202   long values;
8203   REAL_VALUE_TYPE value;
8205   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8206   REAL_VALUE_TO_TARGET_SINGLE (value, values);
8207   operands[2] = GEN_INT (values);
8209   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8212 (define_insn "movsf_i"
8213   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8214         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
8215   "TARGET_SH1
8216    && (! TARGET_SH2E
8217        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8218        || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8219        || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8220    && (arith_reg_operand (operands[0], SFmode)
8221        || arith_reg_operand (operands[1], SFmode))"
8222   "@
8223         mov     %1,%0
8224         mov     #0,%0
8225         mov.l   %1,%0
8226         mov.l   %1,%0
8227         mov.l   %1,%0
8228         lds     %1,%0
8229         sts     %1,%0"
8230   [(set_attr "type" "move,move,pcload,load,store,move,move")])
8232 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8233 ;; update_flow_info would not know where to put REG_EQUAL notes
8234 ;; when the destination changes mode.
8235 (define_insn "movsf_ie"
8236   [(set (match_operand:SF 0 "general_movdst_operand"
8237          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8238         (match_operand:SF 1 "general_movsrc_operand"
8239           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8240    (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"))
8241    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8242   "TARGET_SH2E
8243    && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8244        || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8245        || arith_reg_operand (operands[3], SImode))"
8246   "@
8247         fmov    %1,%0
8248         mov     %1,%0
8249         fldi0   %0
8250         fldi1   %0
8251         #
8252         fmov.s  %1,%0
8253         fmov.s  %1,%0
8254         mov.l   %1,%0
8255         mov.l   %1,%0
8256         mov.l   %1,%0
8257         fsts    fpul,%0
8258         flds    %1,fpul
8259         lds.l   %1,%0
8260         #
8261         sts     %1,%0
8262         lds     %1,%0
8263         sts.l   %1,%0
8264         lds.l   %1,%0
8265         ! move optimized away"
8266   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8267                      store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8268    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8269    (set_attr_alternative "length"
8270      [(const_int 2)
8271       (const_int 2)
8272       (const_int 2)
8273       (const_int 2)
8274       (const_int 4)
8275       (if_then_else
8276         (match_test "TARGET_SH2A")
8277         (const_int 4) (const_int 2))
8278       (if_then_else
8279         (match_test "TARGET_SH2A")
8280         (const_int 4) (const_int 2))
8281       (const_int 2)
8282       (if_then_else
8283         (match_test "TARGET_SH2A")
8284         (const_int 4) (const_int 2))
8285       (if_then_else
8286         (match_test "TARGET_SH2A")
8287         (const_int 4) (const_int 2))
8288       (const_int 2)
8289       (const_int 2)
8290       (const_int 2)
8291       (const_int 4)
8292       (const_int 2)
8293       (const_int 2)
8294       (const_int 2)
8295       (const_int 2)
8296       (const_int 0)])
8297    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8298                                            (const_string "single")
8299                                            (const_string "single")))])
8301 (define_split
8302   [(set (match_operand:SF 0 "register_operand" "")
8303         (match_operand:SF 1 "register_operand" ""))
8304    (use (match_operand:PSI 2 "fpscr_operand" ""))
8305    (clobber (reg:SI FPUL_REG))]
8306   "TARGET_SH1"
8307   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8308               (use (match_dup 2))
8309               (clobber (scratch:SI))])
8310    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8311               (use (match_dup 2))
8312               (clobber (scratch:SI))])]
8313   "")
8315 (define_expand "movsf"
8316   [(set (match_operand:SF 0 "general_movdst_operand" "")
8317         (match_operand:SF 1 "general_movsrc_operand" ""))]
8318   ""
8320   prepare_move_operands (operands, SFmode);
8321   if (TARGET_SHMEDIA)
8322     {
8323       if (TARGET_SHMEDIA_FPU)
8324         emit_insn (gen_movsf_media (operands[0], operands[1]));
8325       else
8326         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8327       DONE;
8328     }
8329   if (TARGET_SH2E)
8330     {
8331       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
8332       DONE;
8333     }
8336 (define_insn "mov_nop"
8337   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8338   "TARGET_SH2E"
8339   ""
8340   [(set_attr "length" "0")
8341    (set_attr "type" "nil")])
8343 (define_expand "reload_insf__frn"
8344   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8345                    (match_operand:SF 1 "immediate_operand" "FQ"))
8346               (use (reg:PSI FPSCR_REG))
8347               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8348   "TARGET_SH1"
8349   "")
8351 (define_expand "reload_insi__i_fpul"
8352   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8353                    (match_operand:SI 1 "immediate_operand" "i"))
8354               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8355   "TARGET_SH1"
8356   "")
8358 (define_expand "ptabs"
8359   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8360   "TARGET_SHMEDIA"
8362   if (!TARGET_PT_FIXED)
8363     {
8364       rtx eq = operands[1];
8366       /* ??? For canonical RTL we really should remove any CONST from EQ
8367          before wrapping it in the AND, and finally wrap the EQ into a
8368          const if is constant.  However, for reload we must expose the
8369          input register or symbolic constant, and we can't have
8370          different insn structures outside of the operands for different
8371          alternatives of the same pattern.  */
8372       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8373                        GEN_INT (3));
8374       operands[1]
8375         = (gen_rtx_IF_THEN_ELSE
8376             (PDImode,
8377              eq,
8378              gen_rtx_MEM (PDImode, operands[1]),
8379              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8380                             PDImode, operands[1])));
8381     }
8384 ;; expanded by ptabs expander.
8385 (define_insn "*extendsipdi_media"
8386   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8387         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8388                                                           "r,Csy")
8389                                       (const_int 3))
8390                               (const_int 3))
8391                           (mem:PDI (match_dup 1))
8392                           (sign_extend:PDI (match_dup 1))))]
8393   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8394   "@
8395         ptabs   %1, %0
8396         pt      %1, %0"
8397   [(set_attr "type"   "ptabs_media,pt_media")
8398    (set_attr "length" "4,*")])
8400 (define_insn "*truncdipdi_media"
8401   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8402         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8403                                                           "r,Csy")
8404                                       (const_int 3))
8405                               (const_int 3))
8406                           (mem:PDI (match_dup 1))
8407                           (truncate:PDI (match_dup 1))))]
8408   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8409   "@
8410         ptabs   %1, %0
8411         pt      %1, %0"
8412   [(set_attr "type"   "ptabs_media,pt_media")
8413    (set_attr "length" "4,*")])
8415 (define_insn "*movsi_y"
8416   [(set (match_operand:SI 0 "register_operand" "=y,y")
8417         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
8418    (clobber (match_scratch:SI 2 "=&z,r"))]
8419   "TARGET_SH2E
8420    && (reload_in_progress || reload_completed)"
8421   "#"
8422   [(set_attr "length" "4")
8423    (set_attr "type" "pcload,move")])
8425 (define_split
8426   [(set (match_operand:SI 0 "register_operand" "")
8427         (match_operand:SI 1 "immediate_operand" ""))
8428    (clobber (match_operand:SI 2 "register_operand" ""))]
8429   "TARGET_SH1"
8430   [(set (match_dup 2) (match_dup 1))
8431    (set (match_dup 0) (match_dup 2))]
8432   "")
8434 ;; ------------------------------------------------------------------------
8435 ;; Define the real conditional branch instructions.
8436 ;; ------------------------------------------------------------------------
8438 (define_expand "branch_true"
8439   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8440                            (label_ref (match_operand 0))
8441                            (pc)))]
8442   "TARGET_SH1")
8444 (define_expand "branch_false"
8445   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8446                            (label_ref (match_operand 0))
8447                            (pc)))]
8448   "TARGET_SH1")
8450 (define_insn_and_split "*cbranch_t"
8451   [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8452                            (label_ref (match_operand 0))
8453                            (pc)))]
8454   "TARGET_SH1"
8456   return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8458   "&& 1"
8459   [(const_int 0)]
8461   /* Try to canonicalize the branch condition if it is not one of:
8462         (ne (reg:SI T_REG) (const_int 0))
8463         (eq (reg:SI T_REG) (const_int 0))
8465      Instead of splitting out a new insn, we modify the current insn's
8466      operands as needed.  This preserves things such as REG_DEAD notes.  */
8468   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
8469       && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
8470       && XEXP (operands[1], 1) == const0_rtx)
8471     DONE;
8473   int branch_cond = sh_eval_treg_value (operands[1]);
8474   rtx new_cond_rtx = NULL_RTX;
8476   if (branch_cond == 0)
8477     new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
8478   else if (branch_cond == 1)
8479     new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
8481   if (new_cond_rtx != NULL_RTX)
8482     validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
8483                      new_cond_rtx, false);
8484   DONE;
8486   [(set_attr "type" "cbranch")])
8488 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
8489 ;; which destination is too far away.
8490 ;; The const_int_operand is distinct for each branch target; it avoids
8491 ;; unwanted matches with redundant_insn.
8492 (define_insn "block_branch_redirect"
8493   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8494   "TARGET_SH1"
8495   ""
8496   [(set_attr "length" "0")])
8498 ;; This one has the additional purpose to record a possible scratch register
8499 ;; for the following branch.
8500 ;; ??? Unfortunately, just setting the scratch register is not good enough,
8501 ;; because the insn then might be deemed dead and deleted.  And we can't
8502 ;; make the use in the jump insn explicit because that would disable
8503 ;; delay slot scheduling from the target.
8504 (define_insn "indirect_jump_scratch"
8505   [(set (match_operand:SI 0 "register_operand" "=r")
8506         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8507    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8508   "TARGET_SH1"
8509   ""
8510   [(set_attr "length" "0")])
8512 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
8513 ;; being pulled into the delay slot of a condbranch that has been made to
8514 ;; jump around the unconditional jump because it was out of range.
8515 (define_insn "stuff_delay_slot"
8516   [(set (pc)
8517         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8518                  (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8519   "TARGET_SH1"
8520   ""
8521   [(set_attr "length" "0")
8522    (set_attr "cond_delay_slot" "yes")])
8524 ;; Conditional branch insns
8526 (define_expand "cbranchint4_media"
8527   [(set (pc)
8528         (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8529                        [(match_operand 1 "" "")
8530                         (match_operand 2 "" "")])
8531                       (match_operand 3 "" "")
8532                       (pc)))]
8533   "TARGET_SHMEDIA"
8535   enum machine_mode mode = GET_MODE (operands[1]);
8536   if (mode == VOIDmode)
8537     mode = GET_MODE (operands[2]);
8538   if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8539     {
8540       operands[1] = force_reg (mode, operands[1]);
8541       if (CONSTANT_P (operands[2])
8542           && (! satisfies_constraint_I06 (operands[2])))
8543         operands[2] = force_reg (mode, operands[2]);
8544     }
8545   else
8546     {
8547       if (operands[1] != const0_rtx)
8548         operands[1] = force_reg (mode, operands[1]);
8549       if (operands[2] != const0_rtx)
8550         operands[2] = force_reg (mode, operands[2]);
8551     }
8552   switch (GET_CODE (operands[0]))
8553     {
8554     case LEU:
8555     case LE:
8556     case LTU:
8557     case LT:
8558       operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8559                                     VOIDmode, operands[2], operands[1]);
8560       operands[1] = XEXP (operands[0], 0);
8561       operands[2] = XEXP (operands[0], 1);
8562       break;
8563     default:
8564       operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8565                                     VOIDmode, operands[1], operands[2]);
8566       break;
8567     }
8568   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8571 (define_expand "cbranchfp4_media"
8572   [(set (pc)
8573         (if_then_else (match_operator 0 "sh_float_comparison_operator"
8574                        [(match_operand 1 "" "")
8575                         (match_operand 2 "" "")])
8576                       (match_operand 3 "" "")
8577                       (pc)))]
8578   "TARGET_SHMEDIA"
8580   rtx tmp = gen_reg_rtx (SImode);
8581   rtx cmp;
8582   if (GET_CODE (operands[0]) == NE)
8583     cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8584   else
8585     cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8586                           operands[1], operands[2]);
8588   emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8590   if (GET_CODE (cmp) == GET_CODE (operands[0]))
8591     operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8592   else
8593     operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8594   operands[1] = tmp;
8595   operands[2] = const0_rtx;
8596   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8599 (define_insn "*beq_media_i"
8600   [(set (pc)
8601         (if_then_else (match_operator 3 "equality_comparison_operator"
8602                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
8603                          (match_operand:DI 2 "arith_operand" "r,I06")])
8604                       (match_operand 0 "target_operand" "b,b")
8605                       (pc)))]
8606   "TARGET_SHMEDIA"
8607   "@
8608         b%o3%'  %1, %2, %0%>
8609         b%o3i%' %1, %2, %0%>"
8610   [(set_attr "type" "cbranch_media")])
8612 (define_insn "*beq_media_i32"
8613   [(set (pc)
8614         (if_then_else (match_operator 3 "equality_comparison_operator"
8615                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
8616                          (match_operand:SI 2 "arith_operand" "r,I06")])
8617                       (match_operand 0 "target_operand" "b,b")
8618                       (pc)))]
8619   "TARGET_SHMEDIA"
8620   "@
8621         b%o3%'  %1, %2, %0%>
8622         b%o3i%' %1, %2, %0%>"
8623   [(set_attr "type" "cbranch_media")])
8625 (define_insn "*bgt_media_i"
8626   [(set (pc)
8627         (if_then_else (match_operator 3 "greater_comparison_operator"
8628                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8629                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8630                       (match_operand 0 "target_operand" "b")
8631                       (pc)))]
8632   "TARGET_SHMEDIA"
8633   "b%o3%'       %N1, %N2, %0%>"
8634   [(set_attr "type" "cbranch_media")])
8636 (define_insn "*bgt_media_i32"
8637   [(set (pc)
8638         (if_then_else (match_operator 3 "greater_comparison_operator"
8639                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8640                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8641                       (match_operand 0 "target_operand" "b")
8642                       (pc)))]
8643   "TARGET_SHMEDIA"
8644   "b%o3%'       %N1, %N2, %0%>"
8645   [(set_attr "type" "cbranch_media")])
8647 ;; These are only needed to make invert_jump() happy - otherwise, jump
8648 ;; optimization will be silently disabled.
8649 (define_insn "*blt_media_i"
8650   [(set (pc)
8651         (if_then_else (match_operator 3 "less_comparison_operator"
8652                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8653                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8654                       (match_operand 0 "target_operand" "b")
8655                       (pc)))]
8656   "TARGET_SHMEDIA"
8657   "b%o3%'       %N2, %N1, %0%>"
8658   [(set_attr "type" "cbranch_media")])
8660 (define_insn "*blt_media_i32"
8661   [(set (pc)
8662         (if_then_else (match_operator 3 "less_comparison_operator"
8663                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8664                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8665                       (match_operand 0 "target_operand" "b")
8666                       (pc)))]
8667   "TARGET_SHMEDIA"
8668   "b%o3%'       %N2, %N1, %0%>"
8669   [(set_attr "type" "cbranch_media")])
8671 ;; combiner splitter for test-and-branch on single bit in register.  This
8672 ;; is endian dependent because the non-paradoxical subreg looks different
8673 ;; on big endian.
8674 (define_split
8675   [(set (pc)
8676         (if_then_else
8677           (match_operator 3 "equality_comparison_operator"
8678             [(subreg:SI
8679                (zero_extract:DI
8680                  (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
8681                  (const_int 1)
8682                  (match_operand 2 "const_int_operand" "")) 0)
8683              (const_int 0)])
8684           (match_operand 0 "target_operand" "")
8685           (pc)))
8686    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8687   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8688   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8689    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8691   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8692   operands[6] = (GET_CODE (operands[3]) == EQ
8693                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8694                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8697 ; operand 0 is the loop count pseudo register
8698 ; operand 1 is the label to jump to at the top of the loop
8699 (define_expand "doloop_end"
8700   [(parallel [(set (pc)
8701                    (if_then_else (ne:SI (match_operand:SI 0 "" "")
8702                                         (const_int 1))
8703                                  (label_ref (match_operand 1 "" ""))
8704                                  (pc)))
8705               (set (match_dup 0)
8706                    (plus:SI (match_dup 0) (const_int -1)))
8707               (clobber (reg:SI T_REG))])]
8708   "TARGET_SH2"
8710   if (GET_MODE (operands[0]) != SImode)
8711     FAIL;
8712   emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
8713   DONE;
8716 (define_insn_and_split "doloop_end_split"
8717   [(set (pc)
8718         (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
8719                              (const_int 1))
8720                       (label_ref (match_operand 1 "" ""))
8721                       (pc)))
8722    (set (match_operand:SI 0 "arith_reg_dest" "=r")
8723         (plus:SI (match_dup 2) (const_int -1)))
8724    (clobber (reg:SI T_REG))]
8725   "TARGET_SH2"
8726   "#"
8727   ""
8728   [(parallel [(set (reg:SI T_REG)
8729                    (eq:SI (match_dup 2) (const_int 1)))
8730               (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8731    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8732                            (label_ref (match_dup 1))
8733                            (pc)))]
8734   ""
8735   [(set_attr "type" "cbranch")])
8737 ;; ------------------------------------------------------------------------
8738 ;; Jump and linkage insns
8739 ;; ------------------------------------------------------------------------
8741 (define_insn "jump_compact"
8742   [(set (pc)
8743         (label_ref (match_operand 0 "" "")))]
8744   "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
8746   /* The length is 16 if the delay slot is unfilled.  */
8747   if (get_attr_length(insn) > 4)
8748     return output_far_jump(insn, operands[0]);
8749   else
8750     return "bra %l0%#";
8752   [(set_attr "type" "jump")
8753    (set_attr "needs_delay_slot" "yes")])
8755 ;; ??? It would be much saner to explicitly use the scratch register
8756 ;; in the jump insn, and have indirect_jump_scratch only set it,
8757 ;; but fill_simple_delay_slots would refuse to do delay slot filling
8758 ;; from the target then, as it uses simplejump_p.
8759 ;;(define_insn "jump_compact_far"
8760 ;;  [(set (pc)
8761 ;;      (label_ref (match_operand 0 "" "")))
8762 ;;   (use (match_operand 1 "register_operand" "r")]
8763 ;;  "TARGET_SH1"
8764 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
8765 ;;  [(set_attr "type" "jump")
8766 ;;   (set_attr "needs_delay_slot" "yes")])
8768 (define_insn "jump_media"
8769   [(set (pc)
8770         (match_operand 0 "target_operand" "b"))]
8771   "TARGET_SHMEDIA"
8772   "blink        %0, r63%>"
8773   [(set_attr "type" "jump_media")])
8775 (define_expand "jump"
8776   [(set (pc)
8777         (label_ref (match_operand 0 "" "")))]
8778   ""
8780   if (TARGET_SH1)
8781     emit_jump_insn (gen_jump_compact (operands[0]));
8782   else if (TARGET_SHMEDIA)
8783     {
8784       if (reload_in_progress || reload_completed)
8785         FAIL;
8786       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
8787     }
8788   DONE;
8791 (define_insn "force_mode_for_call"
8792   [(use (reg:PSI FPSCR_REG))]
8793   "TARGET_SHCOMPACT"
8794   ""
8795   [(set_attr "length" "0")
8796    (set (attr "fp_mode")
8797         (if_then_else (eq_attr "fpu_single" "yes")
8798                       (const_string "single") (const_string "double")))])
8800 (define_insn "calli"
8801   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8802          (match_operand 1 "" ""))
8803    (use (reg:PSI FPSCR_REG))
8804    (clobber (reg:SI PR_REG))]
8805   "TARGET_SH1"
8807   if (TARGET_SH2A && (dbr_sequence_length () == 0))
8808     return "jsr/n       @%0";
8809   else
8810     return "jsr @%0%#";
8812   [(set_attr "type" "call")
8813    (set (attr "fp_mode")
8814         (if_then_else (eq_attr "fpu_single" "yes")
8815                       (const_string "single") (const_string "double")))
8816    (set_attr "needs_delay_slot" "yes")
8817    (set_attr "fp_set" "unknown")])
8819 ;; This is TBR relative jump instruction for SH2A architecture.
8820 ;; Its use is enabled by assigning an attribute "function_vector"
8821 ;; and the vector number to a function during its declaration.
8822 (define_insn "calli_tbr_rel"
8823   [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8824          (match_operand 1 "" ""))
8825    (use (reg:PSI FPSCR_REG))
8826    (clobber (reg:SI PR_REG))]
8827   "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8829   unsigned HOST_WIDE_INT vect_num;
8830   vect_num = sh2a_get_function_vector_number (operands[0]);
8831   operands[2] = GEN_INT (vect_num * 4);
8833   return "jsr/n @@(%O2,tbr)";
8835   [(set_attr "type" "call")
8836    (set (attr "fp_mode")
8837         (if_then_else (eq_attr "fpu_single" "yes")
8838                       (const_string "single") (const_string "double")))
8839    (set_attr "needs_delay_slot" "no")
8840    (set_attr "fp_set" "unknown")])
8842 ;; This is a pc-rel call, using bsrf, for use with PIC.
8843 (define_insn "calli_pcrel"
8844   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8845          (match_operand 1 "" ""))
8846    (use (reg:PSI FPSCR_REG))
8847    (use (reg:SI PIC_REG))
8848    (use (match_operand 2 "" ""))
8849    (clobber (reg:SI PR_REG))]
8850   "TARGET_SH2"
8852   return       "bsrf    %0"     "\n"
8853          "%O2:%#";
8855   [(set_attr "type" "call")
8856    (set (attr "fp_mode")
8857         (if_then_else (eq_attr "fpu_single" "yes")
8858                       (const_string "single") (const_string "double")))
8859    (set_attr "needs_delay_slot" "yes")
8860    (set_attr "fp_set" "unknown")])
8862 (define_insn_and_split "call_pcrel"
8863   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8864          (match_operand 1 "" ""))
8865    (use (reg:PSI FPSCR_REG))
8866    (use (reg:SI PIC_REG))
8867    (clobber (reg:SI PR_REG))
8868    (clobber (match_scratch:SI 2 "=r"))]
8869   "TARGET_SH2"
8870   "#"
8871   "reload_completed"
8872   [(const_int 0)]
8874   rtx lab = PATTERN (gen_call_site ());
8876   if (SYMBOL_REF_LOCAL_P (operands[0]))
8877     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8878   else
8879     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
8880   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
8881   DONE;
8883   [(set_attr "type" "call")
8884    (set (attr "fp_mode")
8885         (if_then_else (eq_attr "fpu_single" "yes")
8886                       (const_string "single") (const_string "double")))
8887    (set_attr "needs_delay_slot" "yes")
8888    (set_attr "fp_set" "unknown")])
8890 (define_insn "call_compact"
8891   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8892          (match_operand 1 "" ""))
8893    (match_operand 2 "immediate_operand" "n")
8894    (use (reg:SI R0_REG))
8895    (use (reg:SI R1_REG))
8896    (use (reg:PSI FPSCR_REG))
8897    (clobber (reg:SI PR_REG))]
8898   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8899   "jsr  @%0%#"
8900   [(set_attr "type" "call")
8901    (set (attr "fp_mode")
8902         (if_then_else (eq_attr "fpu_single" "yes")
8903                       (const_string "single") (const_string "double")))
8904    (set_attr "needs_delay_slot" "yes")])
8906 (define_insn "call_compact_rettramp"
8907   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8908          (match_operand 1 "" ""))
8909    (match_operand 2 "immediate_operand" "n")
8910    (use (reg:SI R0_REG))
8911    (use (reg:SI R1_REG))
8912    (use (reg:PSI FPSCR_REG))
8913    (clobber (reg:SI R10_REG))
8914    (clobber (reg:SI PR_REG))]
8915   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8916   "jsr  @%0%#"
8917   [(set_attr "type" "call")
8918    (set (attr "fp_mode")
8919         (if_then_else (eq_attr "fpu_single" "yes")
8920                       (const_string "single") (const_string "double")))
8921    (set_attr "needs_delay_slot" "yes")])
8923 (define_insn "call_media"
8924   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
8925          (match_operand 1 "" ""))
8926    (clobber (reg:DI PR_MEDIA_REG))]
8927   "TARGET_SHMEDIA"
8928   "blink        %0, r18"
8929   [(set_attr "type" "jump_media")])
8931 (define_insn "call_valuei"
8932   [(set (match_operand 0 "" "=rf")
8933         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8934               (match_operand 2 "" "")))
8935    (use (reg:PSI FPSCR_REG))
8936    (clobber (reg:SI PR_REG))]
8937   "TARGET_SH1"
8939   if (TARGET_SH2A && (dbr_sequence_length () == 0))
8940     return "jsr/n       @%1";
8941   else
8942     return "jsr @%1%#";
8944   [(set_attr "type" "call")
8945    (set (attr "fp_mode")
8946         (if_then_else (eq_attr "fpu_single" "yes")
8947                       (const_string "single") (const_string "double")))
8948    (set_attr "needs_delay_slot" "yes")
8949    (set_attr "fp_set" "unknown")])
8951 ;; This is TBR relative jump instruction for SH2A architecture.
8952 ;; Its use is enabled by assigning an attribute "function_vector"
8953 ;; and the vector number to a function during its declaration.
8954 (define_insn "call_valuei_tbr_rel"
8955   [(set (match_operand 0 "" "=rf")
8956         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8957               (match_operand 2 "" "")))
8958    (use (reg:PSI FPSCR_REG))
8959    (clobber (reg:SI PR_REG))]
8960   "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
8962   unsigned HOST_WIDE_INT vect_num;
8963   vect_num = sh2a_get_function_vector_number (operands[1]);
8964   operands[3] = GEN_INT (vect_num * 4);
8966   return "jsr/n @@(%O3,tbr)";
8968   [(set_attr "type" "call")
8969    (set (attr "fp_mode")
8970         (if_then_else (eq_attr "fpu_single" "yes")
8971                       (const_string "single") (const_string "double")))
8972    (set_attr "needs_delay_slot" "no")
8973    (set_attr "fp_set" "unknown")])
8975 (define_insn "call_valuei_pcrel"
8976   [(set (match_operand 0 "" "=rf")
8977         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8978               (match_operand 2 "" "")))
8979    (use (reg:PSI FPSCR_REG))
8980    (use (reg:SI PIC_REG))
8981    (use (match_operand 3 "" ""))
8982    (clobber (reg:SI PR_REG))]
8983   "TARGET_SH2"
8985   return       "bsrf    %1"     "\n"
8986          "%O3:%#";
8988   [(set_attr "type" "call")
8989    (set (attr "fp_mode")
8990         (if_then_else (eq_attr "fpu_single" "yes")
8991                       (const_string "single") (const_string "double")))
8992    (set_attr "needs_delay_slot" "yes")
8993    (set_attr "fp_set" "unknown")])
8995 (define_insn_and_split "call_value_pcrel"
8996   [(set (match_operand 0 "" "=rf")
8997         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8998               (match_operand 2 "" "")))
8999    (use (reg:PSI FPSCR_REG))
9000    (use (reg:SI PIC_REG))
9001    (clobber (reg:SI PR_REG))
9002    (clobber (match_scratch:SI 3 "=r"))]
9003   "TARGET_SH2"
9004   "#"
9005   "reload_completed"
9006   [(const_int 0)]
9008   rtx lab = PATTERN (gen_call_site ());
9010   if (SYMBOL_REF_LOCAL_P (operands[1]))
9011     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9012   else
9013     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
9014   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9015                                          operands[2], copy_rtx (lab)));
9016   DONE;
9018   [(set_attr "type" "call")
9019    (set (attr "fp_mode")
9020         (if_then_else (eq_attr "fpu_single" "yes")
9021                       (const_string "single") (const_string "double")))
9022    (set_attr "needs_delay_slot" "yes")
9023    (set_attr "fp_set" "unknown")])
9025 (define_insn "call_value_compact"
9026   [(set (match_operand 0 "" "=rf")
9027         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9028               (match_operand 2 "" "")))
9029    (match_operand 3 "immediate_operand" "n")
9030    (use (reg:SI R0_REG))
9031    (use (reg:SI R1_REG))
9032    (use (reg:PSI FPSCR_REG))
9033    (clobber (reg:SI PR_REG))]
9034   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9035   "jsr  @%1%#"
9036   [(set_attr "type" "call")
9037    (set (attr "fp_mode")
9038         (if_then_else (eq_attr "fpu_single" "yes")
9039                       (const_string "single") (const_string "double")))
9040    (set_attr "needs_delay_slot" "yes")])
9042 (define_insn "call_value_compact_rettramp"
9043   [(set (match_operand 0 "" "=rf")
9044         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9045               (match_operand 2 "" "")))
9046    (match_operand 3 "immediate_operand" "n")
9047    (use (reg:SI R0_REG))
9048    (use (reg:SI R1_REG))
9049    (use (reg:PSI FPSCR_REG))
9050    (clobber (reg:SI R10_REG))
9051    (clobber (reg:SI PR_REG))]
9052   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9053   "jsr  @%1%#"
9054   [(set_attr "type" "call")
9055    (set (attr "fp_mode")
9056         (if_then_else (eq_attr "fpu_single" "yes")
9057                       (const_string "single") (const_string "double")))
9058    (set_attr "needs_delay_slot" "yes")])
9060 (define_insn "call_value_media"
9061   [(set (match_operand 0 "" "=rf")
9062         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9063               (match_operand 2 "" "")))
9064    (clobber (reg:DI PR_MEDIA_REG))]
9065   "TARGET_SHMEDIA"
9066   "blink        %1, r18"
9067   [(set_attr "type" "jump_media")])
9069 (define_expand "call"
9070   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9071                             (match_operand 1 "" ""))
9072               (match_operand 2 "" "")
9073               (use (reg:PSI FPSCR_REG))
9074               (clobber (reg:SI PR_REG))])]
9075   ""
9077   if (TARGET_SHMEDIA)
9078     {
9079       operands[0] = shmedia_prepare_call_address (operands[0], 0);
9080       emit_call_insn (gen_call_media (operands[0], operands[1]));
9081       DONE;
9082     }
9083   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9084     {
9085       rtx cookie_rtx = operands[2];
9086       long cookie = INTVAL (cookie_rtx);
9087       rtx func = XEXP (operands[0], 0);
9088       rtx r0, r1;
9090       if (flag_pic)
9091         {
9092           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9093             {
9094               rtx reg = gen_reg_rtx (Pmode);
9096               emit_insn (gen_symGOTPLT2reg (reg, func));
9097               func = reg;
9098             }
9099           else
9100             func = legitimize_pic_address (func, Pmode, 0);
9101         }
9103       r0 = gen_rtx_REG (SImode, R0_REG);
9104       r1 = gen_rtx_REG (SImode, R1_REG);
9106       /* Since such a call function may use all call-clobbered
9107          registers, we force a mode switch earlier, so that we don't
9108          run out of registers when adjusting fpscr for the call.  */
9109       emit_insn (gen_force_mode_for_call ());
9111       operands[0]
9112         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9113       operands[0] = force_reg (SImode, operands[0]);
9115       emit_move_insn (r0, func);
9116       emit_move_insn (r1, cookie_rtx);
9118       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9119         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9120                                                    operands[2]));
9121       else
9122         emit_call_insn (gen_call_compact (operands[0], operands[1],
9123                                           operands[2]));
9125       DONE;
9126     }
9127   else if (TARGET_SHCOMPACT && flag_pic
9128            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9129            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9130     {
9131       rtx reg = gen_reg_rtx (Pmode);
9133       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9134       XEXP (operands[0], 0) = reg;
9135     }
9136   if (!flag_pic && TARGET_SH2A
9137       && MEM_P (operands[0])
9138       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9139     {
9140       if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9141         {
9142           emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9143                                              operands[1]));
9144           DONE;
9145         }
9146     }
9147   if (flag_pic && TARGET_SH2
9148       && MEM_P (operands[0])
9149       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9150     {
9151       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9152       DONE;
9153     }
9154   else
9155   {
9156     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9157     operands[1] = operands[2];
9158   }
9160   emit_call_insn (gen_calli (operands[0], operands[1]));
9161   DONE;
9164 (define_insn "call_pop_compact"
9165   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9166          (match_operand 1 "" ""))
9167    (match_operand 2 "immediate_operand" "n")
9168    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9169                                  (match_operand 3 "immediate_operand" "n")))
9170    (use (reg:SI R0_REG))
9171    (use (reg:SI R1_REG))
9172    (use (reg:PSI FPSCR_REG))
9173    (clobber (reg:SI PR_REG))]
9174   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9175   "jsr  @%0%#"
9176   [(set_attr "type" "call")
9177    (set (attr "fp_mode")
9178         (if_then_else (eq_attr "fpu_single" "yes")
9179                       (const_string "single") (const_string "double")))
9180    (set_attr "needs_delay_slot" "yes")])
9182 (define_insn "call_pop_compact_rettramp"
9183   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9184          (match_operand 1 "" ""))
9185    (match_operand 2 "immediate_operand" "n")
9186    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9187                                  (match_operand 3 "immediate_operand" "n")))
9188    (use (reg:SI R0_REG))
9189    (use (reg:SI R1_REG))
9190    (use (reg:PSI FPSCR_REG))
9191    (clobber (reg:SI R10_REG))
9192    (clobber (reg:SI PR_REG))]
9193   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9194   "jsr  @%0%#"
9195   [(set_attr "type" "call")
9196    (set (attr "fp_mode")
9197         (if_then_else (eq_attr "fpu_single" "yes")
9198                       (const_string "single") (const_string "double")))
9199    (set_attr "needs_delay_slot" "yes")])
9201 (define_expand "call_pop"
9202   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9203                     (match_operand 1 "" ""))
9204              (match_operand 2 "" "")
9205              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9206                                            (match_operand 3 "" "")))])]
9207   "TARGET_SHCOMPACT"
9209   rtx cookie_rtx;
9210   long cookie;
9211   rtx func;
9212   rtx r0, r1;
9214   gcc_assert (operands[2] && INTVAL (operands[2]));
9215   cookie_rtx = operands[2];
9216   cookie = INTVAL (cookie_rtx);
9217   func = XEXP (operands[0], 0);
9219   if (flag_pic)
9220     {
9221       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9222         {
9223           rtx reg = gen_reg_rtx (Pmode);
9224           emit_insn (gen_symGOTPLT2reg (reg, func));
9225           func = reg;
9226         }
9227       else
9228         func = legitimize_pic_address (func, Pmode, 0);
9229     }
9231   r0 = gen_rtx_REG (SImode, R0_REG);
9232   r1 = gen_rtx_REG (SImode, R1_REG);
9234   /* Since such a call function may use all call-clobbered
9235      registers, we force a mode switch earlier, so that we don't
9236      run out of registers when adjusting fpscr for the call.  */
9237   emit_insn (gen_force_mode_for_call ());
9239   operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9240                                  SFUNC_GOT);
9241   operands[0] = force_reg (SImode, operands[0]);
9243   emit_move_insn (r0, func);
9244   emit_move_insn (r1, cookie_rtx);
9246   if (cookie & CALL_COOKIE_RET_TRAMP (1))
9247     emit_call_insn (gen_call_pop_compact_rettramp
9248                      (operands[0], operands[1], operands[2], operands[3]));
9249   else
9250     emit_call_insn (gen_call_pop_compact
9251                      (operands[0], operands[1], operands[2], operands[3]));
9253   DONE;
9256 (define_expand "call_value"
9257   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9258                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9259                                  (match_operand 2 "" "")))
9260               (match_operand 3 "" "")
9261               (use (reg:PSI FPSCR_REG))
9262               (clobber (reg:SI PR_REG))])]
9263   ""
9265   if (TARGET_SHMEDIA)
9266     {
9267       operands[1] = shmedia_prepare_call_address (operands[1], 0);
9268       emit_call_insn (gen_call_value_media (operands[0], operands[1],
9269                                             operands[2]));
9270       DONE;
9271     }
9272   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9273     {
9274       rtx cookie_rtx = operands[3];
9275       long cookie = INTVAL (cookie_rtx);
9276       rtx func = XEXP (operands[1], 0);
9277       rtx r0, r1;
9279       if (flag_pic)
9280         {
9281           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9282             {
9283               rtx reg = gen_reg_rtx (Pmode);
9285               emit_insn (gen_symGOTPLT2reg (reg, func));
9286               func = reg;
9287             }
9288           else
9289             func = legitimize_pic_address (func, Pmode, 0);
9290         }
9292       r0 = gen_rtx_REG (SImode, R0_REG);
9293       r1 = gen_rtx_REG (SImode, R1_REG);
9295       /* Since such a call function may use all call-clobbered
9296          registers, we force a mode switch earlier, so that we don't
9297          run out of registers when adjusting fpscr for the call.  */
9298       emit_insn (gen_force_mode_for_call ());
9300       operands[1]
9301         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9302       operands[1] = force_reg (SImode, operands[1]);
9304       emit_move_insn (r0, func);
9305       emit_move_insn (r1, cookie_rtx);
9307       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9308         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9309                                                          operands[1],
9310                                                          operands[2],
9311                                                          operands[3]));
9312       else
9313         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9314                                                 operands[2], operands[3]));
9316       DONE;
9317     }
9318   else if (TARGET_SHCOMPACT && flag_pic
9319            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9320            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9321     {
9322       rtx reg = gen_reg_rtx (Pmode);
9324       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9325       XEXP (operands[1], 0) = reg;
9326     }
9327   if (!flag_pic && TARGET_SH2A
9328       && MEM_P (operands[1])
9329       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9330     {
9331       if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9332         {
9333           emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9334                                  XEXP (operands[1], 0), operands[2]));
9335           DONE;
9336         }
9337     }
9338   if (flag_pic && TARGET_SH2
9339       && MEM_P (operands[1])
9340       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9341     {
9342       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9343                                             operands[2]));
9344       DONE;
9345     }
9346   else
9347     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9349   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9350   DONE;
9353 (define_insn "sibcalli"
9354   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9355          (match_operand 1 "" ""))
9356    (use (reg:PSI FPSCR_REG))
9357    (return)]
9358   "TARGET_SH1"
9359   "jmp  @%0%#"
9360   [(set_attr "needs_delay_slot" "yes")
9361    (set (attr "fp_mode")
9362         (if_then_else (eq_attr "fpu_single" "yes")
9363                       (const_string "single") (const_string "double")))
9364    (set_attr "type" "jump_ind")])
9366 (define_insn "sibcalli_pcrel"
9367   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9368          (match_operand 1 "" ""))
9369    (use (match_operand 2 "" ""))
9370    (use (reg:PSI FPSCR_REG))
9371    (return)]
9372   "TARGET_SH2"
9374   return       "braf    %0"     "\n"
9375          "%O2:%#";
9377   [(set_attr "needs_delay_slot" "yes")
9378    (set (attr "fp_mode")
9379         (if_then_else (eq_attr "fpu_single" "yes")
9380                       (const_string "single") (const_string "double")))
9381    (set_attr "type" "jump_ind")])
9383 ;; This uses an unspec to describe that the symbol_ref is very close.
9384 (define_insn "sibcalli_thunk"
9385   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9386                              UNSPEC_THUNK))
9387          (match_operand 1 "" ""))
9388    (use (reg:PSI FPSCR_REG))
9389    (return)]
9390   "TARGET_SH1"
9391   "bra  %O0"
9392   [(set_attr "needs_delay_slot" "yes")
9393    (set (attr "fp_mode")
9394         (if_then_else (eq_attr "fpu_single" "yes")
9395                       (const_string "single") (const_string "double")))
9396    (set_attr "type" "jump")
9397    (set_attr "length" "2")])
9399 (define_insn_and_split "sibcall_pcrel"
9400   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9401          (match_operand 1 "" ""))
9402    (use (reg:PSI FPSCR_REG))
9403    (clobber (match_scratch:SI 2 "=k"))
9404    (return)]
9405   "TARGET_SH2"
9406   "#"
9407   "reload_completed"
9408   [(const_int 0)]
9410   rtx lab = PATTERN (gen_call_site ());
9411   rtx call_insn;
9413   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9414   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9415                                                   copy_rtx (lab)));
9416   SIBLING_CALL_P (call_insn) = 1;
9417   DONE;
9419   [(set_attr "needs_delay_slot" "yes")
9420    (set (attr "fp_mode")
9421         (if_then_else (eq_attr "fpu_single" "yes")
9422                       (const_string "single") (const_string "double")))
9423    (set_attr "type" "jump_ind")])
9425 (define_insn "sibcall_compact"
9426   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9427          (match_operand 1 "" ""))
9428    (return)
9429    (use (match_operand:SI 2 "register_operand" "z,x"))
9430    (use (reg:SI R1_REG))
9431    (use (reg:PSI FPSCR_REG))
9432    ;; We want to make sure the `x' above will only match MACH_REG
9433    ;; because sibcall_epilogue may clobber MACL_REG.
9434    (clobber (reg:SI MACL_REG))]
9435   "TARGET_SHCOMPACT"
9437   static const char* alt[] =
9438   {
9439        "jmp     @%0%#",
9441        "jmp     @%0"    "\n"
9442     "   sts     %2,r0"
9443   };
9444   return alt[which_alternative];
9446   [(set_attr "needs_delay_slot" "yes,no")
9447    (set_attr "length" "2,4")
9448    (set (attr "fp_mode") (const_string "single"))
9449    (set_attr "type" "jump_ind")])
9451 (define_insn "sibcall_media"
9452   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9453          (match_operand 1 "" ""))
9454    (use (reg:SI PR_MEDIA_REG))
9455    (return)]
9456   "TARGET_SHMEDIA"
9457   "blink        %0, r63"
9458   [(set_attr "type" "jump_media")])
9460 (define_expand "sibcall"
9461   [(parallel
9462     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9463            (match_operand 1 "" ""))
9464      (match_operand 2 "" "")
9465      (use (reg:PSI FPSCR_REG))
9466      (return)])]
9467   ""
9469   if (TARGET_SHMEDIA)
9470     {
9471       operands[0] = shmedia_prepare_call_address (operands[0], 1);
9472       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9473       DONE;
9474     }
9475   else if (TARGET_SHCOMPACT && operands[2]
9476            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9477     {
9478       rtx cookie_rtx = operands[2];
9479       long cookie = INTVAL (cookie_rtx);
9480       rtx func = XEXP (operands[0], 0);
9481       rtx mach, r1;
9483       if (flag_pic)
9484         {
9485           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9486             {
9487               rtx reg = gen_reg_rtx (Pmode);
9489               emit_insn (gen_symGOT2reg (reg, func));
9490               func = reg;
9491             }
9492           else
9493             func = legitimize_pic_address (func, Pmode, 0);
9494         }
9496       /* FIXME: if we could tell whether all argument registers are
9497          already taken, we could decide whether to force the use of
9498          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9499          simple way to tell.  We could use the CALL_COOKIE, but we
9500          can't currently tell a register used for regular argument
9501          passing from one that is unused.  If we leave it up to reload
9502          to decide which register to use, it seems to always choose
9503          R0_REG, which leaves no available registers in SIBCALL_REGS
9504          to hold the address of the trampoline.  */
9505       mach = gen_rtx_REG (SImode, MACH_REG);
9506       r1 = gen_rtx_REG (SImode, R1_REG);
9508       /* Since such a call function may use all call-clobbered
9509          registers, we force a mode switch earlier, so that we don't
9510          run out of registers when adjusting fpscr for the call.  */
9511       emit_insn (gen_force_mode_for_call ());
9513       operands[0]
9514         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9515       operands[0] = force_reg (SImode, operands[0]);
9517       /* We don't need a return trampoline, since the callee will
9518          return directly to the upper caller.  */
9519       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9520         {
9521           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9522           cookie_rtx = GEN_INT (cookie);
9523         }
9525       emit_move_insn (mach, func);
9526       emit_move_insn (r1, cookie_rtx);
9528       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9529       DONE;
9530     }
9531   else if (TARGET_SHCOMPACT && flag_pic
9532            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9533            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9534     {
9535       rtx reg = gen_reg_rtx (Pmode);
9537       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9538       XEXP (operands[0], 0) = reg;
9539     }
9540   if (flag_pic && TARGET_SH2
9541       && MEM_P (operands[0])
9542       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9543       /* The PLT needs the PIC register, but the epilogue would have
9544          to restore it, so we can only use PC-relative PIC calls for
9545          static functions.  */
9546       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9547     {
9548       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9549       DONE;
9550     }
9551   else
9552     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9554   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9555   DONE;
9558 (define_insn "sibcall_valuei"
9559   [(set (match_operand 0 "" "=rf")
9560         (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9561               (match_operand 2 "" "")))
9562    (use (reg:PSI FPSCR_REG))
9563    (return)]
9564   "TARGET_SH1"
9565   "jmp  @%1%#"
9566   [(set_attr "needs_delay_slot" "yes")
9567    (set (attr "fp_mode")
9568         (if_then_else (eq_attr "fpu_single" "yes")
9569                       (const_string "single") (const_string "double")))
9570    (set_attr "type" "jump_ind")])
9572 (define_insn "sibcall_valuei_pcrel"
9573   [(set (match_operand 0 "" "=rf")
9574         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9575               (match_operand 2 "" "")))
9576    (use (match_operand 3 "" ""))
9577    (use (reg:PSI FPSCR_REG))
9578    (return)]
9579   "TARGET_SH2"
9581   return       "braf    %1"     "\n"
9582          "%O3:%#";
9584   [(set_attr "needs_delay_slot" "yes")
9585    (set (attr "fp_mode")
9586         (if_then_else (eq_attr "fpu_single" "yes")
9587                       (const_string "single") (const_string "double")))
9588    (set_attr "type" "jump_ind")])
9590 (define_insn_and_split "sibcall_value_pcrel"
9591   [(set (match_operand 0 "" "=rf")
9592         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9593               (match_operand 2 "" "")))
9594    (use (reg:PSI FPSCR_REG))
9595    (clobber (match_scratch:SI 3 "=k"))
9596    (return)]
9597   "TARGET_SH2"
9598   "#"
9599   "reload_completed"
9600   [(const_int 0)]
9602   rtx lab = PATTERN (gen_call_site ());
9603   rtx call_insn;
9605   emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9606   call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9607                                                         operands[3],
9608                                                         operands[2],
9609                                                         copy_rtx (lab)));
9610   SIBLING_CALL_P (call_insn) = 1;
9611   DONE;
9613   [(set_attr "needs_delay_slot" "yes")
9614    (set (attr "fp_mode")
9615         (if_then_else (eq_attr "fpu_single" "yes")
9616                       (const_string "single") (const_string "double")))
9617    (set_attr "type" "jump_ind")])
9619 (define_insn "sibcall_value_compact"
9620   [(set (match_operand 0 "" "=rf,rf")
9621         (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9622               (match_operand 2 "" "")))
9623    (return)
9624    (use (match_operand:SI 3 "register_operand" "z,x"))
9625    (use (reg:SI R1_REG))
9626    (use (reg:PSI FPSCR_REG))
9627    ;; We want to make sure the `x' above will only match MACH_REG
9628    ;; because sibcall_epilogue may clobber MACL_REG.
9629    (clobber (reg:SI MACL_REG))]
9630   "TARGET_SHCOMPACT"
9632   static const char* alt[] =
9633   {
9634        "jmp     @%1%#",
9636        "jmp     @%1"    "\n"
9637     "   sts     %3,r0"
9638   };
9639   return alt[which_alternative];
9641   [(set_attr "needs_delay_slot" "yes,no")
9642    (set_attr "length" "2,4")
9643    (set (attr "fp_mode") (const_string "single"))
9644    (set_attr "type" "jump_ind")])
9646 (define_insn "sibcall_value_media"
9647   [(set (match_operand 0 "" "=rf")
9648         (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9649               (match_operand 2 "" "")))
9650    (use (reg:SI PR_MEDIA_REG))
9651    (return)]
9652   "TARGET_SHMEDIA"
9653   "blink        %1, r63"
9654   [(set_attr "type" "jump_media")])
9656 (define_expand "sibcall_value"
9657   [(parallel
9658     [(set (match_operand 0 "arith_reg_operand" "")
9659           (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9660                 (match_operand 2 "" "")))
9661      (match_operand 3 "" "")
9662      (use (reg:PSI FPSCR_REG))
9663      (return)])]
9664   ""
9666   if (TARGET_SHMEDIA)
9667     {
9668       operands[1] = shmedia_prepare_call_address (operands[1], 1);
9669       emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9670                                                operands[2]));
9671       DONE;
9672     }
9673   else if (TARGET_SHCOMPACT && operands[3]
9674            && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9675     {
9676       rtx cookie_rtx = operands[3];
9677       long cookie = INTVAL (cookie_rtx);
9678       rtx func = XEXP (operands[1], 0);
9679       rtx mach, r1;
9681       if (flag_pic)
9682         {
9683           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9684             {
9685               rtx reg = gen_reg_rtx (Pmode);
9687               emit_insn (gen_symGOT2reg (reg, func));
9688               func = reg;
9689             }
9690           else
9691             func = legitimize_pic_address (func, Pmode, 0);
9692         }
9694       /* FIXME: if we could tell whether all argument registers are
9695          already taken, we could decide whether to force the use of
9696          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9697          simple way to tell.  We could use the CALL_COOKIE, but we
9698          can't currently tell a register used for regular argument
9699          passing from one that is unused.  If we leave it up to reload
9700          to decide which register to use, it seems to always choose
9701          R0_REG, which leaves no available registers in SIBCALL_REGS
9702          to hold the address of the trampoline.  */
9703       mach = gen_rtx_REG (SImode, MACH_REG);
9704       r1 = gen_rtx_REG (SImode, R1_REG);
9706       /* Since such a call function may use all call-clobbered
9707          registers, we force a mode switch earlier, so that we don't
9708          run out of registers when adjusting fpscr for the call.  */
9709       emit_insn (gen_force_mode_for_call ());
9711       operands[1]
9712         = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9713       operands[1] = force_reg (SImode, operands[1]);
9715       /* We don't need a return trampoline, since the callee will
9716          return directly to the upper caller.  */
9717       if (cookie & CALL_COOKIE_RET_TRAMP (1))
9718         {
9719           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9720           cookie_rtx = GEN_INT (cookie);
9721         }
9723       emit_move_insn (mach, func);
9724       emit_move_insn (r1, cookie_rtx);
9726       emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9727                                                  operands[2], mach));
9728       DONE;
9729     }
9730   else if (TARGET_SHCOMPACT && flag_pic
9731            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9732            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9733     {
9734       rtx reg = gen_reg_rtx (Pmode);
9736       emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9737       XEXP (operands[1], 0) = reg;
9738     }
9739   if (flag_pic && TARGET_SH2
9740       && MEM_P (operands[1])
9741       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9742       /* The PLT needs the PIC register, but the epilogue would have
9743          to restore it, so we can only use PC-relative PIC calls for
9744          static functions.  */
9745       && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9746     {
9747       emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9748                                                XEXP (operands[1], 0),
9749                                                operands[2]));
9750       DONE;
9751     }
9752   else
9753     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9755   emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9756   DONE;
9759 (define_insn "call_value_pop_compact"
9760   [(set (match_operand 0 "" "=rf")
9761         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9762               (match_operand 2 "" "")))
9763    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9764                                  (match_operand 4 "immediate_operand" "n")))
9765    (match_operand 3 "immediate_operand" "n")
9766    (use (reg:SI R0_REG))
9767    (use (reg:SI R1_REG))
9768    (use (reg:PSI FPSCR_REG))
9769    (clobber (reg:SI PR_REG))]
9770   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9771   "jsr  @%1%#"
9772   [(set_attr "type" "call")
9773    (set (attr "fp_mode")
9774         (if_then_else (eq_attr "fpu_single" "yes")
9775                       (const_string "single") (const_string "double")))
9776    (set_attr "needs_delay_slot" "yes")])
9778 (define_insn "call_value_pop_compact_rettramp"
9779   [(set (match_operand 0 "" "=rf")
9780         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9781               (match_operand 2 "" "")))
9782    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9783                                  (match_operand 4 "immediate_operand" "n")))
9784    (match_operand 3 "immediate_operand" "n")
9785    (use (reg:SI R0_REG))
9786    (use (reg:SI R1_REG))
9787    (use (reg:PSI FPSCR_REG))
9788    (clobber (reg:SI R10_REG))
9789    (clobber (reg:SI PR_REG))]
9790   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9791   "jsr  @%1%#"
9792   [(set_attr "type" "call")
9793    (set (attr "fp_mode")
9794         (if_then_else (eq_attr "fpu_single" "yes")
9795                       (const_string "single") (const_string "double")))
9796    (set_attr "needs_delay_slot" "yes")])
9798 (define_expand "call_value_pop"
9799   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9800                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9801                                  (match_operand 2 "" "")))
9802               (match_operand 3 "" "")
9803               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9804                                             (match_operand 4 "" "")))])]
9805   "TARGET_SHCOMPACT"
9807   rtx cookie_rtx;
9808   long cookie;
9809   rtx func;
9810   rtx r0, r1;
9812   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9813   cookie_rtx = operands[3];
9814   cookie = INTVAL (cookie_rtx);
9815   func = XEXP (operands[1], 0);
9817   if (flag_pic)
9818     {
9819       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9820         {
9821           rtx reg = gen_reg_rtx (Pmode);
9823           emit_insn (gen_symGOTPLT2reg (reg, func));
9824           func = reg;
9825         }
9826       else
9827         func = legitimize_pic_address (func, Pmode, 0);
9828     }
9830   r0 = gen_rtx_REG (SImode, R0_REG);
9831   r1 = gen_rtx_REG (SImode, R1_REG);
9833   /* Since such a call function may use all call-clobbered
9834      registers, we force a mode switch earlier, so that we don't
9835      run out of registers when adjusting fpscr for the call.  */
9836   emit_insn (gen_force_mode_for_call ());
9838   operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9839                                  SFUNC_GOT);
9840   operands[1] = force_reg (SImode, operands[1]);
9842   emit_move_insn (r0, func);
9843   emit_move_insn (r1, cookie_rtx);
9845   if (cookie & CALL_COOKIE_RET_TRAMP (1))
9846     emit_call_insn (gen_call_value_pop_compact_rettramp
9847                         (operands[0], operands[1], operands[2],
9848                          operands[3], operands[4]));
9849   else
9850     emit_call_insn (gen_call_value_pop_compact
9851                         (operands[0], operands[1], operands[2],
9852                          operands[3], operands[4]));
9854   DONE;
9857 (define_expand "sibcall_epilogue"
9858   [(return)]
9859   ""
9861   sh_expand_epilogue (true);
9862   if (TARGET_SHCOMPACT)
9863     {
9864       rtx insn, set;
9866       /* If epilogue clobbers r0, preserve it in macl.  */
9867       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9868         if ((set = single_set (insn))
9869             && REG_P (SET_DEST (set))
9870             && REGNO (SET_DEST (set)) == R0_REG)
9871           {
9872             rtx r0 = gen_rtx_REG (SImode, R0_REG);
9873             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
9875             /* We can't tell at this point whether the sibcall is a
9876                sibcall_compact and, if it is, whether it uses r0 or
9877                mach as operand 2, so let the instructions that
9878                preserve r0 be optimized away if r0 turns out to be
9879                dead.  */
9880             emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9881             emit_move_insn (r0, tmp);
9882             break;
9883           }
9884     }
9885   DONE;
9888 (define_insn "indirect_jump_compact"
9889   [(set (pc)
9890         (match_operand:SI 0 "arith_reg_operand" "r"))]
9891   "TARGET_SH1"
9892   "jmp  @%0%#"
9893   [(set_attr "needs_delay_slot" "yes")
9894    (set_attr "type" "jump_ind")])
9896 (define_expand "indirect_jump"
9897   [(set (pc)
9898         (match_operand 0 "register_operand" ""))]
9899   ""
9901   if (GET_MODE (operands[0]) != Pmode)
9902     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
9905 ;; The use of operand 1 / 2 helps us distinguish case table jumps
9906 ;; which can be present in structured code from indirect jumps which can not
9907 ;; be present in structured code.  This allows -fprofile-arcs to work.
9909 ;; For SH1 processors.
9910 (define_insn "casesi_jump_1"
9911   [(set (pc)
9912         (match_operand:SI 0 "register_operand" "r"))
9913    (use (label_ref (match_operand 1 "" "")))]
9914   "TARGET_SH1"
9915   "jmp  @%0%#"
9916   [(set_attr "needs_delay_slot" "yes")
9917    (set_attr "type" "jump_ind")])
9919 ;; For all later processors.
9920 (define_insn "casesi_jump_2"
9921   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
9922                       (label_ref (match_operand 1 "" ""))))
9923    (use (label_ref (match_operand 2 "" "")))]
9924   "TARGET_SH2
9925    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
9926   "braf %0%#"
9927   [(set_attr "needs_delay_slot" "yes")
9928    (set_attr "type" "jump_ind")])
9930 (define_insn "casesi_jump_media"
9931   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
9932    (use (label_ref (match_operand 1 "" "")))]
9933   "TARGET_SHMEDIA"
9934   "blink        %0, r63"
9935   [(set_attr "type" "jump_media")])
9937 ;; Call subroutine returning any type.
9938 ;; ??? This probably doesn't work.
9939 (define_expand "untyped_call"
9940   [(parallel [(call (match_operand 0 "" "")
9941                     (const_int 0))
9942               (match_operand 1 "" "")
9943               (match_operand 2 "" "")])]
9944   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
9946   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
9948   for (int i = 0; i < XVECLEN (operands[2], 0); i++)
9949     {
9950       rtx set = XVECEXP (operands[2], 0, i);
9951       emit_move_insn (SET_DEST (set), SET_SRC (set));
9952     }
9954   /* The optimizer does not know that the call sets the function value
9955      registers we stored in the result block.  We avoid problems by
9956      claiming that all hard registers are used and clobbered at this
9957      point.  */
9958   emit_insn (gen_blockage ());
9960   DONE;
9963 ;; ------------------------------------------------------------------------
9964 ;; Misc insns
9965 ;; ------------------------------------------------------------------------
9967 (define_insn "dect"
9968   [(set (reg:SI T_REG)
9969         (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
9970    (set (match_operand:SI 0 "arith_reg_dest" "=r")
9971         (plus:SI (match_dup 1) (const_int -1)))]
9972   "TARGET_SH2"
9973   "dt   %0"
9974   [(set_attr "type" "arith")])
9976 (define_insn "nop"
9977   [(const_int 0)]
9978   ""
9979   "nop")
9981 ;; Load address of a label. This is only generated by the casesi expand,
9982 ;; and by machine_dependent_reorg (fixing up fp moves).
9983 ;; This must use unspec, because this only works for labels that are
9984 ;; within range.
9985 (define_insn "mova"
9986   [(set (reg:SI R0_REG)
9987         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
9988   "TARGET_SH1"
9989   "mova %O0,r0"
9990   [(set_attr "in_delay_slot" "no")
9991    (set_attr "type" "arith")])
9993 ;; machine_dependent_reorg will make this a `mova'.
9994 (define_insn "mova_const"
9995   [(set (reg:SI R0_REG)
9996         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
9997   "TARGET_SH1"
9998   "#"
9999   [(set_attr "in_delay_slot" "no")
10000    (set_attr "type" "arith")])
10002 ;; Loads of the GOTPC relocation values must not be optimized away
10003 ;; by e.g. any kind of CSE and must stay as they are.  Although there
10004 ;; are other various ways to ensure this, we use an artificial counter
10005 ;; operand to generate unique symbols.
10006 (define_expand "GOTaddr2picreg"
10007   [(set (reg:SI R0_REG)
10008         (unspec:SI [(const:SI (unspec:SI [(match_dup 2)
10009                                           (match_operand:SI 0 "" "")]
10010                                          UNSPEC_PIC))] UNSPEC_MOVA))
10011    (set (match_dup 1)
10012         (const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC)))
10013    (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))]
10014   ""
10016   if (TARGET_VXWORKS_RTP)
10017     {
10018       rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10019       rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10020       emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10021       DONE;
10022     }
10024   operands[1] = gen_rtx_REG (Pmode, PIC_REG);
10025   operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10027   if (TARGET_SHMEDIA)
10028     {
10029       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10030       rtx pic = operands[0];
10031       rtx lab = PATTERN (gen_call_site ());
10032       rtx insn, equiv;
10034       equiv = operands[2];
10035       operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab),
10036                                     UNSPEC_PCREL_SYMOFF);
10037       operands[2] = gen_rtx_CONST (Pmode, operands[2]);
10039       if (Pmode == SImode)
10040         {
10041           emit_insn (gen_movsi_const (pic, operands[2]));
10042           emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10043         }
10044       else
10045         {
10046           emit_insn (gen_movdi_const (pic, operands[2]));
10047           emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10048         }
10050       insn = emit_move_insn (operands[1], tr);
10052       set_unique_reg_note (insn, REG_EQUAL, equiv);
10054       DONE;
10055     }
10058 ;; A helper for GOTaddr2picreg to finish up the initialization of the
10059 ;; PIC register.
10060 (define_expand "vxworks_picreg"
10061   [(set (reg:SI PIC_REG)
10062         (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10063    (set (reg:SI R0_REG)
10064         (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10065    (set (reg:SI PIC_REG)
10066         (mem:SI (reg:SI PIC_REG)))
10067    (set (reg:SI PIC_REG)
10068         (mem:SI (plus:SI (reg:SI PIC_REG)
10069                          (reg:SI R0_REG))))]
10070   "TARGET_VXWORKS_RTP")
10072 (define_insn "*ptb"
10073   [(set (match_operand 0 "target_reg_operand" "=b")
10074         (const (unspec [(match_operand 1 "" "Csy")]
10075                              UNSPEC_DATALABEL)))]
10076   "TARGET_SHMEDIA && flag_pic
10077    && satisfies_constraint_Csy (operands[1])"
10078   "ptb/u        datalabel %1, %0"
10079   [(set_attr "type" "ptabs_media")
10080    (set_attr "length" "*")])
10082 (define_insn "ptrel_si"
10083   [(set (match_operand:SI 0 "target_reg_operand" "=b")
10084         (plus:SI (match_operand:SI 1 "register_operand" "r")
10085               (pc)))
10086    (match_operand:SI 2 "" "")]
10087   "TARGET_SHMEDIA"
10088   "%O2: ptrel/u %1, %0"
10089   [(set_attr "type" "ptabs_media")])
10091 (define_insn "ptrel_di"
10092   [(set (match_operand:DI 0 "target_reg_operand" "=b")
10093         (plus:DI (match_operand:DI 1 "register_operand" "r")
10094               (pc)))
10095    (match_operand:DI 2 "" "")]
10096   "TARGET_SHMEDIA"
10097   "%O2: ptrel/u %1, %0"
10098   [(set_attr "type" "ptabs_media")])
10100 (define_expand "builtin_setjmp_receiver"
10101   [(match_operand 0 "" "")]
10102   "flag_pic"
10104   emit_insn (gen_GOTaddr2picreg (const0_rtx));
10105   DONE;
10108 (define_expand "call_site"
10109   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10110   "TARGET_SH1"
10112   static HOST_WIDE_INT i = 0;
10113   operands[0] = GEN_INT (i);
10114   i++;
10117 ;; op0 = op1 + r12 but hide it before reload completed.  See the comment
10118 ;; in symGOT_load expand.
10119 (define_insn_and_split "chk_guard_add"
10120   [(set (match_operand:SI 0 "register_operand" "=&r")
10121         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10122                     (reg:SI PIC_REG)]
10123                    UNSPEC_CHKADD))]
10124   "TARGET_SH1"
10125   "#"
10126   "TARGET_SH1 && reload_completed"
10127   [(set (match_dup 0) (reg:SI PIC_REG))
10128    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10129   ""
10130   [(set_attr "type" "arith")])
10132 (define_expand "sym_label2reg"
10133   [(set (match_operand:SI 0 "" "")
10134         (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10135                               (const (plus:SI (match_operand:SI 2 "" "")
10136                                               (const_int 2)))]
10137                              UNSPEC_SYMOFF)))]
10138   "TARGET_SH1" "")
10140 (define_expand "symGOT_load"
10141   [(set (match_dup 2) (match_operand 1 "" ""))
10142    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10143    (set (match_operand 0 "" "") (mem (match_dup 3)))]
10144   ""
10146   rtx mem;
10147   bool stack_chk_guard_p = false;
10149   operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10150   operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10152   if (!TARGET_SHMEDIA
10153       && flag_stack_protect
10154       && GET_CODE (operands[1]) == CONST
10155       && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10156       && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10157       && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10158                  "__stack_chk_guard") == 0)
10159     stack_chk_guard_p = true;
10161   /* Use R0 to avoid long R0 liveness which stack-protector tends to
10162      produce.  */
10163   if (stack_chk_guard_p && ! reload_in_progress && ! reload_completed)
10164     operands[2] = gen_rtx_REG (Pmode, R0_REG);
10166   if (TARGET_SHMEDIA)
10167     {
10168       rtx reg = operands[2];
10170       if (Pmode == DImode)
10171         {      
10172           if (flag_pic > 1)
10173             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10174           else
10175             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10176         }
10177       else
10178         {
10179           if (flag_pic > 1)
10180             emit_insn (gen_movsi_const (reg, operands[1]));
10181           else
10182             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10183         }
10184     }
10185   else
10186     emit_move_insn (operands[2], operands[1]);
10188   /* When stack protector inserts codes after the result is set to
10189      R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
10190      insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10191      when rX is a GOT address for the guard symbol.  Ugly but doesn't
10192      matter because this is a rare situation.  */
10193   if (stack_chk_guard_p)
10194     emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10195   else
10196     emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10197                                                gen_rtx_REG (Pmode, PIC_REG)));
10199   /* N.B. This is not constant for a GOTPLT relocation.  */
10200   mem = gen_rtx_MEM (Pmode, operands[3]);
10201   MEM_NOTRAP_P (mem) = 1;
10202   /* ??? Should we have a special alias set for the GOT?  */
10203   emit_move_insn (operands[0], mem);
10205   DONE;
10208 (define_expand "sym2GOT"
10209   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10210   ""
10211   "")
10213 (define_expand "symGOT2reg"
10214   [(match_operand 0 "" "") (match_operand 1 "" "")]
10215   ""
10217   rtx gotsym, insn;
10219   gotsym = gen_sym2GOT (operands[1]);
10220   PUT_MODE (gotsym, Pmode);
10221   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10223   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10225   DONE;
10228 (define_expand "symGOTPLT2reg"
10229   [(match_operand 0 "" "") (match_operand 1 "" "")]
10230   ""
10232   rtx pltsym = gen_rtx_CONST (Pmode,
10233                               gen_rtx_UNSPEC (Pmode,
10234                                               gen_rtvec (1, operands[1]),
10235                                               UNSPEC_GOTPLT));
10236   emit_insn (gen_symGOT_load (operands[0], pltsym));
10237   DONE;
10240 (define_expand "sym2GOTOFF"
10241   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10242   ""
10243   "")
10245 (define_expand "symGOTOFF2reg"
10246   [(match_operand 0 "" "") (match_operand 1 "" "")]
10247   ""
10249   rtx gotoffsym, insn;
10250   rtx t = (!can_create_pseudo_p ()
10251            ? operands[0]
10252            : gen_reg_rtx (GET_MODE (operands[0])));
10254   gotoffsym = gen_sym2GOTOFF (operands[1]);
10255   PUT_MODE (gotoffsym, Pmode);
10256   emit_move_insn (t, gotoffsym);
10257   insn = emit_move_insn (operands[0],
10258                          gen_rtx_PLUS (Pmode, t,
10259                                        gen_rtx_REG (Pmode, PIC_REG)));
10261   set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10263   DONE;
10266 (define_expand "symPLT_label2reg"
10267   [(set (match_operand:SI 0 "" "")
10268         (const:SI
10269          (unspec:SI
10270           [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10271            (const:SI (plus:SI (match_operand:SI 2 "" "")
10272                               (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10273    ;; Even though the PIC register is not really used by the call
10274    ;; sequence in which this is expanded, the PLT code assumes the PIC
10275    ;; register is set, so we must not skip its initialization.  Since
10276    ;; we only use this expand as part of calling sequences, and never
10277    ;; to take the address of a function, this is the best point to
10278    ;; insert the (use).  Using the PLT to take the address of a
10279    ;; function would be wrong, not only because the PLT entry could
10280    ;; then be called from a function that doesn't initialize the PIC
10281    ;; register to the proper GOT, but also because pointers to the
10282    ;; same function might not compare equal, should they be set by
10283    ;; different shared libraries.
10284    (use (reg:SI PIC_REG))]
10285   "TARGET_SH1"
10286   "")
10288 (define_expand "sym2PIC"
10289   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10290   ""
10291   "")
10293 ;; -------------------------------------------------------------------------
10294 ;; TLS code generation.
10296 ;; FIXME: The multi-insn asm blocks should be converted to use
10297 ;; define_insn_and_split.
10298 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10299 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10300 ;; for details.
10302 (define_insn "tls_global_dynamic"
10303   [(set (match_operand:SI 0 "register_operand" "=&z")
10304         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10305                                   UNSPEC_TLSGD))
10306               (const_int 0)))
10307    (use (reg:PSI FPSCR_REG))
10308    (use (reg:SI PIC_REG))
10309    (clobber (reg:SI PR_REG))
10310    (clobber (scratch:SI))]
10311   "TARGET_SH1"
10313   return       "mov.l   1f,r4"                  "\n"
10314          "      mova    2f,r0"                  "\n"
10315          "      mov.l   2f,r1"                  "\n"
10316          "      add     r0,r1"                  "\n"
10317          "      jsr     @r1"                    "\n"
10318          "      add     r12,r4"                 "\n"
10319          "      bra     3f"                     "\n"
10320          "      nop"                            "\n"
10321          "      .align  2"                      "\n"
10322          "1:    .long   %a1@TLSGD"              "\n"
10323          "2:    .long   __tls_get_addr@PLT"     "\n"
10324          "3:";
10326   [(set_attr "type" "tls_load")
10327    (set_attr "length" "26")])
10329 (define_insn "tls_local_dynamic"
10330   [(set (match_operand:SI 0 "register_operand" "=&z")
10331         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10332                                   UNSPEC_TLSLDM))
10333               (const_int 0)))
10334    (use (reg:PSI FPSCR_REG))
10335    (use (reg:SI PIC_REG))
10336    (clobber (reg:SI PR_REG))
10337    (clobber (scratch:SI))]
10338   "TARGET_SH1"
10340   return       "mov.l   1f,r4"                  "\n"
10341          "      mova    2f,r0"                  "\n"
10342          "      mov.l   2f,r1"                  "\n"
10343          "      add     r0,r1"                  "\n"
10344          "      jsr     @r1"                    "\n"
10345          "      add     r12,r4"                 "\n"
10346          "      bra     3f"                     "\n"
10347          "      nop"                            "\n"
10348          "      .align  2"                      "\n"
10349          "1:    .long   %a1@TLSLDM"             "\n"
10350          "2:    .long   __tls_get_addr@PLT"     "\n"
10351          "3:";
10353   [(set_attr "type" "tls_load")
10354    (set_attr "length" "26")])
10356 (define_expand "sym2DTPOFF"
10357   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10358   ""
10359   "")
10361 (define_expand "symDTPOFF2reg"
10362   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10363   ""
10365   rtx dtpoffsym;
10366   rtx t = (!can_create_pseudo_p ()
10367            ? operands[0]
10368            : gen_reg_rtx (GET_MODE (operands[0])));
10370   dtpoffsym = gen_sym2DTPOFF (operands[1]);
10371   PUT_MODE (dtpoffsym, Pmode);
10372   emit_move_insn (t, dtpoffsym);
10373   emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10374   DONE;
10377 (define_expand "sym2GOTTPOFF"
10378   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10379   ""
10380   "")
10382 (define_insn "tls_initial_exec"
10383   [(set (match_operand:SI 0 "register_operand" "=&r")
10384         (unspec:SI [(match_operand:SI 1 "" "")]
10385                     UNSPEC_TLSIE))
10386    (use (reg:SI GBR_REG))
10387    (use (reg:SI PIC_REG))
10388    (clobber (reg:SI R0_REG))]
10389   ""
10391   return       "mov.l   1f,r0"          "\n"
10392          "      stc     gbr,%0"         "\n"
10393          "      mov.l   @(r0,r12),r0"   "\n"
10394          "      bra     2f"             "\n"
10395          "      add     r0,%0"          "\n"
10396          "      .align  2"              "\n"
10397          "1:    .long   %a1"            "\n"
10398          "2:";
10400   [(set_attr "type" "tls_load")
10401    (set_attr "length" "16")])
10403 (define_expand "sym2TPOFF"
10404   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10405   ""
10406   "")
10408 (define_expand "symTPOFF2reg"
10409   [(match_operand 0 "" "") (match_operand 1 "" "")]
10410   ""
10412   rtx tpoffsym;
10414   tpoffsym = gen_sym2TPOFF (operands[1]);
10415   PUT_MODE (tpoffsym, Pmode);
10416   emit_move_insn (operands[0], tpoffsym);
10417   DONE;
10420 ;;------------------------------------------------------------------------------
10421 ;; Thread pointer getter and setter.
10423 ;; On SH the thread pointer is kept in the GBR.
10424 ;; These patterns are usually expanded from the respective built-in functions.
10425 (define_expand "get_thread_pointersi"
10426   [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10427   "TARGET_SH1")
10429 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10430 (define_insn "store_gbr"
10431   [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10432   ""
10433   "stc  gbr,%0"
10434   [(set_attr "type" "tls_load")])
10436 (define_expand "set_thread_pointersi"
10437   [(set (reg:SI GBR_REG)
10438         (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10439          UNSPECV_GBR))]
10440   "TARGET_SH1")
10442 (define_insn "load_gbr"
10443   [(set (reg:SI GBR_REG)
10444         (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10445          UNSPECV_GBR))]
10446   "TARGET_SH1"
10447   "ldc  %0,gbr"
10448   [(set_attr "type" "move")])
10450 ;;------------------------------------------------------------------------------
10451 ;; Thread pointer relative memory loads and stores.
10453 ;; On SH there are GBR displacement address modes which can be utilized to
10454 ;; access memory behind the thread pointer.
10455 ;; Since we do not allow using GBR for general purpose memory accesses, these
10456 ;; GBR addressing modes are formed by the combine pass.
10457 ;; This could be done with fewer patterns than below by using a mem predicate
10458 ;; for the GBR mem, but then reload would try to reload addresses with a
10459 ;; zero displacement for some strange reason.
10461 (define_insn "*mov<mode>_gbr_load"
10462   [(set (match_operand:QIHISI 0 "register_operand" "=z")
10463         (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10464                              (match_operand:QIHISI 1 "gbr_displacement"))))]
10465   "TARGET_SH1"
10466   "mov.<bwl>    @(%O1,gbr),%0"
10467   [(set_attr "type" "load")])
10469 (define_insn "*mov<mode>_gbr_load"
10470   [(set (match_operand:QIHISI 0 "register_operand" "=z")
10471         (mem:QIHISI (reg:SI GBR_REG)))]
10472   "TARGET_SH1"
10473   "mov.<bwl>    @(0,gbr),%0"
10474   [(set_attr "type" "load")])
10476 (define_insn "*mov<mode>_gbr_load"
10477   [(set (match_operand:SI 0 "register_operand" "=z")
10478         (sign_extend:SI
10479           (mem:QIHI (plus:SI (reg:SI GBR_REG)
10480                              (match_operand:QIHI 1 "gbr_displacement")))))]
10481   "TARGET_SH1"
10482   "mov.<bw>     @(%O1,gbr),%0"
10483   [(set_attr "type" "load")])
10485 (define_insn "*mov<mode>_gbr_load"
10486   [(set (match_operand:SI 0 "register_operand" "=z")
10487         (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10488   "TARGET_SH1"
10489   "mov.<bw>     @(0,gbr),%0"
10490   [(set_attr "type" "load")])
10492 (define_insn "*mov<mode>_gbr_store"
10493   [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10494                              (match_operand:QIHISI 0 "gbr_displacement")))
10495         (match_operand:QIHISI 1 "register_operand" "z"))]
10496   "TARGET_SH1"
10497   "mov.<bwl>    %1,@(%O0,gbr)"
10498   [(set_attr "type" "store")])
10500 (define_insn "*mov<mode>_gbr_store"
10501   [(set (mem:QIHISI (reg:SI GBR_REG))
10502         (match_operand:QIHISI 0 "register_operand" "z"))]
10503   "TARGET_SH1"
10504   "mov.<bwl>    %0,@(0,gbr)"
10505   [(set_attr "type" "store")])
10507 ;; DImode memory accesses have to be split in two SImode accesses.
10508 ;; Split them before reload, so that it gets a better chance to figure out
10509 ;; how to deal with the R0 restriction for the individual SImode accesses.
10510 ;; Do not match this insn during or after reload because it can't be split
10511 ;; afterwards.
10512 (define_insn_and_split "*movdi_gbr_load"
10513   [(set (match_operand:DI 0 "register_operand")
10514         (match_operand:DI 1 "gbr_address_mem"))]
10515   "TARGET_SH1 && can_create_pseudo_p ()"
10516   "#"
10517   "&& 1"
10518   [(set (match_dup 3) (match_dup 5))
10519    (set (match_dup 4) (match_dup 6))]
10521   /* Swap low/high part load order on little endian, so that the result reg
10522      of the second load can be used better.  */
10523   int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10524   operands[3 + off] = gen_lowpart (SImode, operands[0]);
10525   operands[5 + off] = gen_lowpart (SImode, operands[1]);
10526   operands[4 - off] = gen_highpart (SImode, operands[0]);
10527   operands[6 - off] = gen_highpart (SImode, operands[1]);
10530 (define_insn_and_split "*movdi_gbr_store"
10531   [(set (match_operand:DI 0 "gbr_address_mem")
10532         (match_operand:DI 1 "register_operand"))]
10533   "TARGET_SH1 && can_create_pseudo_p ()"
10534   "#"
10535   "&& 1"
10536   [(set (match_dup 3) (match_dup 5))
10537    (set (match_dup 4) (match_dup 6))]
10539   /* Swap low/high part store order on big endian, so that stores of function
10540      call results can save a reg copy.  */
10541   int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10542   operands[3 + off] = gen_lowpart (SImode, operands[0]);
10543   operands[5 + off] = gen_lowpart (SImode, operands[1]);
10544   operands[4 - off] = gen_highpart (SImode, operands[0]);
10545   operands[6 - off] = gen_highpart (SImode, operands[1]);
10548 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
10549 ;; in particular when the displacements are in the range of the regular move
10550 ;; insns.  Thus, in the first split pass after the combine pass we search
10551 ;; for missed opportunities and try to fix them up ourselves.
10552 ;; If an equivalent GBR address can be determined the load / store is split
10553 ;; into one of the GBR load / store patterns.
10554 ;; All of that must happen before reload (GBR address modes use R0 as the
10555 ;; other operand) and there's no point of doing it if the GBR is not
10556 ;; referenced in a function at all.
10557 (define_split
10558   [(set (match_operand:QIHISIDI 0 "register_operand")
10559         (match_operand:QIHISIDI 1 "memory_operand"))]
10560   "TARGET_SH1 && !reload_in_progress && !reload_completed
10561    && df_regs_ever_live_p (GBR_REG)"
10562   [(set (match_dup 0) (match_dup 1))]
10564   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10565   if (gbr_mem != NULL_RTX)
10566     operands[1] = replace_equiv_address (operands[1], gbr_mem);
10567   else
10568     FAIL;
10571 (define_split
10572   [(set (match_operand:SI 0 "register_operand")
10573         (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10574   "TARGET_SH1 && !reload_in_progress && !reload_completed
10575    && df_regs_ever_live_p (GBR_REG)"
10576   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10578   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10579   if (gbr_mem != NULL_RTX)
10580     operands[1] = replace_equiv_address (operands[1], gbr_mem);
10581   else
10582     FAIL;
10585 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10586 ;; Split those so that a GBR load can be used.
10587 (define_split
10588   [(set (match_operand:SI 0 "register_operand")
10589         (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10590   "TARGET_SH2A && !reload_in_progress && !reload_completed
10591    && df_regs_ever_live_p (GBR_REG)"
10592   [(set (match_dup 2) (match_dup 1))
10593    (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10595   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10596   if (gbr_mem != NULL_RTX)
10597     {
10598       operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10599       operands[1] = replace_equiv_address (operands[1], gbr_mem);
10600     }
10601   else
10602     FAIL;
10605 (define_split
10606   [(set (match_operand:QIHISIDI 0 "memory_operand")
10607         (match_operand:QIHISIDI 1 "register_operand"))]
10608   "TARGET_SH1 && !reload_in_progress && !reload_completed
10609    && df_regs_ever_live_p (GBR_REG)"
10610   [(set (match_dup 0) (match_dup 1))]
10612   rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10613   if (gbr_mem != NULL_RTX)
10614     operands[0] = replace_equiv_address (operands[0], gbr_mem);
10615   else
10616     FAIL;
10619 ;;------------------------------------------------------------------------------
10620 ;; case instruction for switch statements.
10622 ;; operand 0 is index
10623 ;; operand 1 is the minimum bound
10624 ;; operand 2 is the maximum bound - minimum bound + 1
10625 ;; operand 3 is CODE_LABEL for the table;
10626 ;; operand 4 is the CODE_LABEL to go to if index out of range.
10627 (define_expand "casesi"
10628   [(match_operand:SI 0 "arith_reg_operand" "")
10629    (match_operand:SI 1 "arith_reg_operand" "")
10630    (match_operand:SI 2 "arith_reg_operand" "")
10631    (match_operand 3 "" "") (match_operand 4 "" "")]
10632   ""
10634   rtx reg = gen_reg_rtx (SImode);
10635   rtx reg2 = gen_reg_rtx (SImode);
10636   if (TARGET_SHMEDIA)
10637     {
10638       rtx reg = gen_reg_rtx (DImode);
10639       rtx reg2 = gen_reg_rtx (DImode);
10640       rtx reg3 = gen_reg_rtx (Pmode);
10641       rtx reg4 = gen_reg_rtx (Pmode);
10642       rtx reg5 = gen_reg_rtx (Pmode);
10643       rtx load, test;
10645       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10646       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10647       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10649       test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10650       emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
10651                                       operands[4]));
10652       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10653       test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10654       emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10655       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10656       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10657                                                (Pmode, operands[3])));
10658       /* Messy: can we subreg to clean this up? */
10659       if (Pmode == DImode)
10660         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10661       else
10662         load = gen_casesi_load_media (reg4,
10663                                       gen_rtx_SUBREG (DImode, reg3, 0),
10664                                       reg2, operands[3]);
10665       PUT_MODE (SET_SRC (load), Pmode);
10666       emit_insn (load);
10667       /* ??? The following add could be eliminated if we used ptrel.  */
10668       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10669       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10670       emit_barrier ();
10671       DONE;
10672     }
10673   operands[1] = copy_to_mode_reg (SImode, operands[1]);
10674   operands[2] = copy_to_mode_reg (SImode, operands[2]);
10675   /* If optimizing, casesi_worker depends on the mode of the instruction
10676      before label it 'uses' - operands[3].  */
10677   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10678                            reg));
10679   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10680   if (TARGET_SH2)
10681     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10682   else
10683     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10684   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10685      operands[3], but to lab.  We will fix this up in
10686      machine_dependent_reorg.  */
10687   emit_barrier ();
10688   DONE;
10691 (define_expand "casesi_0"
10692   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10693    (set (match_dup 4) (minus:SI (match_dup 4)
10694                                 (match_operand:SI 1 "arith_operand" "")))
10695    (set (reg:SI T_REG)
10696         (gtu:SI (match_dup 4)
10697                 (match_operand:SI 2 "arith_reg_operand" "")))
10698    (set (pc)
10699         (if_then_else (ne (reg:SI T_REG)
10700                           (const_int 0))
10701                       (label_ref (match_operand 3 "" ""))
10702                       (pc)))]
10703   "TARGET_SH1"
10704   "")
10706 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10707 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10708 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10709 (define_insn "casesi_worker_0"
10710   [(set (match_operand:SI 0 "register_operand" "=r,r")
10711         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10712                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10713    (clobber (match_scratch:SI 3 "=X,1"))
10714    (clobber (match_scratch:SI 4 "=&z,z"))]
10715   "TARGET_SH1"
10716   "#")
10718 (define_split
10719   [(set (match_operand:SI 0 "register_operand" "")
10720         (unspec:SI [(match_operand:SI 1 "register_operand" "")
10721                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10722    (clobber (match_scratch:SI 3 ""))
10723    (clobber (match_scratch:SI 4 ""))]
10724   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10725   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10726    (parallel [(set (match_dup 0)
10727               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10728                           (label_ref (match_dup 2))] UNSPEC_CASESI))
10729               (clobber (match_dup 3))])
10730    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10732   if (GET_CODE (operands[2]) == CODE_LABEL)
10733     LABEL_NUSES (operands[2])++;
10736 (define_split
10737   [(set (match_operand:SI 0 "register_operand" "")
10738         (unspec:SI [(match_operand:SI 1 "register_operand" "")
10739                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10740    (clobber (match_scratch:SI 3 ""))
10741    (clobber (match_scratch:SI 4 ""))]
10742   "TARGET_SH2 && reload_completed"
10743   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10744    (parallel [(set (match_dup 0)
10745               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10746                           (label_ref (match_dup 2))] UNSPEC_CASESI))
10747               (clobber (match_dup 3))])]
10749   if (GET_CODE (operands[2]) == CODE_LABEL)
10750     LABEL_NUSES (operands[2])++;
10753 (define_insn "casesi_worker_1"
10754   [(set (match_operand:SI 0 "register_operand" "=r,r")
10755         (unspec:SI [(reg:SI R0_REG)
10756                     (match_operand:SI 1 "register_operand" "0,r")
10757                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10758    (clobber (match_scratch:SI 3 "=X,1"))]
10759   "TARGET_SH1"
10761   rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10763   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10765   switch (GET_MODE (diff_vec))
10766     {
10767     case SImode:
10768       return   "shll2   %1"     "\n"
10769              "  mov.l   @(r0,%1),%0";
10770     case HImode:
10771       return   "add     %1,%1"  "\n"
10772              "  mov.w   @(r0,%1),%0";
10773     case QImode:
10774       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10775         return         "mov.b   @(r0,%1),%0"    "\n"
10776                "        extu.b  %0,%0";
10777       else
10778         return "mov.b   @(r0,%1),%0";
10780     default:
10781       gcc_unreachable ();
10782     }
10784   [(set_attr "length" "4")])
10786 (define_insn "casesi_worker_2"
10787   [(set (match_operand:SI 0 "register_operand" "=r,r")
10788         (unspec:SI [(reg:SI R0_REG)
10789                     (match_operand:SI 1 "register_operand" "0,r")
10790                     (label_ref (match_operand 2 "" ""))
10791                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10792    (clobber (match_operand:SI 4 "" "=X,1"))]
10793   "TARGET_SH2 && reload_completed && flag_pic"
10795   rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10796   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10798   switch (GET_MODE (diff_vec))
10799     {
10800     case SImode:
10801       return   "shll2   %1"             "\n"
10802              "  add     r0,%1"          "\n"
10803              "  mova    %O3,r0"         "\n"
10804              "  mov.l   @(r0,%1),%0";
10805     case HImode:
10806       return   "add     %1,%1"          "\n"
10807              "  add     r0,%1"          "\n"
10808              "  mova    %O3,r0"         "\n"
10809              "  mov.w   @(r0,%1),%0";
10810     case QImode:
10811       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10812         return         "add     r0,%1"          "\n"
10813                 "       mova    %O3,r0"         "\n"
10814                 "       mov.b   @(r0,%1),%0"    "\n"
10815                 "       extu.b  %0,%0";
10816       else
10817         return         "add     r0,%1"          "\n"
10818                 "       mova    %O3,r0"         "\n"
10819                 "       mov.b   @(r0,%1),%0";
10820     default:
10821       gcc_unreachable ();
10822     }
10824   [(set_attr "length" "8")])
10826 (define_insn "casesi_shift_media"
10827   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10828         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10829                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10830                     UNSPEC_CASESI)))]
10831   "TARGET_SHMEDIA"
10833   rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
10835   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10837   switch (GET_MODE (diff_vec))
10838     {
10839     case SImode:
10840       return "shlli     %1, 2, %0";
10841     case HImode:
10842       return "shlli     %1, 1, %0";
10843     case QImode:
10844       if (rtx_equal_p (operands[0], operands[1]))
10845         return "";
10846       return "add       %1, r63, %0";
10847     default:
10848       gcc_unreachable ();
10849     }
10851   [(set_attr "type" "arith_media")])
10853 (define_insn "casesi_load_media"
10854   [(set (match_operand 0 "any_arith_reg_dest" "=r")
10855         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10856                       (match_operand:DI 2 "arith_reg_operand" "r")
10857                       (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
10858   "TARGET_SHMEDIA"
10860   rtx diff_vec = PATTERN (NEXT_INSN (operands[3]));
10862   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10864   switch (GET_MODE (diff_vec))
10865     {
10866     case SImode:
10867       return "ldx.l     %1, %2, %0";
10868     case HImode:
10869 #if 0
10870       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10871         return "ldx.uw  %1, %2, %0";
10872 #endif
10873       return "ldx.w     %1, %2, %0";
10874     case QImode:
10875       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10876         return "ldx.ub  %1, %2, %0";
10877       return "ldx.b     %1, %2, %0";
10878     default:
10879       gcc_unreachable ();
10880     }
10882   [(set_attr "type" "load_media")])
10884 (define_expand "simple_return"
10885   [(simple_return)]
10886  "sh_can_use_simple_return_p ()")
10888 (define_expand "return"
10889   [(return)]
10890  "reload_completed && epilogue_completed"
10892   if (TARGET_SHMEDIA)
10893     {
10894       emit_jump_insn (gen_return_media ());
10895       DONE;
10896     }
10898   if (TARGET_SHCOMPACT
10899       && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
10900     {
10901       emit_jump_insn (gen_shcompact_return_tramp ());
10902       DONE;
10903     }
10906 (define_insn "*<code>_i"
10907   [(any_return)]
10908   "TARGET_SH1 && ! (TARGET_SHCOMPACT
10909                     && (crtl->args.info.call_cookie
10910                         & CALL_COOKIE_RET_TRAMP (1)))
10911    && reload_completed
10912    && ! sh_cfun_trap_exit_p ()"
10914   if (TARGET_SH2A && (dbr_sequence_length () == 0)
10915       && !current_function_interrupt)
10916     return "rts/n";
10917   else
10918     return "%@  %#";
10920   [(set_attr "type" "return")
10921    (set_attr "needs_delay_slot" "yes")])
10923 ;; trapa has no delay slot.
10924 (define_insn "*return_trapa"
10925   [(return)]
10926   "TARGET_SH1 && !TARGET_SHCOMPACT
10927    && reload_completed"
10928   "%@"
10929   [(set_attr "type" "return")])
10931 (define_expand "shcompact_return_tramp"
10932   [(return)]
10933   "TARGET_SHCOMPACT
10934    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10936   rtx reg = gen_rtx_REG (Pmode, R0_REG);
10938   function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
10939   emit_jump_insn (gen_shcompact_return_tramp_i ());
10940   DONE;
10943 (define_insn "shcompact_return_tramp_i"
10944   [(parallel [(return) (use (reg:SI R0_REG))])]
10945   "TARGET_SHCOMPACT
10946    && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10947   "jmp  @r0%#"
10948   [(set_attr "type" "jump_ind")
10949    (set_attr "needs_delay_slot" "yes")])
10951 (define_insn "return_media_i"
10952   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
10953   "TARGET_SHMEDIA && reload_completed"
10954   "blink        %0, r63"
10955   [(set_attr "type" "jump_media")])
10957 (define_insn "return_media_rte"
10958   [(return)]
10959   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
10960   "rte"
10961   [(set_attr "type" "jump_media")])
10963 (define_expand "return_media"
10964   [(return)]
10965   "TARGET_SHMEDIA && reload_completed"
10967   int tr_regno = sh_media_register_for_return ();
10968   rtx tr;
10970   if (current_function_interrupt)
10971     {
10972       emit_jump_insn (gen_return_media_rte ());
10973       DONE;
10974     }
10975   if (tr_regno < 0)
10976     {
10977       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
10979       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
10980       tr_regno = TR0_REG;
10981       tr = gen_rtx_REG (Pmode, tr_regno);
10982       emit_move_insn (tr, r18);
10983     }
10984   else
10985     tr = gen_rtx_REG (Pmode, tr_regno);
10987   emit_jump_insn (gen_return_media_i (tr));
10988   DONE;
10991 (define_insn "shcompact_preserve_incoming_args"
10992   [(set (match_operand:SI 0 "register_operand" "+r")
10993         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
10994   "TARGET_SHCOMPACT"
10995   ""
10996   [(set_attr "length" "0")])
10998 (define_insn "shcompact_incoming_args"
10999   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
11000    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
11001    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
11002    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
11003    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
11004    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
11005    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
11006    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
11007    (set (mem:BLK (reg:SI MACL_REG))
11008         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
11009    (use (reg:SI R0_REG))
11010    (clobber (reg:SI R0_REG))
11011    (clobber (reg:SI MACL_REG))
11012    (clobber (reg:SI MACH_REG))
11013    (clobber (reg:SI PR_REG))]
11014   "TARGET_SHCOMPACT"
11015   "jsr  @r0%#"
11016   [(set_attr "needs_delay_slot" "yes")])
11018 (define_insn "shmedia_save_restore_regs_compact"
11019   [(set (reg:SI SP_REG)
11020         (plus:SI (reg:SI SP_REG)
11021                  (match_operand:SI 0 "immediate_operand" "i")))
11022    (use (reg:SI R0_REG))
11023    (clobber (reg:SI PR_REG))]
11024   "TARGET_SHCOMPACT
11025    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
11026        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
11027   "jsr @r0%#"
11028   [(set_attr "needs_delay_slot" "yes")])
11030 (define_expand "prologue"
11031   [(const_int 0)]
11032   ""
11034   sh_expand_prologue ();
11035   DONE;
11038 (define_expand "epilogue"
11039   [(return)]
11040   ""
11042   sh_expand_epilogue (false);
11043   if (TARGET_SHMEDIA
11044       || (TARGET_SHCOMPACT
11045           && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11046     {
11047       emit_jump_insn (gen_return ());
11048       DONE;
11049     }
11052 (define_expand "eh_return"
11053   [(use (match_operand 0 "register_operand" ""))]
11054   ""
11056   rtx ra = operands[0];
11058   if (TARGET_SHMEDIA64)
11059     emit_insn (gen_eh_set_ra_di (ra));
11060   else
11061     emit_insn (gen_eh_set_ra_si (ra));
11063   DONE;
11066 ;; Clobber the return address on the stack.  We can't expand this
11067 ;; until we know where it will be put in the stack frame.
11069 (define_insn "eh_set_ra_si"
11070   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11071       UNSPECV_EH_RETURN)
11072    (clobber (match_scratch:SI 1 "=&r"))]
11073   "! TARGET_SHMEDIA64"
11074   "#")
11076 (define_insn "eh_set_ra_di"
11077   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11078       UNSPECV_EH_RETURN)
11079    (clobber (match_scratch:DI 1 "=&r"))]
11080   "TARGET_SHMEDIA64"
11081   "#")
11083 (define_split
11084   [(unspec_volatile [(match_operand 0 "register_operand" "")]
11085       UNSPECV_EH_RETURN)
11086    (clobber (match_scratch 1 ""))]
11087   "reload_completed"
11088   [(const_int 0)]
11090   sh_set_return_address (operands[0], operands[1]);
11091   DONE;
11094 (define_insn "blockage"
11095   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11096   ""
11097   ""
11098   [(set_attr "length" "0")])
11100 ;; Define movml instructions for SH2A target.  Currently they are
11101 ;; used to push and pop all banked registers only.
11103 (define_insn "movml_push_banked"
11104   [(set (match_operand:SI 0 "register_operand" "=r")
11105           (plus (match_dup 0) (const_int -32)))
11106    (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11107    (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11108    (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11109    (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11110    (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11111    (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11112    (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11113    (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11114   "TARGET_SH2A && REGNO (operands[0]) == 15"
11115   "movml.l      r7,@-r15"
11116   [(set_attr "in_delay_slot" "no")])
11118 (define_insn "movml_pop_banked"
11119   [(set (match_operand:SI 0 "register_operand" "=r")
11120           (plus (match_dup 0) (const_int 32)))
11121    (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11122    (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11123    (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11124    (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11125    (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11126    (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11127    (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11128    (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11129   "TARGET_SH2A && REGNO (operands[0]) == 15"
11130   "movml.l      @r15+,r7"
11131   [(set_attr "in_delay_slot" "no")])
11133 ;; ------------------------------------------------------------------------
11134 ;; Scc instructions
11135 ;; ------------------------------------------------------------------------
11137 (define_insn "movt"
11138   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11139         (match_operand:SI 1 "t_reg_operand"))]
11140   "TARGET_SH1"
11141   "movt %0"
11142   [(set_attr "type" "arith")])
11144 (define_insn "movrt"
11145   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11146         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11147   "TARGET_SH2A"
11148   "movrt        %0"
11149   [(set_attr "type" "arith")])
11151 (define_expand "cstore4_media"
11152   [(set (match_operand:SI 0 "register_operand" "=r")
11153         (match_operator:SI 1 "sh_float_comparison_operator"
11154          [(match_operand 2 "logical_operand" "")
11155           (match_operand 3 "cmp_operand" "")]))]
11156   "TARGET_SHMEDIA"
11158   enum machine_mode mode = GET_MODE (operands[2]);
11159   enum rtx_code code = GET_CODE (operands[1]);
11160   bool invert, swap;
11161   if (mode == VOIDmode)
11162     mode = GET_MODE (operands[3]);
11163   if (operands[2] == const0_rtx)
11164     {
11165       if (code == EQ || code == NE)
11166         operands[2] = operands[3], operands[3] = const0_rtx;
11167     }
11168   else
11169     operands[2] = force_reg (mode, operands[2]);
11170   if (operands[3] != const0_rtx)
11171     operands[3] = force_reg (mode, operands[3]);
11173   switch (code)
11174     {
11175     case GEU:
11176     case GE:
11177       swap = invert = !FLOAT_MODE_P (mode);
11178       break;
11180     case LEU:
11181     case LE:
11182       swap = FLOAT_MODE_P (mode), invert = !swap;
11183       break;
11185     case LTU:
11186     case LT:
11187       swap = true, invert = false;
11188       break;
11190     case GTU:
11191     case GT:
11192     case EQ:
11193     case UNORDERED:
11194       swap = invert = false;
11195       break;
11197     case NE:
11198       swap = invert = true;
11199       break;
11201     default:
11202       gcc_unreachable ();
11203   }
11205   if (swap)
11206     {
11207       rtx tem = operands[2];
11208       operands[2] = operands[3];
11209       operands[3] = tem;
11210       code = swap_condition (code);
11211     }
11213   if (invert)
11214     {
11215       rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11216       code = reverse_condition (code);
11217       operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11218       emit_insn (gen_cstore4_media (tem, operands[1],
11219                                     operands[2], operands[3]));
11220       code = EQ;
11221       operands[2] = tem;
11222       operands[3] = const0_rtx;
11223     }
11225   operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11228 (define_expand "cstoresi4"
11229   [(set (match_operand:SI 0 "register_operand" "=r")
11230         (match_operator:SI 1 "comparison_operator"
11231          [(match_operand:SI 2 "cmpsi_operand" "")
11232           (match_operand:SI 3 "arith_operand" "")]))]
11233   "TARGET_SH1 || TARGET_SHMEDIA"
11235   if (TARGET_SHMEDIA)
11236     {
11237       emit_insn (gen_cstore4_media (operands[0], operands[1],
11238                                     operands[2], operands[3]));
11239       DONE;
11240     }
11242    if (sh_expand_t_scc (operands))
11243      DONE;
11245    if (! currently_expanding_to_rtl)
11246      FAIL;
11247    
11248    sh_emit_compare_and_set (operands, SImode);
11249    DONE;
11252 (define_expand "cstoredi4"
11253   [(set (match_operand:SI 0 "register_operand" "=r")
11254         (match_operator:SI 1 "comparison_operator"
11255          [(match_operand:DI 2 "arith_operand" "")
11256           (match_operand:DI 3 "arith_operand" "")]))]
11257   "TARGET_SH2 || TARGET_SHMEDIA"
11259   if (TARGET_SHMEDIA)
11260     {
11261       emit_insn (gen_cstore4_media (operands[0], operands[1],
11262                                     operands[2], operands[3]));
11263       DONE;
11264     }
11266    if (sh_expand_t_scc (operands))
11267      DONE;
11269    if (! currently_expanding_to_rtl)
11270      FAIL;
11271    
11272    sh_emit_compare_and_set (operands, DImode);
11273    DONE;
11276 ;; Move the complement of the T reg to a reg.
11277 ;; On SH2A the movrt insn can be used.
11278 ;; On anything else than SH2A this has to be done with multiple instructions.
11279 ;; One obvious way would be:
11280 ;;      cmp/eq  ...
11281 ;;      movt    r0
11282 ;;      xor     #1,r0
11284 ;; However, this puts pressure on r0 in most cases and thus the following is
11285 ;; more appealing:
11286 ;;      cmp/eq  ...
11287 ;;      mov     #-1,temp
11288 ;;      negc    temp,dest
11290 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11291 ;; becomes a one instruction operation.  Moreover, care must be taken that
11292 ;; the insn can still be combined with inverted compare and branch code
11293 ;; around it.  On the other hand, if a function returns the complement of
11294 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11295 ;; lead to better code.
11296 (define_expand "movnegt"
11297   [(set (match_operand:SI 0 "arith_reg_dest" "")
11298         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11299   "TARGET_SH1"
11301   if (TARGET_SH2A)
11302     emit_insn (gen_movrt (operands[0], operands[1]));
11303   else
11304     {
11305       rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11306       emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11307     }
11308   DONE;
11311 (define_insn "movrt_negc"
11312   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11313         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11314    (set (reg:SI T_REG) (const_int 1))
11315    (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11316   "TARGET_SH1"
11317   "negc %2,%0"
11318   [(set_attr "type" "arith")])
11320 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11321 ;; pattern can be used by the combine pass.  Using a scratch reg for the
11322 ;; -1 constant results in slightly better register allocations compared to
11323 ;; generating a pseudo reg before reload.
11324 (define_insn_and_split "*movrt_negc"
11325   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11326         (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11327    (clobber (match_scratch:SI 2 "=r"))
11328    (clobber (reg:SI T_REG))]
11329   "TARGET_SH1 && ! TARGET_SH2A"
11330   "#"
11331   "&& reload_completed"
11332   [(set (match_dup 2) (const_int -1))
11333    (parallel
11334        [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11335         (set (reg:SI T_REG) (const_int 1))
11336         (use (match_dup 2))])])
11338 ;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
11339 ;; clobber the T bit, which is useful when storing the T bit and the
11340 ;; negated T bit in parallel.  On SH2A the movrt insn can be used for that.
11341 ;; Usually we don't want this insn to be matched, except for cases where the
11342 ;; T bit clobber is really not appreciated.  Hence the extra use on T_REG.
11343 (define_insn_and_split "movrt_xor"
11344   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11345         (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11346    (use (reg:SI T_REG))]
11347   "TARGET_SH1 && !TARGET_SH2A"
11348   "#"
11349   "&& reload_completed"
11350   [(set (match_dup 0) (reg:SI T_REG))
11351    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11353 ;; Store the T bit and the negated T bit in two regs in parallel.  There is
11354 ;; no real insn to do that, but specifying this pattern will give combine
11355 ;; some opportunities.
11356 (define_insn_and_split "*movt_movrt"
11357   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11358                    (match_operand:SI 1 "negt_reg_operand"))
11359               (set (match_operand:SI 2 "arith_reg_dest")
11360                    (match_operand:SI 3 "t_reg_operand"))])]
11361   "TARGET_SH1"
11362   "#"
11363   "&& 1"
11364   [(const_int 0)]
11366   rtx i = TARGET_SH2A
11367           ? gen_movrt (operands[0], get_t_reg_rtx ())
11368           : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11369   
11370   emit_insn (i);
11371   emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11372   DONE;
11375 (define_insn_and_split "*movt_movrt"
11376   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11377                    (match_operand:SI 1 "t_reg_operand"))
11378               (set (match_operand:SI 2 "arith_reg_dest")
11379                    (match_operand:SI 3 "negt_reg_operand"))])]
11380   "TARGET_SH1"
11381   "#"
11382   "&& 1"
11383   [(parallel [(set (match_dup 2) (match_dup 3))
11384               (set (match_dup 0) (match_dup 1))])])
11386 ;; Use negc to store the T bit in a MSB of a reg in the following way:
11387 ;;      T = 1: 0x80000000 -> reg
11388 ;;      T = 0: 0x7FFFFFFF -> reg
11389 ;; This works because 0 - 0x80000000 = 0x80000000.
11391 ;; This insn must not match again after it has been split into the constant
11392 ;; load and negc.  This is accomplished by the special negc insn that
11393 ;; has a use on the operand.
11394 (define_insn_and_split "*mov_t_msb_neg"
11395   [(set (match_operand:SI 0 "arith_reg_dest")
11396         (minus:SI (const_int -2147483648)  ;; 0x80000000
11397                   (match_operand 1 "t_reg_operand")))
11398    (clobber (reg:SI T_REG))]
11399   "TARGET_SH1"
11400   "#"
11401   "&& can_create_pseudo_p ()"
11402   [(set (match_dup 2) (const_int -2147483648))
11403    (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11404                                            (reg:SI T_REG)))
11405               (clobber (reg:SI T_REG))
11406               (use (match_dup 2))])]
11408   operands[2] = gen_reg_rtx (SImode);
11411 (define_insn "*mov_t_msb_neg_negc"
11412   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11413         (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
11414                   (match_operand:SI 2 "t_reg_operand")))
11415    (clobber (reg:SI T_REG))
11416    (use (match_dup 1))]
11417   "TARGET_SH1"
11418   "negc %1,%0"
11419   [(set_attr "type" "arith")])
11421 ;; These are essentially the same as above, but with the inverted T bit.
11422 ;; Combine recognizes the split patterns, but does not take them sometimes
11423 ;; if the T_REG clobber is specified.  Instead it tries to split out the
11424 ;; T bit negation.  Since these splits are supposed to be taken only by
11425 ;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11426 ;; should be fine.
11427 (define_split
11428   [(set (match_operand:SI 0 "arith_reg_dest")
11429         (plus:SI (match_operand 1 "negt_reg_operand")
11430                  (const_int 2147483647)))]  ;; 0x7fffffff
11431   "TARGET_SH1 && can_create_pseudo_p ()"
11432   [(parallel [(set (match_dup 0)
11433                    (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11434               (clobber (reg:SI T_REG))])])
11436 (define_split
11437   [(set (match_operand:SI 0 "arith_reg_dest")
11438         (if_then_else:SI (match_operand 1 "t_reg_operand")
11439                          (const_int 2147483647)  ;; 0x7fffffff
11440                          (const_int -2147483648)))]  ;; 0x80000000
11441   "TARGET_SH1 && can_create_pseudo_p ()"
11442   [(parallel [(set (match_dup 0)
11443                    (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11444               (clobber (reg:SI T_REG))])])
11446 ;; The *negnegt pattern helps the combine pass to figure out how to fold 
11447 ;; an explicit double T bit negation.
11448 (define_insn_and_split "*negnegt"
11449   [(set (reg:SI T_REG)
11450         (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11451   "TARGET_SH1"
11452   "#"
11453   ""
11454   [(const_int 0)])
11456 ;; Store T bit as all zeros or ones in a reg.
11457 (define_insn "mov_neg_si_t"
11458   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11459         (neg:SI (match_operand 1 "t_reg_operand" "")))]
11460   "TARGET_SH1"
11461   "subc %0,%0"
11462   [(set_attr "type" "arith")])
11464 ;; Store negated T bit as all zeros or ones in a reg.
11465 ;; Use the following sequence:
11466 ;;      subc    Rn,Rn   ! Rn = Rn - Rn - T; T = T
11467 ;;      not     Rn,Rn   ! Rn = 0 - Rn
11468 (define_split
11469   [(set (match_operand:SI 0 "arith_reg_dest" "")
11470         (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11471   "TARGET_SH1"
11472   [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11473    (set (match_dup 0) (not:SI (match_dup 0)))])
11475 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11476 (define_insn_and_split "*movtt"
11477   [(set (reg:SI T_REG)
11478         (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11479   "TARGET_SH1"
11480   "#"
11481   ""
11482   [(const_int 0)])
11484 ;; Invert the T bit.
11485 ;; On SH2A we can use the nott insn.  On anything else this must be done with
11486 ;; multiple insns like:
11487 ;;      movt    Rn
11488 ;;      tst     Rn,Rn
11489 ;; This requires an additional pseudo.  The SH specific sh_treg_combine RTL
11490 ;; pass will look for this insn.  Disallow using it if pseudos can't be
11491 ;; created.
11492 (define_insn_and_split "nott"
11493   [(set (reg:SI T_REG)
11494         (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
11495   "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
11497   gcc_assert (TARGET_SH2A);
11498   return "nott";
11500   "! TARGET_SH2A && can_create_pseudo_p ()"
11501   [(set (match_dup 0) (reg:SI T_REG))
11502    (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11504   operands[0] = gen_reg_rtx (SImode);
11507 ;; Store T bit as MSB in a reg.
11508 ;; T = 0: 0x00000000 -> reg
11509 ;; T = 1: 0x80000000 -> reg
11510 (define_insn_and_split "*movt_msb"
11511   [(set (match_operand:SI 0 "arith_reg_dest")
11512         (mult:SI (match_operand:SI 1 "t_reg_operand")
11513                  (const_int -2147483648)))  ;; 0xffffffff80000000
11514    (clobber (reg:SI T_REG))]
11515   "TARGET_SH1"
11516   "#"
11517   "&& 1"
11518   [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11520 ;; Store inverted T bit as MSB in a reg.
11521 ;; T = 0: 0x80000000 -> reg
11522 ;; T = 1: 0x00000000 -> reg
11523 ;; On SH2A we can get away without clobbering the T_REG.
11524 (define_insn_and_split "*negt_msb"
11525   [(set (match_operand:SI 0 "arith_reg_dest")
11526         (match_operand:SI 1 "negt_reg_shl31_operand"))]
11527   "TARGET_SH2A"
11528   "#"
11529   "&& can_create_pseudo_p ()"
11530   [(const_int 0)]
11532   rtx tmp = gen_reg_rtx (SImode);
11533   emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11534   emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11535   DONE;
11538 (define_insn_and_split "*negt_msb"
11539   [(set (match_operand:SI 0 "arith_reg_dest")
11540         (match_operand:SI 1 "negt_reg_shl31_operand"))
11541    (clobber (reg:SI T_REG))]
11542   "TARGET_SH1 && !TARGET_SH2A"
11543   "#"
11544   "&& can_create_pseudo_p ()"
11545   [(const_int 0)]
11547   rtx tmp = gen_reg_rtx (SImode);
11548   emit_move_insn (tmp, get_t_reg_rtx ());
11549   emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11550   emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11551   DONE;
11554 ;; The *cset_zero patterns convert optimizations such as
11555 ;;      "if (test) x = 0;"
11556 ;; to
11557 ;;      "x &= -(test == 0);"
11558 ;; back to conditional branch sequences if zero-displacement branches
11559 ;; are enabled.
11560 ;; FIXME: These patterns can be removed when conditional execution patterns
11561 ;; are implemented, since ifcvt will not perform these optimizations if
11562 ;; conditional execution is supported.
11563 (define_insn "*cset_zero"
11564   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11565         (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11566                          (const_int -1))
11567                 (match_operand:SI 2 "arith_reg_operand" "0")))]
11568   "TARGET_SH1 && TARGET_ZDCBRANCH"
11570   return       "bf      0f"     "\n"
11571          "      mov     #0,%0"  "\n"
11572          "0:";
11574   [(set_attr "type" "arith") ;; poor approximation
11575    (set_attr "length" "4")])
11577 (define_insn "*cset_zero"
11578   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11579         (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11580                          (match_operand:SI 2 "arith_reg_operand" "0")
11581                          (const_int 0)))]
11582   "TARGET_SH1 && TARGET_ZDCBRANCH"
11584   return       "bt      0f"     "\n"
11585          "      mov     #0,%0"  "\n"
11586          "0:";
11588   [(set_attr "type" "arith") ;; poor approximation
11589    (set_attr "length" "4")])
11591 (define_expand "cstoresf4"
11592   [(set (match_operand:SI 0 "register_operand" "=r")
11593         (match_operator:SI 1 "sh_float_comparison_operator"
11594          [(match_operand:SF 2 "arith_operand" "")
11595           (match_operand:SF 3 "arith_operand" "")]))]
11596   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11598   if (TARGET_SHMEDIA)
11599     {
11600       emit_insn (gen_cstore4_media (operands[0], operands[1],
11601                                     operands[2], operands[3]));
11602       DONE;
11603     }
11605   if (! currently_expanding_to_rtl)
11606     FAIL;
11607    
11608   sh_emit_compare_and_set (operands, SFmode);
11609   DONE;
11612 (define_expand "cstoredf4"
11613   [(set (match_operand:SI 0 "register_operand" "=r")
11614         (match_operator:SI 1 "sh_float_comparison_operator"
11615          [(match_operand:DF 2 "arith_operand" "")
11616           (match_operand:DF 3 "arith_operand" "")]))]
11617   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11619   if (TARGET_SHMEDIA)
11620     {
11621       emit_insn (gen_cstore4_media (operands[0], operands[1],
11622                                     operands[2], operands[3]));
11623       DONE;
11624     }
11626   if (! currently_expanding_to_rtl)
11627     FAIL;
11628    
11629   sh_emit_compare_and_set (operands, DFmode);
11630   DONE;
11633 ;; -------------------------------------------------------------------------
11634 ;; Instructions to cope with inline literal tables
11635 ;; -------------------------------------------------------------------------
11637 ;; 2 byte integer in line
11638 (define_insn "consttable_2"
11639  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11640                     (match_operand 1 "" "")]
11641                    UNSPECV_CONST2)]
11642  ""
11644   if (operands[1] != const0_rtx)
11645     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11646   return "";
11648  [(set_attr "length" "2")
11649  (set_attr "in_delay_slot" "no")])
11651 ;; 4 byte integer in line
11652 (define_insn "consttable_4"
11653  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11654                     (match_operand 1 "" "")]
11655                    UNSPECV_CONST4)]
11656  ""
11658   if (operands[1] != const0_rtx)
11659     {
11660       assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11661       mark_symbol_refs_as_used (operands[0]);
11662     }
11663   return "";
11665  [(set_attr "length" "4")
11666   (set_attr "in_delay_slot" "no")])
11668 ;; 8 byte integer in line
11669 (define_insn "consttable_8"
11670  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11671                     (match_operand 1 "" "")]
11672                    UNSPECV_CONST8)]
11673  ""
11675   if (operands[1] != const0_rtx)
11676     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11677   return "";
11679  [(set_attr "length" "8")
11680   (set_attr "in_delay_slot" "no")])
11682 ;; 4 byte floating point
11683 (define_insn "consttable_sf"
11684  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11685                     (match_operand 1 "" "")]
11686                    UNSPECV_CONST4)]
11687  ""
11689   if (operands[1] != const0_rtx)
11690     {
11691       REAL_VALUE_TYPE d;
11692       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11693       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11694     }
11695   return "";
11697  [(set_attr "length" "4")
11698   (set_attr "in_delay_slot" "no")])
11700 ;; 8 byte floating point
11701 (define_insn "consttable_df"
11702  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11703                     (match_operand 1 "" "")]
11704                    UNSPECV_CONST8)]
11705  ""
11707   if (operands[1] != const0_rtx)
11708     {
11709       REAL_VALUE_TYPE d;
11710       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11711       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11712     }
11713   return "";
11715  [(set_attr "length" "8")
11716   (set_attr "in_delay_slot" "no")])
11718 ;; Alignment is needed for some constant tables; it may also be added for
11719 ;; Instructions at the start of loops, or after unconditional branches.
11720 ;; ??? We would get more accurate lengths if we did instruction
11721 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11722 ;; here is too conservative.
11724 ;; align to a two byte boundary
11725 (define_expand "align_2"
11726  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11727  ""
11728  "")
11730 ;; Align to a four byte boundary.
11731 ;; align_4 and align_log are instructions for the starts of loops, or
11732 ;; after unconditional branches, which may take up extra room.
11733 (define_expand "align_4"
11734  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11735  ""
11736  "")
11738 ;; Align to a cache line boundary.
11739 (define_insn "align_log"
11740  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11741  ""
11742  ""
11743  [(set_attr "length" "0")
11744   (set_attr "in_delay_slot" "no")])
11746 ;; Emitted at the end of the literal table, used to emit the
11747 ;; 32bit branch labels if needed.
11748 (define_insn "consttable_end"
11749   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11750   ""
11752   return output_jump_label_table ();
11754   [(set_attr "in_delay_slot" "no")])
11756 ;; Emitted at the end of the window in the literal table.
11757 (define_insn "consttable_window_end"
11758   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11759   ""
11760   ""
11761   [(set_attr "length" "0")
11762    (set_attr "in_delay_slot" "no")])
11764 ;; -------------------------------------------------------------------------
11765 ;; Minimum / maximum operations.
11766 ;; -------------------------------------------------------------------------
11768 ;; The SH2A clips.b and clips.w insns do a signed min-max function.  If smin
11769 ;; and smax standard name patterns are defined, they will be used during
11770 ;; initial expansion and combine will then be able to form the actual min-max
11771 ;; pattern.
11772 ;; The clips.b and clips.w set the SR.CS bit if the value in the register is
11773 ;; clipped, but there is currently no way of making use of this information.
11774 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11775 (define_expand "<code>si3"
11776   [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11777                    (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11778                                  (match_operand 2 "const_int_operand")))
11779               (clobber (reg:SI T_REG))])]
11780   "TARGET_SH2A"
11782   /* Force the comparison value into a register, because greater-than
11783      comparisons can work only on registers.  Combine will be able to pick up
11784      the constant value from the REG_EQUAL note when trying to form a min-max
11785      pattern.  */
11786   operands[2] = force_reg (SImode, operands[2]);
11789 ;; Convert
11790 ;;      smax (smin (...))
11791 ;; to
11792 ;;      smin (smax (...))
11793 (define_insn_and_split "*clips"
11794   [(set (match_operand:SI 0 "arith_reg_dest")
11795         (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
11796                           (match_operand 2 "clips_max_const_int"))
11797                  (match_operand 3 "clips_min_const_int")))]
11798   "TARGET_SH2A"
11799   "#"
11800   "&& 1"
11801   [(set (match_dup 0)
11802         (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
11804 (define_insn "*clips"
11805   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11806         (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
11807                           (match_operand 2 "clips_min_const_int"))
11808                  (match_operand 3 "clips_max_const_int")))]
11809   "TARGET_SH2A"
11811   if (INTVAL (operands[3]) == 127)
11812     return "clips.b     %0";
11813   else if (INTVAL (operands[3]) == 32767)
11814     return "clips.w     %0";
11815   else
11816     gcc_unreachable ();
11818   [(set_attr "type" "arith")])
11820 ;; If the expanded smin or smax patterns were not combined, split them into
11821 ;; a compare and branch sequence, because there are no real smin or smax
11822 ;; insns.
11823 (define_insn_and_split "*<code>si3"
11824   [(set (match_operand:SI 0 "arith_reg_dest")
11825         (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
11826                       (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
11827    (clobber (reg:SI T_REG))]
11828   "TARGET_SH2A && can_create_pseudo_p ()"
11829   "#"
11830   "&& 1"
11831   [(const_int 0)]
11833   rtx skip_label = gen_label_rtx ();
11834   emit_move_insn (operands[0], operands[1]);
11836   rtx cmp_val = operands[2];
11837   if (satisfies_constraint_M (cmp_val))
11838     cmp_val = const0_rtx;
11840   emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
11841   emit_jump_insn (<CODE> == SMIN
11842                             ? gen_branch_false (skip_label)
11843                             : gen_branch_true (skip_label));
11845   emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
11846   DONE;
11849 ;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
11850 ;; with a register and a constant.
11851 ;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
11852 ;; clipped, but there is currently no way of making use of this information.
11853 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
11854 (define_expand "uminsi3"
11855   [(set (match_operand:SI 0 "arith_reg_dest")
11856         (umin:SI (match_operand:SI 1 "arith_reg_operand")
11857                  (match_operand 2 "const_int_operand")))]
11858   "TARGET_SH2A"
11860   if (INTVAL (operands[2]) == 1)
11861     {
11862       emit_insn (gen_clipu_one (operands[0], operands[1]));
11863       DONE;
11864     }
11865   else if (! clipu_max_const_int (operands[2], VOIDmode))
11866     FAIL;
11869 (define_insn "*clipu"
11870   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11871         (umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
11872                  (match_operand 2 "clipu_max_const_int")))]
11873   "TARGET_SH2A"
11875   if (INTVAL (operands[2]) == 255)
11876     return "clipu.b     %0";
11877   else if (INTVAL (operands[2]) == 65535)
11878     return "clipu.w     %0";
11879   else
11880     gcc_unreachable ();
11882   [(set_attr "type" "arith")])
11884 (define_insn_and_split "clipu_one"
11885   [(set (match_operand:SI 0 "arith_reg_dest")
11886         (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
11887    (clobber (reg:SI T_REG))]
11888   "TARGET_SH2A"
11889   "#"
11890   "&& can_create_pseudo_p ()"
11891   [(const_int 0)]
11893   emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
11894   emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
11895   DONE;
11898 ;; -------------------------------------------------------------------------
11899 ;; Misc
11900 ;; -------------------------------------------------------------------------
11902 ;; String/block move insn.
11904 (define_expand "movmemsi"
11905   [(parallel [(set (mem:BLK (match_operand:BLK 0))
11906                    (mem:BLK (match_operand:BLK 1)))
11907               (use (match_operand:SI 2 "nonmemory_operand"))
11908               (use (match_operand:SI 3 "immediate_operand"))
11909               (clobber (reg:SI PR_REG))
11910               (clobber (reg:SI R4_REG))
11911               (clobber (reg:SI R5_REG))
11912               (clobber (reg:SI R0_REG))])]
11913   "TARGET_SH1 && ! TARGET_SH5"
11915   if (expand_block_move (operands))
11916     DONE;
11917   else
11918     FAIL;
11921 (define_insn "block_move_real"
11922   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11923                    (mem:BLK (reg:SI R5_REG)))
11924               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11925               (clobber (reg:SI PR_REG))
11926               (clobber (reg:SI R0_REG))])]
11927   "TARGET_SH1 && ! TARGET_HARD_SH4"
11928   "jsr  @%0%#"
11929   [(set_attr "type" "sfunc")
11930    (set_attr "needs_delay_slot" "yes")])
11932 (define_insn "block_lump_real"
11933   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11934                    (mem:BLK (reg:SI R5_REG)))
11935               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11936               (use (reg:SI R6_REG))
11937               (clobber (reg:SI PR_REG))
11938               (clobber (reg:SI T_REG))
11939               (clobber (reg:SI R4_REG))
11940               (clobber (reg:SI R5_REG))
11941               (clobber (reg:SI R6_REG))
11942               (clobber (reg:SI R0_REG))])]
11943   "TARGET_SH1 && ! TARGET_HARD_SH4"
11944   "jsr  @%0%#"
11945   [(set_attr "type" "sfunc")
11946    (set_attr "needs_delay_slot" "yes")])
11948 (define_insn "block_move_real_i4"
11949   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11950                    (mem:BLK (reg:SI R5_REG)))
11951               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11952               (clobber (reg:SI PR_REG))
11953               (clobber (reg:SI R0_REG))
11954               (clobber (reg:SI R1_REG))
11955               (clobber (reg:SI R2_REG))])]
11956   "TARGET_HARD_SH4"
11957   "jsr  @%0%#"
11958   [(set_attr "type" "sfunc")
11959    (set_attr "needs_delay_slot" "yes")])
11961 (define_insn "block_lump_real_i4"
11962   [(parallel [(set (mem:BLK (reg:SI R4_REG))
11963                    (mem:BLK (reg:SI R5_REG)))
11964               (use (match_operand:SI 0 "arith_reg_operand" "r"))
11965               (use (reg:SI R6_REG))
11966               (clobber (reg:SI PR_REG))
11967               (clobber (reg:SI T_REG))
11968               (clobber (reg:SI R4_REG))
11969               (clobber (reg:SI R5_REG))
11970               (clobber (reg:SI R6_REG))
11971               (clobber (reg:SI R0_REG))
11972               (clobber (reg:SI R1_REG))
11973               (clobber (reg:SI R2_REG))
11974               (clobber (reg:SI R3_REG))])]
11975   "TARGET_HARD_SH4"
11976   "jsr  @%0%#"
11977   [(set_attr "type" "sfunc")
11978    (set_attr "needs_delay_slot" "yes")])
11980 ;; byte compare pattern
11981 ;; temp = a ^ b;
11982 ;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
11983 (define_insn "cmpstr_t"
11984   [(set (reg:SI T_REG)
11985         (eq:SI (and:SI
11986                  (and:SI
11987                    (and:SI
11988                      (zero_extract:SI
11989                        (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
11990                                (match_operand:SI 1 "arith_reg_operand" "r"))
11991                        (const_int 8) (const_int 0))
11992                      (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
11993                                       (const_int 8) (const_int 8)))
11994                     (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
11995                                      (const_int 8) (const_int 16)))
11996                  (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
11997                                   (const_int 8) (const_int 24)))
11998                (const_int 0)))]
11999   "TARGET_SH1"
12000   "cmp/str      %0,%1"
12001   [(set_attr "type" "mt_group")])
12003 (define_expand "cmpstrsi"
12004   [(set (match_operand:SI 0 "register_operand")
12005         (compare:SI (match_operand:BLK 1 "memory_operand")
12006                     (match_operand:BLK 2 "memory_operand")))
12007    (use (match_operand 3 "immediate_operand"))]
12008   "TARGET_SH1 && optimize"
12010   if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
12011     DONE;
12012   else
12013     FAIL;
12016 (define_expand "cmpstrnsi"
12017   [(set (match_operand:SI 0 "register_operand")
12018         (compare:SI (match_operand:BLK 1 "memory_operand")
12019                     (match_operand:BLK 2 "memory_operand")))
12020    (use (match_operand:SI 3 "immediate_operand"))
12021    (use (match_operand:SI 4 "immediate_operand"))]
12022   "TARGET_SH1 && optimize"
12024   if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
12025     DONE;
12026   else
12027     FAIL;
12030 (define_expand "strlensi"
12031   [(set (match_operand:SI 0 "register_operand")
12032         (unspec:SI [(match_operand:BLK 1 "memory_operand")
12033                    (match_operand:SI 2 "immediate_operand")
12034                    (match_operand:SI 3 "immediate_operand")]
12035                   UNSPEC_BUILTIN_STRLEN))]
12036   "TARGET_SH1 && optimize"
12038  if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
12039    DONE;
12040  else
12041    FAIL;
12045 ;; -------------------------------------------------------------------------
12046 ;; Floating point instructions.
12047 ;; -------------------------------------------------------------------------
12049 ;; ??? All patterns should have a type attribute.
12051 (define_expand "movpsi"
12052   [(set (match_operand:PSI 0 "register_operand" "")
12053         (match_operand:PSI 1 "general_movsrc_operand" ""))]
12054   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12055   "")
12057 ;; The c / m alternative is a fake to guide reload to load directly into
12058 ;; fpscr, since reload doesn't know how to use post-increment.
12059 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
12060 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
12061 ;; predicate after reload.
12062 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
12063 ;; like a mac -> gpr move.
12064 (define_insn "fpu_switch"
12065   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
12066         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
12067   "TARGET_SH2E
12068    && (! reload_completed
12069        || true_regnum (operands[0]) != FPSCR_REG
12070        || !MEM_P (operands[1])
12071        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
12072   "@
12073         ! precision stays the same
12074         lds.l   %1,fpscr
12075         mov.l   %1,%0
12076         #
12077         lds     %1,fpscr
12078         mov     %1,%0
12079         mov.l   %1,%0
12080         sts     fpscr,%0
12081         sts.l   fpscr,%0"
12082   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
12083    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,
12084                      mac_gp,fstore")])
12086 (define_peephole2
12087   [(set (reg:PSI FPSCR_REG)
12088         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
12089   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
12090   [(const_int 0)]
12092   rtx fpscr, mem, new_insn;
12094   fpscr = SET_DEST (PATTERN (curr_insn));
12095   mem = SET_SRC (PATTERN (curr_insn));
12096   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
12098   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
12099   add_reg_note (new_insn, REG_INC, operands[0]);
12100   DONE;
12103 (define_split
12104   [(set (reg:PSI FPSCR_REG)
12105         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
12106   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
12107    && (flag_peephole2 ? epilogue_completed : reload_completed)"
12108   [(const_int 0)]
12110   rtx fpscr, mem, new_insn;
12112   fpscr = SET_DEST (PATTERN (curr_insn));
12113   mem = SET_SRC (PATTERN (curr_insn));
12114   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
12116   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
12117   add_reg_note (new_insn, REG_INC, operands[0]);
12119   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
12120     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
12121   DONE;
12124 ;; ??? This uses the fp unit, but has no type indicating that.
12125 ;; If we did that, this would either give a bogus latency or introduce
12126 ;; a bogus FIFO constraint.
12127 ;; Since this insn is currently only used for prologues/epilogues,
12128 ;; it is probably best to claim no function unit, which matches the
12129 ;; current setting.
12130 (define_insn "toggle_sz"
12131   [(set (reg:PSI FPSCR_REG)
12132         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
12133   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12134   "fschg"
12135   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
12137 ;; There's no way we can use it today, since optimize mode switching
12138 ;; doesn't enable us to know from which mode we're switching to the
12139 ;; mode it requests, to tell whether we can use a relative mode switch
12140 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
12141 ;; memory).
12142 (define_insn "toggle_pr"
12143   [(set (reg:PSI FPSCR_REG)
12144         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
12145   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
12146   "fpchg"
12147   [(set_attr "type" "fpscr_toggle")])
12149 (define_expand "addsf3"
12150   [(set (match_operand:SF 0 "fp_arith_reg_operand")
12151         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
12152                  (match_operand:SF 2 "fp_arith_reg_operand")))]
12153   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12155   if (TARGET_SH2E)
12156     {
12157       expand_sf_binop (&gen_addsf3_i, operands);
12158       DONE;
12159     }
12162 (define_insn "*addsf3_media"
12163   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12164         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12165                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12166   "TARGET_SHMEDIA_FPU"
12167   "fadd.s       %1, %2, %0"
12168   [(set_attr "type" "fparith_media")])
12170 (define_insn_and_split "unary_sf_op"
12171   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12172         (vec_select:V2SF
12173          (vec_concat:V2SF
12174           (vec_select:SF
12175            (match_dup 0)
12176            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
12177           (match_operator:SF 2 "unary_float_operator"
12178             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12179                             (parallel [(match_operand 4
12180                                         "const_int_operand" "n")]))]))
12181          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
12182   "TARGET_SHMEDIA_FPU"
12183   "#"
12184   "TARGET_SHMEDIA_FPU && reload_completed"
12185   [(set (match_dup 5) (match_dup 6))]
12187   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12188   rtx op1 = gen_rtx_REG (SFmode,
12189                          (true_regnum (operands[1])
12190                           + (INTVAL (operands[4]) ^ endian)));
12192   operands[7] = gen_rtx_REG (SFmode,
12193                              (true_regnum (operands[0])
12194                               + (INTVAL (operands[3]) ^ endian)));
12195   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
12197   [(set_attr "type" "fparith_media")])
12199 (define_insn_and_split "binary_sf_op0"
12200   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12201         (vec_concat:V2SF
12202           (match_operator:SF 3 "binary_float_operator"
12203             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12204                             (parallel [(const_int 0)]))
12205              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12206                             (parallel [(const_int 0)]))])
12207           (vec_select:SF
12208            (match_dup 0)
12209            (parallel [(const_int 1)]))))]
12210   "TARGET_SHMEDIA_FPU"
12211   "#"
12212   "&& reload_completed"
12213   [(set (match_dup 4) (match_dup 5))]
12215   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12216   rtx op1 = gen_rtx_REG (SFmode,
12217                          true_regnum (operands[1]) + endian);
12218   rtx op2 = gen_rtx_REG (SFmode,
12219                          true_regnum (operands[2]) + endian);
12221   operands[4] = gen_rtx_REG (SFmode,
12222                              true_regnum (operands[0]) + endian);
12223   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12225   [(set_attr "type" "fparith_media")])
12227 (define_insn_and_split "binary_sf_op1"
12228   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12229         (vec_concat:V2SF
12230           (vec_select:SF
12231            (match_dup 0)
12232            (parallel [(const_int 0)]))
12233           (match_operator:SF 3 "binary_float_operator"
12234             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12235                             (parallel [(const_int 1)]))
12236              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12237                             (parallel [(const_int 1)]))])))]
12238   "TARGET_SHMEDIA_FPU"
12239   "#"
12240   "&& reload_completed"
12241   [(set (match_dup 4) (match_dup 5))]
12243   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12244   rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
12245   rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
12247   operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
12248   operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12250   [(set_attr "type" "fparith_media")])
12252 (define_insn "addsf3_i"
12253   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12254         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12255                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12256    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12257   "TARGET_SH2E"
12258   "fadd %2,%0"
12259   [(set_attr "type" "fp")
12260    (set_attr "fp_mode" "single")])
12262 (define_expand "subsf3"
12263   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12264         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12265                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12266   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12268   if (TARGET_SH2E)
12269     {
12270       expand_sf_binop (&gen_subsf3_i, operands);
12271       DONE;
12272     }
12275 (define_insn "*subsf3_media"
12276   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12277         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12278                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12279   "TARGET_SHMEDIA_FPU"
12280   "fsub.s       %1, %2, %0"
12281   [(set_attr "type" "fparith_media")])
12283 (define_insn "subsf3_i"
12284   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12285         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12286                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12287    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12288   "TARGET_SH2E"
12289   "fsub %2,%0"
12290   [(set_attr "type" "fp")
12291    (set_attr "fp_mode" "single")])
12293 (define_expand "mulsf3"
12294   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12295         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12296                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12297   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12299   if (TARGET_SH2E)
12300     {
12301       emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
12302                  get_fpscr_rtx ()));
12303       DONE;
12304     }
12307 (define_insn "*mulsf3_media"
12308   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12309         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12310                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12311   "TARGET_SHMEDIA_FPU"
12312   "fmul.s       %1, %2, %0"
12313   [(set_attr "type" "fparith_media")])
12315 (define_insn "mulsf3_i"
12316   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12317         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12318                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12319    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12320   "TARGET_SH2E"
12321   "fmul %2,%0"
12322   [(set_attr "type" "fp")
12323    (set_attr "fp_mode" "single")])
12325 ;; FMA (fused multiply-add) patterns
12326 (define_expand "fmasf4"
12327   [(set (match_operand:SF 0 "fp_arith_reg_operand")
12328         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
12329                 (match_operand:SF 2 "fp_arith_reg_operand")
12330                 (match_operand:SF 3 "fp_arith_reg_operand")))]
12331   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12333   if (TARGET_SH2E)
12334     {
12335       emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12336                                   operands[3], get_fpscr_rtx ()));
12337       DONE;
12338     }
12341 (define_insn "fmasf4_i"
12342   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12343         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12344                 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12345                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
12346    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
12347   "TARGET_SH2E"
12348   "fmac %1,%2,%0"
12349   [(set_attr "type" "fp")
12350    (set_attr "fp_mode" "single")])
12352 (define_insn "fmasf4_media"
12353   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12354         (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12355                 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12356                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12357   "TARGET_SHMEDIA_FPU"
12358   "fmac.s %1, %2, %0"
12359   [(set_attr "type" "fparith_media")])
12361 ;; For some cases such as 'a * b + a' the FMA pattern is not generated by
12362 ;; previous transformations.  If FMA is generally allowed, let the combine
12363 ;; pass utilize it.
12364 (define_insn_and_split "*fmasf4"
12365   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12366         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
12367                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12368                  (match_operand:SF 3 "arith_reg_operand" "0")))
12369    (use (match_operand:PSI 4 "fpscr_operand"))]
12370   "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
12371   "fmac %1,%2,%0"
12372   "&& can_create_pseudo_p ()"
12373   [(parallel [(set (match_dup 0)
12374                    (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
12375               (use (match_dup 4))])]
12377   /* Change 'b * a + a' into 'a * b + a'.
12378      This is better for register allocation.  */
12379   if (REGNO (operands[2]) == REGNO (operands[3]))
12380     {
12381       rtx tmp = operands[1];
12382       operands[1] = operands[2];
12383       operands[2] = tmp;
12384     }
12386   [(set_attr "type" "fp")
12387    (set_attr "fp_mode" "single")])
12389 (define_insn "*fmasf4_media"
12390   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12391         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12392                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12393                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12394   "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
12395   "fmac.s %1, %2, %0"
12396   [(set_attr "type" "fparith_media")])
12398 (define_expand "divsf3"
12399   [(set (match_operand:SF 0 "fp_arith_reg_operand")
12400         (div:SF (match_operand:SF 1 "fp_arith_reg_operand")
12401                 (match_operand:SF 2 "fp_arith_reg_operand")))]
12402   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12404   if (TARGET_SH2E)
12405     {
12406       expand_sf_binop (&gen_divsf3_i, operands);
12407       DONE;
12408     }
12411 (define_insn "*divsf3_media"
12412   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12413         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12414                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12415   "TARGET_SHMEDIA_FPU"
12416   "fdiv.s       %1, %2, %0"
12417   [(set_attr "type" "fdiv_media")])
12419 (define_insn "divsf3_i"
12420   [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
12421         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12422                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12423    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12424   "TARGET_SH2E"
12425   "fdiv %2,%0"
12426   [(set_attr "type" "fdiv")
12427    (set_attr "fp_mode" "single")])
12429 (define_insn "floatdisf2"
12430   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12431         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12432   "TARGET_SHMEDIA_FPU"
12433   "float.qs %1, %0"
12434   [(set_attr "type" "fpconv_media")])
12436 (define_expand "floatsisf2"
12437   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12438         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
12439   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12441   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12442     {
12443       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1],
12444                                        get_fpscr_rtx ()));
12445       DONE;
12446     }
12449 (define_insn "*floatsisf2_media"
12450   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12451         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12452   "TARGET_SHMEDIA_FPU"
12453   "float.ls     %1, %0"
12454   [(set_attr "type" "fpconv_media")])
12456 (define_insn "floatsisf2_i4"
12457   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12458         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
12459    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12460   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12461   "float        %1,%0"
12462   [(set_attr "type" "fp")
12463    (set_attr "fp_mode" "single")])
12465 (define_insn "*floatsisf2_ie"
12466   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12467         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
12468   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12469   "float        %1,%0"
12470   [(set_attr "type" "fp")])
12472 (define_insn "fix_truncsfdi2"
12473   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12474         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12475   "TARGET_SHMEDIA_FPU"
12476   "ftrc.sq %1, %0"
12477   [(set_attr "type" "fpconv_media")])
12479 (define_expand "fix_truncsfsi2"
12480   [(set (match_operand:SI 0 "fpul_operand" "=y")
12481         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12482   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12484   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12485     {
12486       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1],
12487                                            get_fpscr_rtx ()));
12488       DONE;
12489     }
12492 (define_insn "*fix_truncsfsi2_media"
12493   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12494         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12495   "TARGET_SHMEDIA_FPU"
12496   "ftrc.sl      %1, %0"
12497   [(set_attr "type" "fpconv_media")])
12499 (define_insn "fix_truncsfsi2_i4"
12500   [(set (match_operand:SI 0 "fpul_operand" "=y")
12501         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12502    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12503   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12504   "ftrc %1,%0"
12505   [(set_attr "type" "ftrc_s")
12506    (set_attr "fp_mode" "single")])
12508 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
12509 ;; fix_truncsfsi2_i4.
12510 ;; (define_insn "fix_truncsfsi2_i4_2"
12511 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12512 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12513 ;;   (use (reg:PSI FPSCR_REG))
12514 ;;   (clobber (reg:SI FPUL_REG))]
12515 ;;  "TARGET_SH4"
12516 ;;  "#"
12517 ;;  [(set_attr "length" "4")
12518 ;;   (set_attr "fp_mode" "single")])
12520 ;;(define_split
12521 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12522 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12523 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
12524 ;;   (clobber (reg:SI FPUL_REG))]
12525 ;;  "TARGET_SH4"
12526 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12527 ;;            (use (match_dup 2))])
12528 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
12530 (define_insn "*fixsfsi"
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_SH4 || TARGET_SH2A_SINGLE)"
12534   "ftrc %1,%0"
12535   [(set_attr "type" "fp")])
12537 (define_insn "cmpgtsf_t"
12538   [(set (reg:SI T_REG)
12539         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12540                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12541   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12542   "fcmp/gt      %1,%0"
12543   [(set_attr "type" "fp_cmp")
12544    (set_attr "fp_mode" "single")])
12546 (define_insn "cmpeqsf_t"
12547   [(set (reg:SI T_REG)
12548         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12549                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12550   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12551   "fcmp/eq      %1,%0"
12552   [(set_attr "type" "fp_cmp")
12553    (set_attr "fp_mode" "single")])
12555 (define_insn "ieee_ccmpeqsf_t"
12556   [(set (reg:SI T_REG)
12557         (ior:SI (reg:SI T_REG)
12558                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12559                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
12560   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12562   return output_ieee_ccmpeq (insn, operands);
12564   [(set_attr "length" "4")])
12567 (define_insn "cmpgtsf_t_i4"
12568   [(set (reg:SI T_REG)
12569         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12570                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12571    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12572   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12573   "fcmp/gt      %1,%0"
12574   [(set_attr "type" "fp_cmp")
12575    (set_attr "fp_mode" "single")])
12577 (define_insn "cmpeqsf_t_i4"
12578   [(set (reg:SI T_REG)
12579         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12580                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12581    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12582   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12583   "fcmp/eq      %1,%0"
12584   [(set_attr "type" "fp_cmp")
12585    (set_attr "fp_mode" "single")])
12587 (define_insn "*ieee_ccmpeqsf_t_4"
12588   [(set (reg:SI T_REG)
12589         (ior:SI (reg:SI T_REG)
12590                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12591                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12592    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12593   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12595   return output_ieee_ccmpeq (insn, operands);
12597   [(set_attr "length" "4")
12598    (set_attr "fp_mode" "single")])
12600 (define_insn "cmpeqsf_media"
12601   [(set (match_operand:SI 0 "register_operand" "=r")
12602         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12603                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12604   "TARGET_SHMEDIA_FPU"
12605   "fcmpeq.s     %1, %2, %0"
12606   [(set_attr "type" "fcmp_media")])
12608 (define_insn "cmpgtsf_media"
12609   [(set (match_operand:SI 0 "register_operand" "=r")
12610         (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12611                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12612   "TARGET_SHMEDIA_FPU"
12613   "fcmpgt.s     %1, %2, %0"
12614   [(set_attr "type" "fcmp_media")])
12616 (define_insn "cmpgesf_media"
12617   [(set (match_operand:SI 0 "register_operand" "=r")
12618         (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12619                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12620   "TARGET_SHMEDIA_FPU"
12621   "fcmpge.s     %1, %2, %0"
12622   [(set_attr "type" "fcmp_media")])
12624 (define_insn "cmpunsf_media"
12625   [(set (match_operand:SI 0 "register_operand" "=r")
12626         (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12627                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12628   "TARGET_SHMEDIA_FPU"
12629   "fcmpun.s     %1, %2, %0"
12630   [(set_attr "type" "fcmp_media")])
12632 (define_expand "cbranchsf4"
12633   [(set (pc)
12634         (if_then_else (match_operator 0 "sh_float_comparison_operator"
12635                        [(match_operand:SF 1 "arith_operand" "")
12636                         (match_operand:SF 2 "arith_operand" "")])
12637                       (match_operand 3 "" "")
12638                       (pc)))]
12639   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12641   if (TARGET_SHMEDIA)
12642     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12643                                           operands[3]));
12644   else
12645     sh_emit_compare_and_branch (operands, SFmode);
12646   DONE;
12649 (define_expand "negsf2"
12650   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12651         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12652   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12654   if (TARGET_SH2E)
12655     {
12656       expand_sf_unop (&gen_negsf2_i, operands);
12657       DONE;
12658     }
12661 (define_insn "*negsf2_media"
12662   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12663         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12664   "TARGET_SHMEDIA_FPU"
12665   "fneg.s       %1, %0"
12666   [(set_attr "type" "fmove_media")])
12668 (define_insn "negsf2_i"
12669   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12670         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12671    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12672   "TARGET_SH2E"
12673   "fneg %0"
12674   [(set_attr "type" "fmove")
12675    (set_attr "fp_mode" "single")])
12677 (define_expand "sqrtsf2"
12678   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12679         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12680   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12682   if (TARGET_SH3E)
12683     {
12684       expand_sf_unop (&gen_sqrtsf2_i, operands);
12685       DONE;
12686     }
12689 (define_insn "*sqrtsf2_media"
12690   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12691         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12692   "TARGET_SHMEDIA_FPU"
12693   "fsqrt.s      %1, %0"
12694   [(set_attr "type" "fdiv_media")])
12696 (define_insn "sqrtsf2_i"
12697   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12698         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12699    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12700   "TARGET_SH3E"
12701   "fsqrt        %0"
12702   [(set_attr "type" "fdiv")
12703    (set_attr "fp_mode" "single")])
12705 (define_insn "rsqrtsf2"
12706   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12707         (div:SF (match_operand:SF 1 "immediate_operand" "i")
12708                 (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
12709    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12710   "TARGET_FPU_ANY && TARGET_FSRRA
12711    && operands[1] == CONST1_RTX (SFmode)"
12712   "fsrra        %0"
12713   [(set_attr "type" "fsrra")
12714    (set_attr "fp_mode" "single")])
12716 ;; When the sincos pattern is defined, the builtin functions sin and cos
12717 ;; will be expanded to the sincos pattern and one of the output values will
12718 ;; remain unused.
12719 (define_expand "sincossf3"
12720   [(set (match_operand:SF 0 "nonimmediate_operand")
12721         (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12722    (set (match_operand:SF 1 "nonimmediate_operand")
12723         (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
12724   "TARGET_FPU_ANY && TARGET_FSCA"
12726   rtx scaled = gen_reg_rtx (SFmode);
12727   rtx truncated = gen_reg_rtx (SImode);
12728   rtx fsca = gen_reg_rtx (V2SFmode);
12729   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12731   emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12732   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12733   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12734                           get_fpscr_rtx ()));
12736   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12737   emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
12738   DONE;
12741 (define_insn_and_split "fsca"
12742   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12743         (vec_concat:V2SF
12744          (unspec:SF [(mult:SF
12745                       (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12746                       (match_operand:SF 2 "fsca_scale_factor" "i"))
12747                     ] UNSPEC_FSINA)
12748          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12749                     ] UNSPEC_FCOSA)))
12750    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12751   "TARGET_FPU_ANY && TARGET_FSCA"
12752   "fsca fpul,%d0"
12753   "&& !fpul_operand (operands[1], SImode)"
12754   [(const_int 0)]
12756   /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12757      to a simple reg, otherwise reload will have trouble reloading the
12758      pseudo into fpul.  */
12759   rtx x = XEXP (operands[1], 0);
12760   while (x != NULL_RTX && !fpul_operand (x, SImode))
12761     {
12762       gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12763       x = XEXP (x, 0);
12764     }
12766   gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12767   emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12768   DONE;
12770   [(set_attr "type" "fsca")
12771    (set_attr "fp_mode" "single")])
12773 (define_expand "abssf2"
12774   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12775         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12776   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12778   if (TARGET_SH2E)
12779     {
12780       expand_sf_unop (&gen_abssf2_i, operands);
12781       DONE;
12782     }
12785 (define_insn "*abssf2_media"
12786   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12787         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12788   "TARGET_SHMEDIA_FPU"
12789   "fabs.s       %1, %0"
12790   [(set_attr "type" "fmove_media")])
12792 (define_insn "abssf2_i"
12793   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12794         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12795    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12796   "TARGET_SH2E"
12797   "fabs %0"
12798   [(set_attr "type" "fmove")
12799    (set_attr "fp_mode" "single")])
12801 (define_expand "adddf3"
12802   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12803         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12804                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12805   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12807   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12808     {
12809       expand_df_binop (&gen_adddf3_i, operands);
12810       DONE;
12811     }
12814 (define_insn "*adddf3_media"
12815   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12816         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12817                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12818   "TARGET_SHMEDIA_FPU"
12819   "fadd.d       %1, %2, %0"
12820   [(set_attr "type" "dfparith_media")])
12822 (define_insn "adddf3_i"
12823   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12824         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12825                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12826    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12827   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12828   "fadd %2,%0"
12829   [(set_attr "type" "dfp_arith")
12830    (set_attr "fp_mode" "double")])
12832 (define_expand "subdf3"
12833   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12834         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12835                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12836   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12838   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12839     {
12840       expand_df_binop (&gen_subdf3_i, operands);
12841       DONE;
12842     }
12845 (define_insn "*subdf3_media"
12846   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12847         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12848                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12849   "TARGET_SHMEDIA_FPU"
12850   "fsub.d       %1, %2, %0"
12851   [(set_attr "type" "dfparith_media")])
12853 (define_insn "subdf3_i"
12854   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12855         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12856                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12857    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12858   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12859   "fsub %2,%0"
12860   [(set_attr "type" "dfp_arith")
12861    (set_attr "fp_mode" "double")])
12863 (define_expand "muldf3"
12864   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12865         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12866                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12867   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12869   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12870     {
12871       expand_df_binop (&gen_muldf3_i, operands);
12872       DONE;
12873     }
12876 (define_insn "*muldf3_media"
12877   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12878         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12879                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12880   "TARGET_SHMEDIA_FPU"
12881   "fmul.d       %1, %2, %0"
12882   [(set_attr "type" "dfmul_media")])
12884 (define_insn "muldf3_i"
12885   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12886         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12887                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12888    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12889   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12890   "fmul %2,%0"
12891   [(set_attr "type" "dfp_mul")
12892    (set_attr "fp_mode" "double")])
12894 (define_expand "divdf3"
12895   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12896         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12897                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12898   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12900   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12901     {
12902       expand_df_binop (&gen_divdf3_i, operands);
12903       DONE;
12904     }
12907 (define_insn "*divdf3_media"
12908   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12909         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12910                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12911   "TARGET_SHMEDIA_FPU"
12912   "fdiv.d       %1, %2, %0"
12913   [(set_attr "type" "dfdiv_media")])
12915 (define_insn "divdf3_i"
12916   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12917         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12918                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12919    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12920   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12921   "fdiv %2,%0"
12922   [(set_attr "type" "dfdiv")
12923    (set_attr "fp_mode" "double")])
12925 (define_insn "floatdidf2"
12926   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12927         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12928   "TARGET_SHMEDIA_FPU"
12929   "float.qd     %1, %0"
12930   [(set_attr "type" "dfpconv_media")])
12932 (define_expand "floatsidf2"
12933   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12934         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
12935   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12937   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12938     {
12939       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12940                                       get_fpscr_rtx ()));
12941       DONE;
12942     }
12945 (define_insn "*floatsidf2_media"
12946   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12947         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12948   "TARGET_SHMEDIA_FPU"
12949   "float.ld     %1, %0"
12950   [(set_attr "type" "dfpconv_media")])
12952 (define_insn "floatsidf2_i"
12953   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12954         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
12955    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12956   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12957   "float        %1,%0"
12958   [(set_attr "type" "dfp_conv")
12959    (set_attr "fp_mode" "double")])
12961 (define_insn "fix_truncdfdi2"
12962   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12963         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12964   "TARGET_SHMEDIA_FPU"
12965   "ftrc.dq      %1, %0"
12966   [(set_attr "type" "dfpconv_media")])
12968 (define_expand "fix_truncdfsi2"
12969   [(set (match_operand:SI 0 "fpul_operand" "")
12970         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12971   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12973   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12974     {
12975       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
12976                                           get_fpscr_rtx ()));
12977       DONE;
12978     }
12981 (define_insn "*fix_truncdfsi2_media"
12982   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12983         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12984   "TARGET_SHMEDIA_FPU"
12985   "ftrc.dl      %1, %0"
12986   [(set_attr "type" "dfpconv_media")])
12988 (define_insn "fix_truncdfsi2_i"
12989   [(set (match_operand:SI 0 "fpul_operand" "=y")
12990         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12991    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12992   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12993   "ftrc %1,%0"
12994   [(set_attr "type" "dfp_conv")
12995    (set_attr "dfp_comp" "no")
12996    (set_attr "fp_mode" "double")])
12998 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
12999 ;; fix_truncdfsi2_i.
13000 ;; (define_insn "fix_truncdfsi2_i4"
13001 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13002 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
13003 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
13004 ;;    (clobber (reg:SI FPUL_REG))]
13005 ;;   "TARGET_SH4"
13006 ;;   "#"
13007 ;;   [(set_attr "length" "4")
13008 ;;    (set_attr "fp_mode" "double")])
13010 ;; (define_split
13011 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13012 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
13013 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
13014 ;;    (clobber (reg:SI FPUL_REG))]
13015 ;;   "TARGET_SH4"
13016 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
13017 ;;            (use (match_dup 2))])
13018 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
13020 (define_insn "cmpgtdf_t"
13021   [(set (reg:SI T_REG)
13022         (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13023                (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13024    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13025   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13026   "fcmp/gt      %1,%0"
13027   [(set_attr "type" "dfp_cmp")
13028    (set_attr "fp_mode" "double")])
13030 (define_insn "cmpeqdf_t"
13031   [(set (reg:SI T_REG)
13032         (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13033                (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13034    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13035   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13036   "fcmp/eq      %1,%0"
13037   [(set_attr "type" "dfp_cmp")
13038    (set_attr "fp_mode" "double")])
13040 (define_insn "*ieee_ccmpeqdf_t"
13041   [(set (reg:SI T_REG)
13042         (ior:SI (reg:SI T_REG)
13043                 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13044                        (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
13045    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13046   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13048   return output_ieee_ccmpeq (insn, operands);
13050   [(set_attr "length" "4")
13051    (set_attr "fp_mode" "double")])
13053 (define_insn "cmpeqdf_media"
13054   [(set (match_operand:SI 0 "register_operand" "=r")
13055         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13056                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13057   "TARGET_SHMEDIA_FPU"
13058   "fcmpeq.d     %1,%2,%0"
13059   [(set_attr "type" "fcmp_media")])
13061 (define_insn "cmpgtdf_media"
13062   [(set (match_operand:SI 0 "register_operand" "=r")
13063         (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13064                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13065   "TARGET_SHMEDIA_FPU"
13066   "fcmpgt.d     %1,%2,%0"
13067   [(set_attr "type" "fcmp_media")])
13069 (define_insn "cmpgedf_media"
13070   [(set (match_operand:SI 0 "register_operand" "=r")
13071         (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13072                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13073   "TARGET_SHMEDIA_FPU"
13074   "fcmpge.d     %1,%2,%0"
13075   [(set_attr "type" "fcmp_media")])
13077 (define_insn "cmpundf_media"
13078   [(set (match_operand:SI 0 "register_operand" "=r")
13079         (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13080                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13081   "TARGET_SHMEDIA_FPU"
13082   "fcmpun.d     %1,%2,%0"
13083   [(set_attr "type" "fcmp_media")])
13085 (define_expand "cbranchdf4"
13086   [(set (pc)
13087         (if_then_else (match_operator 0 "sh_float_comparison_operator"
13088                        [(match_operand:DF 1 "arith_operand" "")
13089                         (match_operand:DF 2 "arith_operand" "")])
13090                       (match_operand 3 "" "")
13091                       (pc)))]
13092   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13094   if (TARGET_SHMEDIA)
13095     emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13096                                           operands[3]));
13097   else
13098     sh_emit_compare_and_branch (operands, DFmode);
13099   DONE;
13102 (define_expand "negdf2"
13103   [(set (match_operand:DF 0 "fp_arith_reg_operand")
13104         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13105   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13107   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13108     {
13109       expand_df_unop (&gen_negdf2_i, operands);
13110       DONE;
13111     }
13114 (define_insn "*negdf2_media"
13115   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13116         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13117   "TARGET_SHMEDIA_FPU"
13118   "fneg.d       %1, %0"
13119   [(set_attr "type" "fmove_media")])
13121 (define_insn "negdf2_i"
13122   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13123         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13124    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13125   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13126   "fneg %0"
13127   [(set_attr "type" "fmove")
13128    (set_attr "fp_mode" "double")])
13130 (define_expand "sqrtdf2"
13131   [(set (match_operand:DF 0 "fp_arith_reg_operand")
13132         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13133   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13135   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13136     {
13137       expand_df_unop (&gen_sqrtdf2_i, operands);
13138       DONE;
13139     }
13142 (define_insn "*sqrtdf2_media"
13143   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13144         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13145   "TARGET_SHMEDIA_FPU"
13146   "fsqrt.d      %1, %0"
13147   [(set_attr "type" "dfdiv_media")])
13149 (define_insn "sqrtdf2_i"
13150   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13151         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13152    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13153   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13154   "fsqrt        %0"
13155   [(set_attr "type" "dfdiv")
13156    (set_attr "fp_mode" "double")])
13158 (define_expand "absdf2"
13159   [(set (match_operand:DF 0 "fp_arith_reg_operand")
13160         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13161   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13163   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13164     {
13165       expand_df_unop (&gen_absdf2_i, operands);
13166       DONE;
13167     }
13170 (define_insn "*absdf2_media"
13171   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13172         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13173   "TARGET_SHMEDIA_FPU"
13174   "fabs.d       %1, %0"
13175   [(set_attr "type" "fmove_media")])
13177 (define_insn "absdf2_i"
13178   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13179         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13180    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13181   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13182   "fabs %0"
13183   [(set_attr "type" "fmove")
13184    (set_attr "fp_mode" "double")])
13186 (define_expand "extendsfdf2"
13187   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13188         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
13189   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13191   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13192     {
13193       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
13194                                         get_fpscr_rtx ()));
13195       DONE;
13196     }
13199 (define_insn "*extendsfdf2_media"
13200   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13201         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13202   "TARGET_SHMEDIA_FPU"
13203   "fcnv.sd      %1, %0"
13204   [(set_attr "type" "dfpconv_media")])
13206 (define_insn "extendsfdf2_i4"
13207   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13208         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
13209    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13210   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13211   "fcnvsd  %1,%0"
13212   [(set_attr "type" "fp")
13213    (set_attr "fp_mode" "double")])
13215 (define_expand "truncdfsf2"
13216   [(set (match_operand:SF 0 "fpul_operand" "")
13217         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13218   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13220   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13221     {
13222       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
13223                                        get_fpscr_rtx ()));
13224       DONE;
13225     }
13228 (define_insn "*truncdfsf2_media"
13229   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13230         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13231   "TARGET_SHMEDIA_FPU"
13232   "fcnv.ds      %1, %0"
13233   [(set_attr "type" "dfpconv_media")])
13235 (define_insn "truncdfsf2_i4"
13236   [(set (match_operand:SF 0 "fpul_operand" "=y")
13237         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13238    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
13239   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13240   "fcnvds  %1,%0"
13241   [(set_attr "type" "fp")
13242    (set_attr "fp_mode" "double")])
13244 ;; -------------------------------------------------------------------------
13245 ;; Bit field extract patterns.
13246 ;; -------------------------------------------------------------------------
13248 ;; These give better code for packed bitfields,  because they allow
13249 ;; auto-increment addresses to be generated.
13251 (define_expand "insv"
13252   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
13253                          (match_operand:SI 1 "immediate_operand" "")
13254                          (match_operand:SI 2 "immediate_operand" ""))
13255         (match_operand:SI 3 "general_operand" ""))]
13256   "TARGET_SH1 && TARGET_BIG_ENDIAN"
13258   rtx addr_target, orig_address, shift_reg, qi_val;
13259   HOST_WIDE_INT bitsize, size, v = 0;
13260   rtx x = operands[3];
13262   if (TARGET_SH2A && TARGET_BITOPS
13263       && (satisfies_constraint_Sbw (operands[0])
13264           || satisfies_constraint_Sbv (operands[0]))
13265       && satisfies_constraint_M (operands[1])
13266       && satisfies_constraint_K03 (operands[2]))
13267     {
13268       if (satisfies_constraint_N (operands[3]))
13269         {
13270           emit_insn (gen_bclr_m2a (operands[0], operands[2]));
13271           DONE;
13272         }
13273       else if (satisfies_constraint_M (operands[3]))
13274         {
13275           emit_insn (gen_bset_m2a (operands[0], operands[2]));
13276           DONE;
13277         }
13278       else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
13279                 && satisfies_constraint_M (operands[1]))
13280         {
13281           emit_insn (gen_bst_m2a (operands[0], operands[2]));
13282           DONE;
13283         }
13284       else if (REG_P (operands[3])
13285                && satisfies_constraint_M (operands[1]))
13286         {
13287           emit_insn (gen_bld_reg (operands[3], const0_rtx));
13288           emit_insn (gen_bst_m2a (operands[0], operands[2]));
13289           DONE;
13290         }
13291     }
13292   /* ??? expmed doesn't care for non-register predicates.  */
13293   if (! memory_operand (operands[0], VOIDmode)
13294       || ! immediate_operand (operands[1], VOIDmode)
13295       || ! immediate_operand (operands[2], VOIDmode)
13296       || ! general_operand (x, VOIDmode))
13297     FAIL;
13298   /* If this isn't a 16 / 24 / 32 bit field, or if
13299      it doesn't start on a byte boundary, then fail.  */
13300   bitsize = INTVAL (operands[1]);
13301   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13302       || (INTVAL (operands[2]) % 8) != 0)
13303     FAIL;
13305   size = bitsize / 8;
13306   orig_address = XEXP (operands[0], 0);
13307   shift_reg = gen_reg_rtx (SImode);
13308   if (CONST_INT_P (x))
13309     {
13310       v = INTVAL (x);
13311       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13312     }
13313   else
13314     {
13315       emit_insn (gen_movsi (shift_reg, operands[3]));
13316       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13317     }
13318   addr_target = copy_addr_to_reg (plus_constant (Pmode,
13319                                                  orig_address, size - 1));
13321   operands[0] = replace_equiv_address (operands[0], addr_target);
13322   emit_insn (gen_movqi (operands[0], qi_val));
13324   while (size -= 1)
13325     {
13326       if (CONST_INT_P (x))
13327         qi_val
13328           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13329       else
13330         {
13331           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13332           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13333         }
13334       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13335       emit_insn (gen_movqi (operands[0], qi_val));
13336     }
13338   DONE;
13341 (define_insn "movua"
13342   [(set (match_operand:SI 0 "register_operand" "=z")
13343         (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13344                    UNSPEC_MOVUA))]
13345   "TARGET_SH4A_ARCH"
13346   "movua.l      %1,%0"
13347   [(set_attr "type" "movua")])
13349 ;; We shouldn't need this, but cse replaces increments with references
13350 ;; to other regs before flow has a chance to create post_inc
13351 ;; addressing modes, and only postreload's cse_move2add brings the
13352 ;; increments back to a usable form.
13353 (define_peephole2
13354   [(set (match_operand:SI 0 "register_operand" "")
13355         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13356                          (const_int 32) (const_int 0)))
13357    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13358   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
13359   [(set (match_operand:SI 0 "register_operand" "")
13360         (sign_extract:SI (mem:SI (post_inc:SI
13361                                   (match_operand:SI 1 "register_operand" "")))
13362                          (const_int 32) (const_int 0)))]
13363   "")
13365 (define_expand "extv"
13366   [(set (match_operand:SI 0 "register_operand" "")
13367         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13368                          (match_operand 2 "const_int_operand" "")
13369                          (match_operand 3 "const_int_operand" "")))]
13370   "TARGET_SH4A_ARCH || TARGET_SH2A"
13372   if (TARGET_SH2A && TARGET_BITOPS
13373       && (satisfies_constraint_Sbw (operands[1])
13374           || satisfies_constraint_Sbv (operands[1]))
13375       && satisfies_constraint_M (operands[2])
13376       && satisfies_constraint_K03 (operands[3]))
13377    {
13378       emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13379       if (REGNO (operands[0]) != T_REG)
13380         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13381       DONE;
13382    }
13383   if (TARGET_SH4A_ARCH
13384       && INTVAL (operands[2]) == 32
13385       && INTVAL (operands[3]) == 0
13386       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13387     {
13388       rtx src = adjust_address (operands[1], BLKmode, 0);
13389       set_mem_size (src, 4);
13390       emit_insn (gen_movua (operands[0], src));
13391       DONE;
13392     }
13394   FAIL;
13397 (define_expand "extzv"
13398   [(set (match_operand:SI 0 "register_operand" "")
13399         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13400                          (match_operand 2 "const_int_operand" "")
13401                          (match_operand 3 "const_int_operand" "")))]
13402   "TARGET_SH4A_ARCH || TARGET_SH2A"
13404   if (TARGET_SH2A && TARGET_BITOPS
13405       && (satisfies_constraint_Sbw (operands[1])
13406           || satisfies_constraint_Sbv (operands[1]))
13407       && satisfies_constraint_M (operands[2])
13408       && satisfies_constraint_K03 (operands[3]))
13409     {
13410       emit_insn (gen_bld_m2a (operands[1], operands[3]));
13411       if (REGNO (operands[0]) != T_REG)
13412         emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13413       DONE;
13414     }
13415   if (TARGET_SH4A_ARCH
13416       && INTVAL (operands[2]) == 32
13417       && INTVAL (operands[3]) == 0
13418       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13419     {
13420       rtx src = adjust_address (operands[1], BLKmode, 0);
13421       set_mem_size (src, 4);
13422       emit_insn (gen_movua (operands[0], src));
13423       DONE;
13424     }
13426   FAIL;
13429 ;; SH2A instructions for bitwise operations.
13430 ;; FIXME: Convert multiple instruction insns to insn_and_split.
13431 ;; FIXME: Use iterators to fold at least and,xor,or insn variations.
13433 ;; Clear a bit in a memory location.
13434 (define_insn "bclr_m2a"
13435   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13436         (and:QI
13437             (not:QI (ashift:QI (const_int 1)
13438                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
13439             (match_dup 0)))]
13440   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13441   "@
13442         bclr.b  %1,%0
13443         bclr.b  %1,@(0,%t0)"
13444 [(set_attr "length" "4,4")])
13446 (define_insn "bclrmem_m2a"
13447   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13448         (and:QI (match_dup 0)
13449                 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13450   "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13451   "@
13452         bclr.b  %W1,%0
13453         bclr.b  %W1,@(0,%t0)"
13454   [(set_attr "length" "4,4")])
13456 ;; Set a bit in a memory location.
13457 (define_insn "bset_m2a"
13458   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13459         (ior:QI
13460             (ashift:QI (const_int 1)
13461                        (match_operand:QI 1 "const_int_operand" "K03,K03"))
13462             (match_dup 0)))]
13463   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13464   "@
13465         bset.b  %1,%0
13466         bset.b  %1,@(0,%t0)"
13467   [(set_attr "length" "4,4")])
13469 (define_insn "bsetmem_m2a"
13470   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13471         (ior:QI (match_dup 0)
13472                 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13473   "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13474   "@
13475         bset.b  %V1,%0
13476         bset.b  %V1,@(0,%t0)"
13477   [(set_attr "length" "4,4")])
13479 ;;; Transfer the contents of the T bit to a specified bit of memory.
13480 (define_insn "bst_m2a"
13481   [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13482         (if_then_else (eq (reg:SI T_REG) (const_int 0))
13483             (and:QI
13484                 (not:QI (ashift:QI (const_int 1)
13485                         (match_operand:QI 1 "const_int_operand" "K03,K03")))
13486                 (match_dup 0))
13487             (ior:QI
13488                 (ashift:QI (const_int 1) (match_dup 1))
13489                 (match_dup 0))))]
13490   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13491   "@
13492         bst.b   %1,%0
13493         bst.b   %1,@(0,%t0)"
13494   [(set_attr "length" "4")])
13496 ;; Store a specified bit of memory in the T bit.
13497 (define_insn "bld_m2a"
13498   [(set (reg:SI T_REG)
13499         (zero_extract:SI
13500             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13501             (const_int 1)
13502             (match_operand 1 "const_int_operand" "K03,K03")))]
13503   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13504   "@
13505         bld.b   %1,%0
13506         bld.b   %1,@(0,%t0)"
13507   [(set_attr "length" "4,4")])
13509 ;; Store a specified bit of memory in the T bit.
13510 (define_insn "bldsign_m2a"
13511   [(set (reg:SI T_REG)
13512         (sign_extract:SI
13513             (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13514             (const_int 1)
13515             (match_operand 1 "const_int_operand" "K03,K03")))]
13516   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13517   "@
13518         bld.b   %1,%0
13519         bld.b   %1,@(0,%t0)"
13520   [(set_attr "length" "4,4")])
13522 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13523 (define_insn "bld_reg"
13524   [(set (reg:SI T_REG)
13525         (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13526                          (const_int 1)
13527                          (match_operand 1 "const_int_operand" "K03")))]
13528   "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13529   "bld  %1,%0")
13531 (define_insn "*bld_regqi"
13532   [(set (reg:SI T_REG)
13533         (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13534                          (const_int 1)
13535                          (match_operand 1 "const_int_operand" "K03")))]
13536   "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13537   "bld  %1,%0")
13539 ;; Take logical and of a specified bit of memory with the T bit and
13540 ;; store its result in the T bit.
13541 (define_insn "band_m2a"
13542   [(set (reg:SI T_REG)
13543         (and:SI (reg:SI T_REG)
13544                 (zero_extract:SI
13545                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13546                     (const_int 1)
13547                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13548   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13549   "@
13550         band.b  %1,%0
13551         band.b  %1,@(0,%t0)"
13552   [(set_attr "length" "4,4")])
13554 (define_insn "bandreg_m2a"
13555   [(set (match_operand:SI 0 "register_operand" "=r,r")
13556         (and:SI (zero_extract:SI
13557                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13558                     (const_int 1)
13559                     (match_operand 2 "const_int_operand" "K03,K03"))
13560                 (match_operand:SI 3 "register_operand" "r,r")))]
13561   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13563   static const char* alt[] =
13564   {
13565        "band.b  %2,%1"          "\n"
13566     "   movt    %0",
13568        "band.b  %2,@(0,%t1)"    "\n"
13569     "   movt    %0"
13570   };
13571   return alt[which_alternative];
13573   [(set_attr "length" "6,6")])
13575 ;; Take logical or of a specified bit of memory with the T bit and
13576 ;; store its result in the T bit.
13577 (define_insn "bor_m2a"
13578   [(set (reg:SI T_REG)
13579         (ior:SI (reg:SI T_REG)
13580                 (zero_extract:SI
13581                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13582                     (const_int 1)
13583                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13584   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13585   "@
13586         bor.b   %1,%0
13587         bor.b   %1,@(0,%t0)"
13588   [(set_attr "length" "4,4")])
13590 (define_insn "borreg_m2a"
13591   [(set (match_operand:SI 0 "register_operand" "=r,r")
13592         (ior:SI (zero_extract:SI
13593                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13594                     (const_int 1)
13595                     (match_operand 2 "const_int_operand" "K03,K03"))
13596                 (match_operand:SI 3 "register_operand" "=r,r")))]
13597   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13599   static const char* alt[] =
13600   {
13601        "bor.b   %2,%1"          "\n"
13602     "   movt    %0",
13604        "bor.b   %2,@(0,%t1)"    "\n"
13605     "   movt    %0"
13606   };
13607   return alt[which_alternative];
13609   [(set_attr "length" "6,6")])
13611 ;; Take exclusive or of a specified bit of memory with the T bit and
13612 ;; store its result in the T bit.
13613 (define_insn "bxor_m2a"
13614   [(set (reg:SI T_REG)
13615         (xor:SI (reg:SI T_REG)
13616                 (zero_extract:SI
13617                     (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13618                     (const_int 1)
13619                     (match_operand 1 "const_int_operand" "K03,K03"))))]
13620   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13621   "@
13622         bxor.b  %1,%0
13623         bxor.b  %1,@(0,%t0)"
13624   [(set_attr "length" "4,4")])
13626 (define_insn "bxorreg_m2a"
13627   [(set (match_operand:SI 0 "register_operand" "=r,r")
13628         (xor:SI (zero_extract:SI
13629                     (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13630                     (const_int 1)
13631                     (match_operand 2 "const_int_operand" "K03,K03"))
13632                 (match_operand:SI 3 "register_operand" "=r,r")))]
13633   "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13635   static const char* alt[] =
13636   {
13637        "bxor.b  %2,%1"          "\n"
13638     "   movt    %0",
13640        "bxor.b  %2,@(0,%t1)"    "\n"
13641     "   movt    %0"
13642   };
13643   return alt[which_alternative];
13645   [(set_attr "length" "6,6")])
13647 ;; -------------------------------------------------------------------------
13648 ;; Peepholes
13649 ;; -------------------------------------------------------------------------
13650 ;; This matches cases where the bit in a memory location is set.
13651 (define_peephole2
13652   [(set (match_operand:SI 0 "register_operand")
13653         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
13654    (set (match_dup 0)
13655         (ior:SI (match_dup 0)
13656         (match_operand:SI 2 "const_int_operand")))
13657    (set (match_dup 1)
13658         (match_operand 3 "arith_reg_operand"))]
13659   "TARGET_SH2A && TARGET_BITOPS
13660    && satisfies_constraint_Pso (operands[2])
13661    && REGNO (operands[0]) == REGNO (operands[3])"
13662   [(set (match_dup 1)
13663         (ior:QI (match_dup 1) (match_dup 2)))]
13664   "")
13666 ;; This matches cases where the bit in a memory location is cleared.
13667 (define_peephole2
13668   [(set (match_operand:SI 0 "register_operand")
13669         (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
13670    (set (match_dup 0)
13671         (and:SI (match_dup 0)
13672         (match_operand:SI 2 "const_int_operand")))
13673    (set (match_dup 1)
13674         (match_operand 3 "arith_reg_operand"))]
13675   "TARGET_SH2A && TARGET_BITOPS
13676    && satisfies_constraint_Psz (operands[2])
13677    && REGNO (operands[0]) == REGNO (operands[3])"
13678   [(set (match_dup 1)
13679         (and:QI (match_dup 1) (match_dup 2)))]
13680   "")
13682 ;; This matches cases where a stack pointer increment at the start of the
13683 ;; epilogue combines with a stack slot read loading the return value.
13684 (define_peephole
13685   [(set (match_operand:SI 0 "arith_reg_operand" "")
13686         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13687    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13688   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13689   "mov.l        @%1+,%0")
13691 ;; See the comment on the dt combiner pattern above.
13692 (define_peephole
13693   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13694         (plus:SI (match_dup 0)
13695                  (const_int -1)))
13696    (set (reg:SI T_REG)
13697         (eq:SI (match_dup 0) (const_int 0)))]
13698   "TARGET_SH2"
13699   "dt   %0")
13701 ;; The following peepholes fold load sequences for which reload was not
13702 ;; able to generate a displacement addressing move insn.
13703 ;; This can happen when reload has to transform a move insn 
13704 ;; without displacement into one with displacement.  Or when reload can't
13705 ;; fit a displacement into the insn's constraints.  In the latter case, the
13706 ;; load destination reg remains at r0, which reload compensates by inserting
13707 ;; another mov insn.
13709 ;; Fold sequence:
13710 ;;      mov #54,r0
13711 ;;      mov.{b,w} @(r0,r15),r0
13712 ;;      mov r0,r3
13713 ;; into:
13714 ;;      mov.{b,w} @(54,r15),r3
13716 (define_peephole2
13717   [(set (match_operand:SI 0 "arith_reg_dest" "")
13718         (match_operand:SI 1 "const_int_operand" ""))
13719    (set (match_operand:SI 2 "arith_reg_dest" "")
13720         (sign_extend:SI
13721          (mem:QI (plus:SI (match_dup 0)
13722                           (match_operand:SI 3 "arith_reg_operand" "")))))
13723    (set (match_operand:QI 4 "arith_reg_dest" "")
13724         (match_operand:QI 5 "arith_reg_operand" ""))]
13725   "TARGET_SH2A
13726    && sh_legitimate_index_p (QImode, operands[1], true, true)
13727    && REGNO (operands[2]) == REGNO (operands[5])
13728    && peep2_reg_dead_p (3, operands[5])"
13729   [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13730   "")
13732 (define_peephole2
13733   [(set (match_operand:SI 0 "arith_reg_dest" "")
13734         (match_operand:SI 1 "const_int_operand" ""))
13735    (set (match_operand:SI 2 "arith_reg_dest" "")
13736         (sign_extend:SI
13737          (mem:HI (plus:SI (match_dup 0)
13738                           (match_operand:SI 3 "arith_reg_operand" "")))))
13739    (set (match_operand:HI 4 "arith_reg_dest" "")
13740         (match_operand:HI 5 "arith_reg_operand" ""))]
13741   "TARGET_SH2A
13742    && sh_legitimate_index_p (HImode, operands[1], true, true)
13743    && REGNO (operands[2]) == REGNO (operands[5])
13744    && peep2_reg_dead_p (3, operands[5])"
13745   [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13746   "")
13748 ;; Fold sequence:
13749 ;;      mov #54,r0
13750 ;;      mov.{b,w} @(r0,r15),r1
13751 ;; into:
13752 ;;      mov.{b,w} @(54,r15),r1
13754 (define_peephole2
13755   [(set (match_operand:SI 0 "arith_reg_dest" "")
13756         (match_operand:SI 1 "const_int_operand" ""))
13757    (set (match_operand:SI 2 "arith_reg_dest" "")
13758          (sign_extend:SI
13759          (mem:QI (plus:SI (match_dup 0)
13760                           (match_operand:SI 3 "arith_reg_operand" "")))))]
13761   "TARGET_SH2A
13762    && sh_legitimate_index_p (QImode, operands[1], true, true)
13763    && (peep2_reg_dead_p (2, operands[0])
13764        || REGNO (operands[0]) == REGNO (operands[2]))"
13765   [(set (match_dup 2)
13766         (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13767   "")
13769 (define_peephole2
13770   [(set (match_operand:SI 0 "arith_reg_dest" "")
13771         (match_operand:SI 1 "const_int_operand" ""))
13772    (set (match_operand:SI 2 "arith_reg_dest" "")
13773          (sign_extend:SI
13774          (mem:HI (plus:SI (match_dup 0)
13775                           (match_operand:SI 3 "arith_reg_operand" "")))))]
13776   "TARGET_SH2A
13777    && sh_legitimate_index_p (HImode, operands[1], true, true)
13778    && (peep2_reg_dead_p (2, operands[0])
13779        || REGNO (operands[0]) == REGNO (operands[2]))"
13780   [(set (match_dup 2)
13781         (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13782   "")
13784 ;; Fold sequence:
13785 ;;      mov.{b,w} @(r0,r15),r0
13786 ;;      mov r0,r3
13787 ;; into:
13788 ;;      mov.{b,w} @(r0,r15),r3
13790 ;; This can happen when initially a displacement address is picked, where
13791 ;; the destination reg is fixed to r0, and then the address is transformed
13792 ;; into 'r0 + reg'.
13793 (define_peephole2
13794   [(set (match_operand:SI 0 "arith_reg_dest" "")
13795         (sign_extend:SI
13796          (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13797                           (match_operand:SI 2 "arith_reg_operand" "")))))
13798    (set (match_operand:QI 3 "arith_reg_dest" "")
13799         (match_operand:QI 4 "arith_reg_operand" ""))]
13800   "TARGET_SH1
13801    && REGNO (operands[0]) == REGNO (operands[4])
13802    && peep2_reg_dead_p (2, operands[0])"
13803   [(set (match_dup 3)
13804         (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13805   "")
13807 (define_peephole2
13808   [(set (match_operand:SI 0 "arith_reg_dest" "")
13809         (sign_extend:SI
13810          (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13811                           (match_operand:SI 2 "arith_reg_operand" "")))))
13812    (set (match_operand:HI 3 "arith_reg_dest" "")
13813         (match_operand:HI 4 "arith_reg_operand" ""))]
13814   "TARGET_SH1
13815    && REGNO (operands[0]) == REGNO (operands[4])
13816    && peep2_reg_dead_p (2, operands[0])"
13817   [(set (match_dup 3)
13818         (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13819   "")
13821 (define_peephole
13822   [(set (match_operand:SI 0 "register_operand" "=r")
13823         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13824    (set (mem:SF (match_dup 0))
13825         (match_operand:SF 2 "general_movsrc_operand" ""))]
13826   "TARGET_SH1 && REGNO (operands[0]) == 0
13827    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13828        || (GET_CODE (operands[2]) == SUBREG
13829            && REGNO (SUBREG_REG (operands[2])) < 16))
13830    && reg_unused_after (operands[0], insn)"
13831   "mov.l        %2,@(%0,%1)")
13833 (define_peephole
13834   [(set (match_operand:SI 0 "register_operand" "=r")
13835         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13836    (set (match_operand:SF 2 "general_movdst_operand" "")
13838         (mem:SF (match_dup 0)))]
13839   "TARGET_SH1 && REGNO (operands[0]) == 0
13840    && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13841        || (GET_CODE (operands[2]) == SUBREG
13842            && REGNO (SUBREG_REG (operands[2])) < 16))
13843    && reg_unused_after (operands[0], insn)"
13844   "mov.l        @(%0,%1),%2")
13846 (define_peephole
13847   [(set (match_operand:SI 0 "register_operand" "=r")
13848         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13849    (set (mem:SF (match_dup 0))
13850         (match_operand:SF 2 "general_movsrc_operand" ""))]
13851   "TARGET_SH2E && REGNO (operands[0]) == 0
13852    && ((REG_P (operands[2])
13853         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13854        || (GET_CODE (operands[2]) == SUBREG
13855            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13856    && reg_unused_after (operands[0], insn)"
13857   "fmov{.s|}    %2,@(%0,%1)")
13859 (define_peephole
13860   [(set (match_operand:SI 0 "register_operand" "=r")
13861         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13862    (set (match_operand:SF 2 "general_movdst_operand" "")
13864         (mem:SF (match_dup 0)))]
13865   "TARGET_SH2E && REGNO (operands[0]) == 0
13866    && ((REG_P (operands[2])
13867         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13868        || (GET_CODE (operands[2]) == SUBREG
13869            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13870    && reg_unused_after (operands[0], insn)"
13871   "fmov{.s|}    @(%0,%1),%2")
13873 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13874 (define_insn "sp_switch_1"
13875   [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
13876     UNSPECV_SP_SWITCH_B))]
13877   "TARGET_SH1"
13879   return       "mov.l   r0,@-r15"       "\n"
13880          "      mov.l   %0,r0"          "\n"
13881          "      mov.l   @r0,r0"         "\n"
13882          "      mov.l   r15,@-r0"       "\n"
13883          "      mov     r0,r15";
13885   [(set_attr "length" "10")])
13887 ;; Switch back to the original stack for interrupt functions with the
13888 ;; sp_switch attribute.
13889 (define_insn "sp_switch_2"
13890   [(unspec_volatile [(const_int 0)]
13891     UNSPECV_SP_SWITCH_E)]
13892   "TARGET_SH1"
13894   return       "mov.l   @r15,r15"       "\n"
13895          "      mov.l   @r15+,r0";
13897   [(set_attr "length" "4")])
13899 ;; -------------------------------------------------------------------------
13900 ;; Integer vector moves
13901 ;; -------------------------------------------------------------------------
13903 (define_expand "movv8qi"
13904   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13905         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13906   "TARGET_SHMEDIA"
13908   prepare_move_operands (operands, V8QImode);
13911 (define_insn "movv8qi_i"
13912   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13913         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13914   "TARGET_SHMEDIA
13915    && (register_operand (operands[0], V8QImode)
13916        || sh_register_operand (operands[1], V8QImode))"
13917   "@
13918         add     %1, r63, %0
13919         movi    %1, %0
13920         #
13921         ld%M1.q %m1, %0
13922         st%M0.q %m0, %N1"
13923   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13924    (set_attr "length" "4,4,16,4,4")])
13926 (define_split
13927   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13928         (subreg:V8QI (const_int 0) 0))]
13929   "TARGET_SHMEDIA"
13930   [(set (match_dup 0)
13931         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13932                             (const_int 0) (const_int 0) (const_int 0)
13933                             (const_int 0) (const_int 0)]))])
13935 (define_split
13936   [(set (match_operand 0 "arith_reg_dest" "")
13937         (match_operand 1 "sh_rep_vec" ""))]
13938   "TARGET_SHMEDIA && reload_completed
13939    && GET_MODE (operands[0]) == GET_MODE (operands[1])
13940    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13941    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13942    && (XVECEXP (operands[1], 0, 0) != const0_rtx
13943        || XVECEXP (operands[1], 0, 1) != const0_rtx)
13944    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13945        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13946   [(set (match_dup 0) (match_dup 1))
13947    (match_dup 2)]
13949   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
13950   rtx elt1 = XVECEXP (operands[1], 0, 1);
13952   if (unit_size > 2)
13953     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
13954   else
13955     {
13956       if (unit_size < 2)
13957         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
13958       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
13959     }
13960   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
13961   operands[1] = XVECEXP (operands[1], 0, 0);
13962   if (unit_size < 2)
13963     {
13964       if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
13965         operands[1]
13966           = GEN_INT (TARGET_LITTLE_ENDIAN
13967                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
13968                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
13969       else
13970         {
13971           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
13972           operands[1]
13973             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
13974         }
13975     }
13978 (define_split
13979   [(set (match_operand 0 "arith_reg_dest" "")
13980         (match_operand 1 "sh_const_vec" ""))]
13981   "TARGET_SHMEDIA && reload_completed
13982    && GET_MODE (operands[0]) == GET_MODE (operands[1])
13983    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
13984   [(set (match_dup 0) (match_dup 1))]
13986   rtx v = operands[1];
13987   enum machine_mode new_mode
13988     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
13990   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
13991   operands[1]
13992     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
13995 (define_expand "movv2hi"
13996   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
13997         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
13998   "TARGET_SHMEDIA"
14000   prepare_move_operands (operands, V2HImode);
14003 (define_insn "movv2hi_i"
14004   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14005         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14006   "TARGET_SHMEDIA
14007    && (register_operand (operands[0], V2HImode)
14008        || sh_register_operand (operands[1], V2HImode))"
14009   "@
14010         add.l   %1, r63, %0
14011         movi    %1, %0
14012         #
14013         ld%M1.l %m1, %0
14014         st%M0.l %m0, %N1"
14015   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
14016    (set_attr "length" "4,4,16,4,4")
14017    (set (attr "highpart")
14018         (cond [(match_test "sh_contains_memref_p (insn)")
14019                (const_string "user")]
14020               (const_string "ignore")))])
14022 (define_expand "movv4hi"
14023   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
14024         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
14025   "TARGET_SHMEDIA"
14027   prepare_move_operands (operands, V4HImode);
14030 (define_insn "movv4hi_i"
14031   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
14032         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14033   "TARGET_SHMEDIA
14034    && (register_operand (operands[0], V4HImode)
14035        || sh_register_operand (operands[1], V4HImode))"
14036   "@
14037         add     %1, r63, %0
14038         movi    %1, %0
14039         #
14040         ld%M1.q %m1, %0
14041         st%M0.q %m0, %N1"
14042   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
14043    (set_attr "length" "4,4,16,4,4")
14044    (set_attr "highpart" "depend")])
14046 (define_expand "movv2si"
14047   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
14048         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
14049   "TARGET_SHMEDIA"
14051   prepare_move_operands (operands, V2SImode);
14054 (define_insn "movv2si_i"
14055   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
14056         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14057   "TARGET_SHMEDIA
14058    && (register_operand (operands[0], V2SImode)
14059        || sh_register_operand (operands[1], V2SImode))"
14060   "@
14061         add     %1, r63, %0
14062         #
14063         #
14064         ld%M1.q %m1, %0
14065         st%M0.q %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" "depend")])
14070 ;; -------------------------------------------------------------------------
14071 ;; Multimedia Intrinsics
14072 ;; -------------------------------------------------------------------------
14074 (define_insn "absv2si2"
14075   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14076         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
14077   "TARGET_SHMEDIA"
14078   "mabs.l       %1, %0"
14079   [(set_attr "type" "mcmp_media")
14080    (set_attr "highpart" "depend")])
14082 (define_insn "absv4hi2"
14083   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14084         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
14085   "TARGET_SHMEDIA"
14086   "mabs.w       %1, %0"
14087   [(set_attr "type" "mcmp_media")
14088    (set_attr "highpart" "depend")])
14090 (define_insn "addv2si3"
14091   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14092         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14093                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14094   "TARGET_SHMEDIA"
14095   "madd.l       %1, %2, %0"
14096   [(set_attr "type" "arith_media")
14097    (set_attr "highpart" "depend")])
14099 (define_insn "addv4hi3"
14100   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14101         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14102                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14103   "TARGET_SHMEDIA"
14104   "madd.w       %1, %2, %0"
14105   [(set_attr "type" "arith_media")
14106    (set_attr "highpart" "depend")])
14108 (define_insn_and_split "addv2hi3"
14109   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14110         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
14111                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
14112   "TARGET_SHMEDIA"
14113   "#"
14114   "TARGET_SHMEDIA"
14115   [(const_int 0)]
14117   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14118   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14119   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14120   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14121   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14123   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
14124   emit_insn (gen_truncdisi2 (si_dst, di_dst));
14125   DONE;
14127   [(set_attr "highpart" "must_split")])
14129 (define_insn "ssaddv2si3"
14130   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14131         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
14132                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14133   "TARGET_SHMEDIA"
14134   "madds.l      %1, %2, %0"
14135   [(set_attr "type" "mcmp_media")
14136    (set_attr "highpart" "depend")])
14138 (define_insn "usaddv8qi3"
14139   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14140         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
14141                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14142   "TARGET_SHMEDIA"
14143   "madds.ub     %1, %2, %0"
14144   [(set_attr "type" "mcmp_media")
14145    (set_attr "highpart" "depend")])
14147 (define_insn "ssaddv4hi3"
14148   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14149         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
14150                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14151   "TARGET_SHMEDIA"
14152   "madds.w      %1, %2, %0"
14153   [(set_attr "type" "mcmp_media")
14154    (set_attr "highpart" "depend")])
14156 (define_insn "negcmpeqv8qi"
14157   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14158         (neg:V8QI (eq:V8QI
14159                     (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14160                     (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14161   "TARGET_SHMEDIA"
14162   "mcmpeq.b     %N1, %N2, %0"
14163   [(set_attr "type" "mcmp_media")
14164    (set_attr "highpart" "depend")])
14166 (define_insn "negcmpeqv2si"
14167   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14168         (neg:V2SI (eq:V2SI
14169                     (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14170                     (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14171   "TARGET_SHMEDIA"
14172   "mcmpeq.l     %N1, %N2, %0"
14173   [(set_attr "type" "mcmp_media")
14174    (set_attr "highpart" "depend")])
14176 (define_insn "negcmpeqv4hi"
14177   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14178         (neg:V4HI (eq:V4HI
14179                     (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14180                     (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14181   "TARGET_SHMEDIA"
14182   "mcmpeq.w     %N1, %N2, %0"
14183   [(set_attr "type" "mcmp_media")
14184    (set_attr "highpart" "depend")])
14186 (define_insn "negcmpgtuv8qi"
14187   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14188         (neg:V8QI (gtu:V8QI
14189                     (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
14190                     (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
14191   "TARGET_SHMEDIA"
14192   "mcmpgt.ub    %N1, %N2, %0"
14193   [(set_attr "type" "mcmp_media")
14194    (set_attr "highpart" "depend")])
14196 (define_insn "negcmpgtv2si"
14197   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14198         (neg:V2SI (gt:V2SI
14199                     (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
14200                     (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14201   "TARGET_SHMEDIA"
14202   "mcmpgt.l     %N1, %N2, %0"
14203   [(set_attr "type" "mcmp_media")
14204    (set_attr "highpart" "depend")])
14206 (define_insn "negcmpgtv4hi"
14207   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14208         (neg:V4HI (gt:V4HI
14209                     (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
14210                     (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14211   "TARGET_SHMEDIA"
14212   "mcmpgt.w     %N1, %N2, %0"
14213   [(set_attr "type" "mcmp_media")
14214    (set_attr "highpart" "depend")])
14216 (define_insn "mcmv"
14217   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14218         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14219                         (match_operand:DI 2 "arith_reg_operand" "r"))
14220                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
14221                         (not:DI (match_dup 2)))))]
14222   "TARGET_SHMEDIA"
14223   "mcmv %N1, %2, %0"
14224   [(set_attr "type" "arith_media")
14225    (set_attr "highpart" "depend")])
14227 (define_insn "mcnvs_lw"
14228   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14229         (vec_concat:V4HI
14230          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
14231          (ss_truncate:V2HI
14232            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
14233   "TARGET_SHMEDIA"
14234   "mcnvs.lw     %N1, %N2, %0"
14235   [(set_attr "type" "mcmp_media")])
14237 (define_insn "mcnvs_wb"
14238   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14239         (vec_concat:V8QI
14240          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14241          (ss_truncate:V4QI
14242            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14243   "TARGET_SHMEDIA"
14244   "mcnvs.wb     %N1, %N2, %0"
14245   [(set_attr "type" "mcmp_media")])
14247 (define_insn "mcnvs_wub"
14248   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14249         (vec_concat:V8QI
14250          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
14251          (us_truncate:V4QI
14252            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
14253   "TARGET_SHMEDIA"
14254   "mcnvs.wub    %N1, %N2, %0"
14255   [(set_attr "type" "mcmp_media")])
14257 (define_insn "mextr_rl"
14258   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14259         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14260                              (match_operand:HI 3 "mextr_bit_offset" "i"))
14261                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14262                            (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14263   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14265   static char templ[21];
14266   sprintf (templ, "mextr%d      %%N1, %%N2, %%0",
14267            (int) INTVAL (operands[3]) >> 3);
14268   return templ;
14270   [(set_attr "type" "arith_media")])
14272 (define_insn "*mextr_lr"
14273   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14274         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14275                            (match_operand:HI 3 "mextr_bit_offset" "i"))
14276                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14277                              (match_operand:HI 4 "mextr_bit_offset" "i"))))]
14278   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
14280   static char templ[21];
14281   sprintf (templ, "mextr%d      %%N2, %%N1, %%0",
14282            (int) INTVAL (operands[4]) >> 3);
14283   return templ;
14285   [(set_attr "type" "arith_media")])
14287 ; mextrN can be modelled with vec_select / vec_concat, but the selection
14288 ; vector then varies depending on endianness.
14289 (define_expand "mextr1"
14290   [(match_operand:DI 0 "arith_reg_dest" "")
14291    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14292    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14293   "TARGET_SHMEDIA"
14295   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14296                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
14297   DONE;
14300 (define_expand "mextr2"
14301   [(match_operand:DI 0 "arith_reg_dest" "")
14302    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14303    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14304   "TARGET_SHMEDIA"
14306   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14307                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
14308   DONE;
14311 (define_expand "mextr3"
14312   [(match_operand:DI 0 "arith_reg_dest" "")
14313    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14314    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14315   "TARGET_SHMEDIA"
14317   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14318                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
14319   DONE;
14322 (define_expand "mextr4"
14323   [(match_operand:DI 0 "arith_reg_dest" "")
14324    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14325    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14326   "TARGET_SHMEDIA"
14328   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14329                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
14330   DONE;
14333 (define_expand "mextr5"
14334   [(match_operand:DI 0 "arith_reg_dest" "")
14335    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14336    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14337   "TARGET_SHMEDIA"
14339   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14340                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
14341   DONE;
14344 (define_expand "mextr6"
14345   [(match_operand:DI 0 "arith_reg_dest" "")
14346    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14347    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14348   "TARGET_SHMEDIA"
14350   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14351                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
14352   DONE;
14355 (define_expand "mextr7"
14356   [(match_operand:DI 0 "arith_reg_dest" "")
14357    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14358    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14359   "TARGET_SHMEDIA"
14361   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14362                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
14363   DONE;
14366 (define_expand "mmacfx_wl"
14367   [(match_operand:V2SI 0 "arith_reg_dest" "")
14368    (match_operand:V2HI 1 "extend_reg_operand" "")
14369    (match_operand:V2HI 2 "extend_reg_operand" "")
14370    (match_operand:V2SI 3 "arith_reg_operand" "")]
14371   "TARGET_SHMEDIA"
14373   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14374                               operands[1], operands[2]));
14375   DONE;
14378 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14379 ;; is depend
14380 (define_insn "mmacfx_wl_i"
14381   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14382         (ss_plus:V2SI
14383          (match_operand:V2SI 1 "arith_reg_operand" "0")
14384          (ss_truncate:V2SI
14385           (ashift:V2DI
14386            (sign_extend:V2DI
14387             (mult:V2SI
14388              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14389              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14390            (const_int 1)))))]
14391   "TARGET_SHMEDIA"
14392   "mmacfx.wl    %2, %3, %0"
14393   [(set_attr "type" "mac_media")
14394    (set_attr "highpart" "depend")])
14396 (define_expand "mmacnfx_wl"
14397   [(match_operand:V2SI 0 "arith_reg_dest" "")
14398    (match_operand:V2HI 1 "extend_reg_operand" "")
14399    (match_operand:V2HI 2 "extend_reg_operand" "")
14400    (match_operand:V2SI 3 "arith_reg_operand" "")]
14401   "TARGET_SHMEDIA"
14403   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14404                                operands[1], operands[2]));
14405   DONE;
14408 (define_insn "mmacnfx_wl_i"
14409   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14410         (ss_minus:V2SI
14411          (match_operand:V2SI 1 "arith_reg_operand" "0")
14412          (ss_truncate:V2SI
14413           (ashift:V2DI
14414            (sign_extend:V2DI
14415             (mult:V2SI
14416              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14417              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14418            (const_int 1)))))]
14419   "TARGET_SHMEDIA"
14420   "mmacnfx.wl   %2, %3, %0"
14421   [(set_attr "type" "mac_media")
14422    (set_attr "highpart" "depend")])
14424 (define_insn "mulv2si3"
14425   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14426         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14427                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14428   "TARGET_SHMEDIA"
14429   "mmul.l       %1, %2, %0"
14430   [(set_attr "type" "d2mpy_media")
14431    (set_attr "highpart" "depend")])
14433 (define_insn "mulv4hi3"
14434   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14435         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14436                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14437   "TARGET_SHMEDIA"
14438   "mmul.w       %1, %2, %0"
14439   [(set_attr "type" "dmpy_media")
14440    (set_attr "highpart" "depend")])
14442 (define_insn "mmulfx_l"
14443   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14444         (ss_truncate:V2SI
14445          (ashiftrt:V2DI
14446           (mult:V2DI
14447            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14448            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14449           (const_int 31))))]
14450   "TARGET_SHMEDIA"
14451   "mmulfx.l     %1, %2, %0"
14452   [(set_attr "type" "d2mpy_media")
14453    (set_attr "highpart" "depend")])
14455 (define_insn "mmulfx_w"
14456   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14457         (ss_truncate:V4HI
14458          (ashiftrt:V4SI
14459           (mult:V4SI
14460            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14461            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14462           (const_int 15))))]
14463   "TARGET_SHMEDIA"
14464   "mmulfx.w     %1, %2, %0"
14465   [(set_attr "type" "dmpy_media")
14466    (set_attr "highpart" "depend")])
14468 (define_insn "mmulfxrp_w"
14469   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14470         (ss_truncate:V4HI
14471          (ashiftrt:V4SI
14472           (plus:V4SI
14473            (mult:V4SI
14474             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14475             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14476            (const_int 16384))
14477           (const_int 15))))]
14478   "TARGET_SHMEDIA"
14479   "mmulfxrp.w   %1, %2, %0"
14480   [(set_attr "type" "dmpy_media")
14481    (set_attr "highpart" "depend")])
14484 (define_expand "mmulhi_wl"
14485   [(match_operand:V2SI 0 "arith_reg_dest" "")
14486    (match_operand:V4HI 1 "arith_reg_operand" "")
14487    (match_operand:V4HI 2 "arith_reg_operand" "")]
14488   "TARGET_SHMEDIA"
14490   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14491              (operands[0], operands[1], operands[2]));
14492   DONE;
14495 (define_expand "mmullo_wl"
14496   [(match_operand:V2SI 0 "arith_reg_dest" "")
14497    (match_operand:V4HI 1 "arith_reg_operand" "")
14498    (match_operand:V4HI 2 "arith_reg_operand" "")]
14499   "TARGET_SHMEDIA"
14501   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14502              (operands[0], operands[1], operands[2]));
14503   DONE;
14506 (define_insn "mmul23_wl"
14507   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14508         (vec_select:V2SI
14509          (mult:V4SI
14510           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14511           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14512          (parallel [(const_int 2) (const_int 3)])))]
14513   "TARGET_SHMEDIA"
14515   return (TARGET_LITTLE_ENDIAN
14516           ? "mmulhi.wl  %1, %2, %0"
14517           : "mmullo.wl  %1, %2, %0");
14519   [(set_attr "type" "dmpy_media")
14520    (set (attr "highpart")
14521         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14522          (const_string "user")))])
14524 (define_insn "mmul01_wl"
14525   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14526         (vec_select:V2SI
14527          (mult:V4SI
14528           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14529           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14530          (parallel [(const_int 0) (const_int 1)])))]
14531   "TARGET_SHMEDIA"
14533   return (TARGET_LITTLE_ENDIAN
14534           ? "mmullo.wl  %1, %2, %0"
14535           : "mmulhi.wl  %1, %2, %0");
14537   [(set_attr "type" "dmpy_media")
14538    (set (attr "highpart")
14539         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14540          (const_string "user")))])
14543 (define_expand "mmulsum_wq"
14544   [(match_operand:DI 0 "arith_reg_dest" "")
14545    (match_operand:V4HI 1 "arith_reg_operand" "")
14546    (match_operand:V4HI 2 "arith_reg_operand" "")
14547    (match_operand:DI 3 "arith_reg_operand" "")]
14548   "TARGET_SHMEDIA"
14550   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14551                                operands[1], operands[2]));
14552   DONE;
14555 (define_insn "mmulsum_wq_i"
14556   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14557         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14558          (plus:DI
14559           (plus:DI
14560            (vec_select:DI
14561             (mult:V4DI
14562              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14563              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14564             (parallel [(const_int 0)]))
14565            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14566                                      (sign_extend:V4DI (match_dup 3)))
14567                           (parallel [(const_int 1)])))
14568           (plus:DI
14569            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14570                                      (sign_extend:V4DI (match_dup 3)))
14571                           (parallel [(const_int 2)]))
14572            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14573                                      (sign_extend:V4DI (match_dup 3)))
14574                           (parallel [(const_int 3)]))))))]
14575   "TARGET_SHMEDIA"
14576   "mmulsum.wq   %2, %3, %0"
14577   [(set_attr "type" "mac_media")])
14579 (define_expand "mperm_w"
14580   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14581    (match_operand:V4HI 1 "arith_reg_operand" "r")
14582    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14583   "TARGET_SHMEDIA"
14585   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14586              (operands[0], operands[1], operands[2]));
14587   DONE;
14590 ; This use of vec_select isn't exactly correct according to rtl.texi
14591 ; (because not constant), but it seems a straightforward extension.
14592 (define_insn "mperm_w_little"
14593   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14594         (vec_select:V4HI
14595          (match_operand:V4HI 1 "arith_reg_operand" "r")
14596          (parallel
14597           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14598                             (const_int 2) (const_int 0))
14599            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14600            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14601            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14602   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14603   "mperm.w      %1, %N2, %0"
14604   [(set_attr "type" "arith_media")])
14606 (define_insn "mperm_w_big"
14607   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14608         (vec_select:V4HI
14609          (match_operand:V4HI 1 "arith_reg_operand" "r")
14610          (parallel
14611           [(zero_extract:QI (not:QI (match_operand:QI 2
14612                                      "extend_reg_or_0_operand" "rZ"))
14613                             (const_int 2) (const_int 0))
14614            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14615            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14616            (zero_extract:QI (not:QI (match_dup 2))
14617                             (const_int 2) (const_int 6))])))]
14618   "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
14619   "mperm.w      %1, %N2, %0"
14620   [(set_attr "type" "arith_media")])
14622 (define_insn "mperm_w0"
14623   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14624         (vec_duplicate:V4HI (truncate:HI (match_operand 1
14625                                           "trunc_hi_operand" "r"))))]
14626   "TARGET_SHMEDIA"
14627   "mperm.w      %1, r63, %0"
14628   [(set_attr "type" "arith_media")
14629    (set_attr "highpart" "ignore")])
14631 (define_expand "msad_ubq"
14632   [(match_operand:DI 0 "arith_reg_dest" "")
14633    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14634    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14635    (match_operand:DI 3 "arith_reg_operand" "")]
14636   "TARGET_SHMEDIA"
14638   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14639                              operands[1], operands[2]));
14640   DONE;
14643 (define_insn "msad_ubq_i"
14644   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14645         (plus:DI
14646          (plus:DI
14647           (plus:DI
14648            (plus:DI
14649             (match_operand:DI 1 "arith_reg_operand" "0")
14650             (abs:DI (vec_select:DI
14651                      (minus:V8DI
14652                       (zero_extend:V8DI
14653                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14654                       (zero_extend:V8DI
14655                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14656                      (parallel [(const_int 0)]))))
14657            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14658                                               (zero_extend:V8DI (match_dup 3)))
14659                                   (parallel [(const_int 1)]))))
14660           (plus:DI
14661            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14662                                               (zero_extend:V8DI (match_dup 3)))
14663                                   (parallel [(const_int 2)])))
14664            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14665                                               (zero_extend:V8DI (match_dup 3)))
14666                                   (parallel [(const_int 3)])))))
14667          (plus:DI
14668           (plus:DI
14669            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14670                                               (zero_extend:V8DI (match_dup 3)))
14671                                   (parallel [(const_int 4)])))
14672            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14673                                               (zero_extend:V8DI (match_dup 3)))
14674                                   (parallel [(const_int 5)]))))
14675           (plus:DI
14676            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14677                                               (zero_extend:V8DI (match_dup 3)))
14678                                   (parallel [(const_int 6)])))
14679            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14680                                               (zero_extend:V8DI (match_dup 3)))
14681                                   (parallel [(const_int 7)])))))))]
14682   "TARGET_SHMEDIA"
14683   "msad.ubq     %N2, %N3, %0"
14684   [(set_attr "type" "mac_media")])
14686 (define_insn "mshalds_l"
14687   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14688         (ss_truncate:V2SI
14689          (ashift:V2DI
14690           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14691           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14692                   (const_int 31)))))]
14693   "TARGET_SHMEDIA"
14694   "mshalds.l    %1, %2, %0"
14695   [(set_attr "type" "mcmp_media")
14696    (set_attr "highpart" "depend")])
14698 (define_insn "mshalds_w"
14699   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14700         (ss_truncate:V4HI
14701          (ashift:V4SI
14702           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14703           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14704                   (const_int 15)))))]
14705   "TARGET_SHMEDIA"
14706   "mshalds.w    %1, %2, %0"
14707   [(set_attr "type" "mcmp_media")
14708    (set_attr "highpart" "depend")])
14710 (define_insn "ashrv2si3"
14711   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14712         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14713                        (match_operand:DI 2 "arith_reg_operand" "r")))]
14714   "TARGET_SHMEDIA"
14715   "mshard.l     %1, %2, %0"
14716   [(set_attr "type" "arith_media")
14717    (set_attr "highpart" "depend")])
14719 (define_insn "ashrv4hi3"
14720   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14721         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14722                        (match_operand:DI 2 "arith_reg_operand" "r")))]
14723   "TARGET_SHMEDIA"
14724   "mshard.w     %1, %2, %0"
14725   [(set_attr "type" "arith_media")
14726    (set_attr "highpart" "depend")])
14728 (define_insn "mshards_q"
14729   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14730         (ss_truncate:HI
14731          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14732                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14733   "TARGET_SHMEDIA"
14734   "mshards.q    %1, %N2, %0"
14735   [(set_attr "type" "mcmp_media")])
14737 (define_expand "mshfhi_b"
14738   [(match_operand:V8QI 0 "arith_reg_dest" "")
14739    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14740    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14741   "TARGET_SHMEDIA"
14743   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14744              (operands[0], operands[1], operands[2]));
14745   DONE;
14748 (define_expand "mshflo_b"
14749   [(match_operand:V8QI 0 "arith_reg_dest" "")
14750    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14751    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14752   "TARGET_SHMEDIA"
14754   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14755              (operands[0], operands[1], operands[2]));
14756   DONE;
14759 (define_insn "mshf4_b"
14760   [(set
14761     (match_operand:V8QI 0 "arith_reg_dest" "=r")
14762     (vec_select:V8QI
14763      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14764                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14765      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14766                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14767   "TARGET_SHMEDIA"
14769   return (TARGET_LITTLE_ENDIAN
14770           ? "mshfhi.b   %N1, %N2, %0"
14771           : "mshflo.b   %N1, %N2, %0");
14773   [(set_attr "type" "arith_media")
14774    (set (attr "highpart")
14775         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14776          (const_string "user")))])
14778 (define_insn "mshf0_b"
14779   [(set
14780     (match_operand:V8QI 0 "arith_reg_dest" "=r")
14781     (vec_select:V8QI
14782      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14783                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14784      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14785                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14786   "TARGET_SHMEDIA"
14788   return (TARGET_LITTLE_ENDIAN
14789           ? "mshflo.b   %N1, %N2, %0"
14790           : "mshfhi.b   %N1, %N2, %0");
14792   [(set_attr "type" "arith_media")
14793    (set (attr "highpart")
14794         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14795          (const_string "user")))])
14797 (define_expand "mshfhi_l"
14798   [(match_operand:V2SI 0 "arith_reg_dest" "")
14799    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14800    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14801   "TARGET_SHMEDIA"
14803   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14804              (operands[0], operands[1], operands[2]));
14805   DONE;
14808 (define_expand "mshflo_l"
14809   [(match_operand:V2SI 0 "arith_reg_dest" "")
14810    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14811    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14812   "TARGET_SHMEDIA"
14814   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14815              (operands[0], operands[1], operands[2]));
14816   DONE;
14819 (define_insn "mshf4_l"
14820   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14821         (vec_select:V2SI
14822          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14823                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14824          (parallel [(const_int 1) (const_int 3)])))]
14825   "TARGET_SHMEDIA"
14827   return (TARGET_LITTLE_ENDIAN
14828           ? "mshfhi.l   %N1, %N2, %0"
14829           : "mshflo.l   %N1, %N2, %0");
14831   [(set_attr "type" "arith_media")
14832    (set (attr "highpart")
14833         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14834          (const_string "user")))])
14836 (define_insn "mshf0_l"
14837   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14838         (vec_select:V2SI
14839          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14840                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14841          (parallel [(const_int 0) (const_int 2)])))]
14842   "TARGET_SHMEDIA"
14844   return (TARGET_LITTLE_ENDIAN
14845           ? "mshflo.l   %N1, %N2, %0"
14846           : "mshfhi.l   %N1, %N2, %0");
14848   [(set_attr "type" "arith_media")
14849    (set (attr "highpart")
14850         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14851          (const_string "user")))])
14853 (define_expand "mshfhi_w"
14854   [(match_operand:V4HI 0 "arith_reg_dest" "")
14855    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14856    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14857   "TARGET_SHMEDIA"
14859   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14860              (operands[0], operands[1], operands[2]));
14861   DONE;
14864 (define_expand "mshflo_w"
14865   [(match_operand:V4HI 0 "arith_reg_dest" "")
14866    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14867    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14868   "TARGET_SHMEDIA"
14870   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14871              (operands[0], operands[1], operands[2]));
14872   DONE;
14875 (define_insn "mshf4_w"
14876   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14877         (vec_select:V4HI
14878          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14879                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14880          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14881   "TARGET_SHMEDIA"
14883   return (TARGET_LITTLE_ENDIAN
14884           ? "mshfhi.w   %N1, %N2, %0"
14885           : "mshflo.w   %N1, %N2, %0");
14887   [(set_attr "type" "arith_media")
14888    (set (attr "highpart")
14889         (cond [(eq_attr "endian" "big") (const_string "ignore")]
14890          (const_string "user")))])
14892 (define_insn "mshf0_w"
14893   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14894         (vec_select:V4HI
14895          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14896                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14897          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14898   "TARGET_SHMEDIA"
14900   return (TARGET_LITTLE_ENDIAN
14901           ? "mshflo.w   %N1, %N2, %0"
14902           : "mshfhi.w   %N1, %N2, %0");
14904   [(set_attr "type" "arith_media")
14905    (set (attr "highpart")
14906         (cond [(eq_attr "endian" "little") (const_string "ignore")]
14907          (const_string "user")))])
14909 (define_insn "mshflo_w_x"
14910   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14911         (vec_select:V4HI
14912          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14913                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14914          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14915   "TARGET_SHMEDIA"
14916   "mshflo.w     %N1, %N2, %0"
14917   [(set_attr "type" "arith_media")
14918    (set_attr "highpart" "ignore")])
14920 ;; These are useful to expand ANDs and as combiner patterns.
14921 (define_insn_and_split "mshfhi_l_di"
14922   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14923         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14924                              (const_int 32))
14925                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14926                         (const_int -4294967296))))]
14927   "TARGET_SHMEDIA"
14928   "@
14929         mshfhi.l        %N1, %N2, %0
14930         #"
14931   "TARGET_SHMEDIA && reload_completed
14932    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14933   [(set (match_dup 3) (match_dup 4))
14934    (set (match_dup 5) (match_dup 6))]
14936   operands[3] = gen_lowpart (SImode, operands[0]);
14937   operands[4] = gen_highpart (SImode, operands[1]);
14938   operands[5] = gen_highpart (SImode, operands[0]);
14939   operands[6] = gen_highpart (SImode, operands[2]);
14941   [(set_attr "type" "arith_media")])
14943 (define_insn "*mshfhi_l_di_rev"
14944   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14945         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14946                         (const_int -4294967296))
14947                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14948                              (const_int 32))))]
14949   "TARGET_SHMEDIA"
14950   "mshfhi.l     %N2, %N1, %0"
14951   [(set_attr "type" "arith_media")])
14953 (define_split
14954   [(set (match_operand:DI 0 "arith_reg_dest" "")
14955         (ior:DI (zero_extend:DI (match_operand:SI 1
14956                                               "extend_reg_or_0_operand" ""))
14957                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
14958                         (const_int -4294967296))))
14959    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
14960   "TARGET_SHMEDIA"
14961   [(const_int 0)]
14963   emit_insn (gen_ashldi3_media (operands[3],
14964                                 simplify_gen_subreg (DImode, operands[1],
14965                                                      SImode, 0),
14966                                 GEN_INT (32)));
14967   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
14968   DONE;
14971 (define_insn "mshflo_l_di"
14972   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14973         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14974                         (const_int 4294967295))
14975                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14976                            (const_int 32))))]
14978   "TARGET_SHMEDIA"
14979   "mshflo.l     %N1, %N2, %0"
14980   [(set_attr "type" "arith_media")
14981    (set_attr "highpart" "ignore")])
14983 (define_insn "*mshflo_l_di_rev"
14984   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14985         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14986                            (const_int 32))
14987                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14988                         (const_int 4294967295))))]
14990   "TARGET_SHMEDIA"
14991   "mshflo.l     %N2, %N1, %0"
14992   [(set_attr "type" "arith_media")
14993    (set_attr "highpart" "ignore")])
14995 ;; Combiner pattern for trampoline initialization.
14996 (define_insn_and_split "*double_shori"
14997   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14998         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
14999                            (const_int 32))
15000                 (match_operand:DI 2 "const_int_operand" "n")))]
15001   "TARGET_SHMEDIA
15002    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
15003   "#"
15004   "rtx_equal_p (operands[0], operands[1])"
15005   [(const_int 0)]
15007   HOST_WIDE_INT v = INTVAL (operands[2]);
15009   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
15010   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
15011   DONE;
15013   [(set_attr "highpart" "ignore")])
15015 (define_insn "*mshflo_l_di_x"
15016   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15017         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
15018                                  "rZ"))
15019                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15020                            (const_int 32))))]
15021   "TARGET_SHMEDIA"
15022   "mshflo.l     %N1, %N2, %0"
15023   [(set_attr "type" "arith_media")
15024    (set_attr "highpart" "ignore")])
15026 (define_insn_and_split "concat_v2sf"
15027   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
15028 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
15029         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
15030                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
15031   "TARGET_SHMEDIA"
15032   "@
15033         mshflo.l        %N1, %N2, %0
15034         #
15035         #"
15036   "TARGET_SHMEDIA && reload_completed
15037    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
15038   [(set (match_dup 3) (match_dup 1))
15039    (set (match_dup 4) (match_dup 2))]
15041   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
15042   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
15044   [(set_attr "type" "arith_media")
15045    (set_attr "highpart" "ignore")])
15047 (define_insn "*mshflo_l_di_x_rev"
15048   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15049         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15050                            (const_int 32))
15051                 (zero_extend:DI
15052                   (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
15053   "TARGET_SHMEDIA"
15054   "mshflo.l     %N2, %N1, %0"
15055   [(set_attr "type" "arith_media")
15056    (set_attr "highpart" "ignore")])
15058 (define_insn "ashlv2si3"
15059   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15060         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15061                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15062   "TARGET_SHMEDIA"
15063   "mshlld.l     %1, %2, %0"
15064   [(set_attr "type" "arith_media")
15065    (set_attr "highpart" "depend")])
15067 (define_split
15068   [(set (match_operand 0 "any_register_operand" "")
15069         (match_operator 3 "shift_operator"
15070           [(match_operand 1 "any_register_operand" "")
15071            (match_operand 2 "shift_count_reg_operand" "")]))]
15072   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
15073   [(set (match_dup 0) (match_dup 3))]
15075   rtx count = operands[2];
15076   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
15078   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
15079          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
15080          || GET_CODE (count) == TRUNCATE)
15081     count = XEXP (count, 0);
15082   inner_mode = GET_MODE (count);
15083   count = simplify_gen_subreg (outer_mode, count, inner_mode,
15084                                subreg_lowpart_offset (outer_mode, inner_mode));
15085   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
15086                                 operands[1], count);
15089 (define_insn "ashlv4hi3"
15090   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15091         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15092                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15093   "TARGET_SHMEDIA"
15094   "mshlld.w     %1, %2, %0"
15095   [(set_attr "type" "arith_media")
15096    (set_attr "highpart" "depend")])
15098 (define_insn "lshrv2si3"
15099   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15100         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15101                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15102   "TARGET_SHMEDIA"
15103   "mshlrd.l     %1, %2, %0"
15104   [(set_attr "type" "arith_media")
15105    (set_attr "highpart" "depend")])
15107 (define_insn "lshrv4hi3"
15108   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15109         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15110                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
15111   "TARGET_SHMEDIA"
15112   "mshlrd.w     %1, %2, %0"
15113   [(set_attr "type" "arith_media")
15114    (set_attr "highpart" "depend")])
15116 (define_insn "subv2si3"
15117   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15118         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15119                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15120   "TARGET_SHMEDIA"
15121   "msub.l       %N1, %2, %0"
15122   [(set_attr "type" "arith_media")
15123    (set_attr "highpart" "depend")])
15125 (define_insn "subv4hi3"
15126   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15127         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15128                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15129   "TARGET_SHMEDIA"
15130   "msub.w       %N1, %2, %0"
15131   [(set_attr "type" "arith_media")
15132    (set_attr "highpart" "depend")])
15134 (define_insn_and_split "subv2hi3"
15135   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15136         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
15137                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
15138   "TARGET_SHMEDIA"
15139   "#"
15140   "TARGET_SHMEDIA"
15141   [(const_int 0)]
15143   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15144   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15145   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15146   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15147   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15149   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
15150   emit_insn (gen_truncdisi2 (si_dst, di_dst));
15151   DONE;
15153   [(set_attr "highpart" "must_split")])
15155 (define_insn "sssubv2si3"
15156   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15157         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15158                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15159   "TARGET_SHMEDIA"
15160   "msubs.l      %N1, %2, %0"
15161   [(set_attr "type" "mcmp_media")
15162    (set_attr "highpart" "depend")])
15164 (define_insn "ussubv8qi3"
15165   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15166         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15167                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15168   "TARGET_SHMEDIA"
15169   "msubs.ub     %N1, %2, %0"
15170   [(set_attr "type" "mcmp_media")
15171    (set_attr "highpart" "depend")])
15173 (define_insn "sssubv4hi3"
15174   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15175         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15176                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15177   "TARGET_SHMEDIA"
15178   "msubs.w      %N1, %2, %0"
15179   [(set_attr "type" "mcmp_media")
15180    (set_attr "highpart" "depend")])
15182 ;; -------------------------------------------------------------------------
15183 ;; Floating Point Intrinsics
15184 ;; -------------------------------------------------------------------------
15186 (define_insn "fcosa_s"
15187   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15188         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15189                    UNSPEC_FCOSA))]
15190   "TARGET_SHMEDIA"
15191   "fcosa.s      %1, %0"
15192   [(set_attr "type" "atrans_media")])
15194 (define_insn "fsina_s"
15195   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15196         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
15197                    UNSPEC_FSINA))]
15198   "TARGET_SHMEDIA"
15199   "fsina.s      %1, %0"
15200   [(set_attr "type" "atrans_media")])
15202 (define_insn "fipr"
15203   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15204         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
15205                                                     "fp_arith_reg_operand" "f")
15206                                                    (match_operand:V4SF 2
15207                                                     "fp_arith_reg_operand" "f"))
15208                                          (parallel [(const_int 0)]))
15209                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15210                                          (parallel [(const_int 1)])))
15211                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15212                                          (parallel [(const_int 2)]))
15213                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
15214                                          (parallel [(const_int 3)])))))]
15215   "TARGET_SHMEDIA"
15216   "fipr.s       %1, %2, %0"
15217   [(set_attr "type" "fparith_media")])
15219 (define_insn "fsrra_s"
15220   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
15221         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
15222                    UNSPEC_FSRRA))]
15223   "TARGET_SHMEDIA"
15224   "fsrra.s      %1, %0"
15225   [(set_attr "type" "atrans_media")])
15227 (define_insn "ftrv"
15228   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
15229         (plus:V4SF
15230          (plus:V4SF
15231           (mult:V4SF
15232            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
15233                             (parallel [(const_int 0) (const_int 5)
15234                                        (const_int 10) (const_int 15)]))
15235            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
15236           (mult:V4SF
15237            (vec_select:V4SF (match_dup 1)
15238                             (parallel [(const_int 4) (const_int 9)
15239                                        (const_int 14) (const_int 3)]))
15240            (vec_select:V4SF (match_dup 2)
15241                             (parallel [(const_int 1) (const_int 2)
15242                                        (const_int 3) (const_int 0)]))))
15243          (plus:V4SF
15244           (mult:V4SF
15245            (vec_select:V4SF (match_dup 1)
15246                             (parallel [(const_int 8) (const_int 13)
15247                                        (const_int 2) (const_int 7)]))
15248            (vec_select:V4SF (match_dup 2)
15249                             (parallel [(const_int 2) (const_int 3)
15250                                        (const_int 0) (const_int 1)])))
15251           (mult:V4SF
15252            (vec_select:V4SF (match_dup 1)
15253                             (parallel [(const_int 12) (const_int 1)
15254                                        (const_int 6) (const_int 11)]))
15255            (vec_select:V4SF (match_dup 2)
15256                             (parallel [(const_int 3) (const_int 0)
15257                                        (const_int 1) (const_int 2)]))))))]
15258   "TARGET_SHMEDIA"
15259   "ftrv.s %1, %2, %0"
15260   [(set_attr "type" "fparith_media")])
15262 (define_insn "ldhi_l"
15263   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15264         (zero_extract:SI
15265          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15266                                   (const_int 3))
15267                           (const_int -3)))
15268          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
15269          (const_int 0)))]
15270   "TARGET_SHMEDIA32"
15271   "ldhi.l       %U1, %0"
15272   [(set_attr "type" "load_media")])
15274 (define_insn "ldhi_q"
15275   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15276         (zero_extract:DI
15277          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
15278                                   (const_int 7))
15279                           (const_int -7)))
15280          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
15281          (const_int 0)))]
15282   "TARGET_SHMEDIA32"
15283   "ldhi.q       %U1, %0"
15284   [(set_attr "type" "load_media")])
15286 (define_insn_and_split "*ldhi_q_comb0"
15287   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15288         (zero_extract:DI
15289          (mem:DI (plus:SI (ior:SI (plus:SI
15290                                     (match_operand:SI 1 "register_operand" "r")
15291                                     (match_operand:SI 2 "ua_offset" "I06"))
15292                                   (const_int 7))
15293                           (const_int -7)))
15294          (plus:SI (and:SI (match_dup 1) (const_int 7))
15295                   (const_int 1))
15296          (const_int 0)))]
15297   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15298   "#"
15299   ""
15300   [(pc)]
15302   emit_insn (gen_ldhi_q (operands[0],
15303                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15304   DONE;
15307 (define_insn_and_split "*ldhi_q_comb1"
15308   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15309         (zero_extract:DI
15310          (mem:DI (plus:SI (ior:SI (plus:SI
15311                                     (match_operand:SI 1 "register_operand" "r")
15312                                     (match_operand:SI 2 "ua_offset" "I06"))
15313                                   (const_int 7))
15314                           (const_int -7)))
15315          (plus:SI (and:SI (plus:SI (match_dup 1)
15316                                    (match_operand:SI 3 "ua_offset" "I06"))
15317                           (const_int 7))
15318                   (const_int 1))
15319          (const_int 0)))]
15320   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15321    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15322   "#"
15323   ""
15324   [(pc)]
15326   emit_insn (gen_ldhi_q (operands[0],
15327                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15328   DONE;
15331 (define_insn "ldlo_l"
15332   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15333         (zero_extract:SI
15334          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15335                          (const_int -4)))
15336          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15337          (and:SI (match_dup 1) (const_int 3))))]
15338   "TARGET_SHMEDIA32"
15339   "ldlo.l       %U1, %0"
15340   [(set_attr "type" "load_media")])
15342 (define_insn "ldlo_q"
15343   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15344         (zero_extract:DI
15345          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15346                          (const_int -8)))
15347          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15348          (and:SI (match_dup 1) (const_int 7))))]
15349   "TARGET_SHMEDIA32"
15350   "ldlo.q       %U1, %0"
15351   [(set_attr "type" "load_media")])
15353 (define_insn_and_split "*ldlo_q_comb0"
15354   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15355         (zero_extract:DI
15356          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15357                                   (match_operand:SI 2 "ua_offset" "I06"))
15358                          (const_int -8)))
15359          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15360          (and:SI (match_dup 1) (const_int 7))))]
15361   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15362   "#"
15363   ""
15364   [(pc)]
15366   emit_insn (gen_ldlo_q (operands[0],
15367                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15368   DONE;
15371 (define_insn_and_split "*ldlo_q_comb1"
15372   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15373         (zero_extract:DI
15374          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15375                                   (match_operand:SI 2 "ua_offset" "I06"))
15376                          (const_int -8)))
15377          (minus:SI (const_int 8)
15378                    (and:SI (plus:SI (match_dup 1)
15379                                     (match_operand:SI 3 "ua_offset" "I06"))
15380                            (const_int 7)))
15381          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15382   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15383    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15384   "#"
15385   ""
15386   [(pc)]
15388   emit_insn (gen_ldlo_q (operands[0],
15389                          gen_rtx_PLUS (SImode, operands[1], operands[2])));
15390   DONE;
15393 (define_insn "sthi_l"
15394   [(set (zero_extract:SI
15395          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15396                                   (const_int 3))
15397                           (const_int -3)))
15398          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15399          (const_int 0))
15400         (match_operand:SI 1 "arith_reg_operand" "r"))]
15401   "TARGET_SHMEDIA32"
15402   "sthi.l       %U0, %1"
15403   [(set_attr "type" "ustore_media")])
15405 ;; All unaligned stores are considered to be 'narrow' because they typically
15406 ;; operate on less that a quadword, and when they operate on a full quadword,
15407 ;; the vanilla store high / store low sequence will cause a stall if not
15408 ;; scheduled apart.
15409 (define_insn "sthi_q"
15410   [(set (zero_extract:DI
15411          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15412                                   (const_int 7))
15413                           (const_int -7)))
15414          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15415          (const_int 0))
15416         (match_operand:DI 1 "arith_reg_operand" "r"))]
15417   "TARGET_SHMEDIA32"
15418   "sthi.q       %U0, %1"
15419   [(set_attr "type" "ustore_media")])
15421 (define_insn_and_split "*sthi_q_comb0"
15422   [(set (zero_extract:DI
15423          (mem:DI (plus:SI (ior:SI (plus:SI
15424                                     (match_operand:SI 0 "register_operand" "r")
15425                                     (match_operand:SI 1 "ua_offset" "I06"))
15426                                   (const_int 7))
15427                           (const_int -7)))
15428          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15429          (const_int 0))
15430         (match_operand:DI 2 "arith_reg_operand" "r"))]
15431   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15432   "#"
15433   ""
15434   [(pc)]
15436   emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15437                          operands[2]));
15438   DONE;
15441 (define_insn_and_split "*sthi_q_comb1"
15442   [(set (zero_extract:DI
15443          (mem:DI (plus:SI (ior:SI (plus:SI
15444                                     (match_operand:SI 0 "register_operand" "r")
15445                                     (match_operand:SI 1 "ua_offset" "I06"))
15446                                   (const_int 7))
15447                           (const_int -7)))
15448          (plus:SI (and:SI (plus:SI (match_dup 0)
15449                                    (match_operand:SI 2 "ua_offset" "I06"))
15450                           (const_int 7))
15451                   (const_int 1))
15452          (const_int 0))
15453         (match_operand:DI 3 "arith_reg_operand" "r"))]
15454   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15455    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15456   "#"
15457   ""
15458   [(pc)]
15460   emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15461                          operands[3]));
15462   DONE;
15465 ;; This is highpart user because the address is used as full 64 bit.
15466 (define_insn "stlo_l"
15467   [(set (zero_extract:SI
15468          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15469                          (const_int -4)))
15470          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15471          (and:SI (match_dup 0) (const_int 3)))
15472         (match_operand:SI 1 "arith_reg_operand" "r"))]
15473   "TARGET_SHMEDIA32"
15474   "stlo.l       %U0, %1"
15475   [(set_attr "type" "ustore_media")])
15477 (define_insn "stlo_q"
15478   [(set (zero_extract:DI
15479          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15480                          (const_int -8)))
15481          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15482          (and:SI (match_dup 0) (const_int 7)))
15483         (match_operand:DI 1 "arith_reg_operand" "r"))]
15484   "TARGET_SHMEDIA32"
15485   "stlo.q       %U0, %1"
15486   [(set_attr "type" "ustore_media")])
15488 (define_insn_and_split "*stlo_q_comb0"
15489   [(set (zero_extract:DI
15490          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15491                                   (match_operand:SI 1 "ua_offset" "I06"))
15492                          (const_int -8)))
15493          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15494          (and:SI (match_dup 0) (const_int 7)))
15495         (match_operand:DI 2 "arith_reg_operand" "r"))]
15496   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15497   "#"
15498   ""
15499   [(pc)]
15501   emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15502                          operands[2]));
15503   DONE;
15506 (define_insn_and_split "*stlo_q_comb1"
15507   [(set (zero_extract:DI
15508          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15509                                   (match_operand:SI 1 "ua_offset" "I06"))
15510                          (const_int -8)))
15511          (minus:SI (const_int 8)
15512                    (and:SI (plus:SI (match_dup 0)
15513                                     (match_operand:SI 2 "ua_offset" "I06"))
15514                            (const_int 7)))
15515          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15516         (match_operand:DI 3 "arith_reg_operand" "r"))]
15517   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15518   "#"
15519   ""
15520   [(pc)]
15522   emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15523                          operands[3]));
15524    DONE;
15527 (define_insn "ldhi_l64"
15528   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15529         (zero_extract:SI
15530          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15531                                   (const_int 3))
15532                           (const_int -3)))
15533          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15534          (const_int 0)))]
15535   "TARGET_SHMEDIA64"
15536   "ldhi.l       %U1, %0"
15537   [(set_attr "type" "load_media")])
15539 (define_insn "ldhi_q64"
15540   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15541         (zero_extract:DI
15542          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15543                                   (const_int 7))
15544                           (const_int -7)))
15545          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15546          (const_int 0)))]
15547   "TARGET_SHMEDIA64"
15548   "ldhi.q       %U1, %0"
15549   [(set_attr "type" "load_media")])
15551 (define_insn "ldlo_l64"
15552   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15553         (zero_extract:SI
15554          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15555                          (const_int -4)))
15556          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15557          (and:DI (match_dup 1) (const_int 3))))]
15558   "TARGET_SHMEDIA64"
15559   "ldlo.l       %U1, %0"
15560   [(set_attr "type" "load_media")])
15562 (define_insn "ldlo_q64"
15563   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15564         (zero_extract:DI
15565          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15566                          (const_int -8)))
15567          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15568          (and:DI (match_dup 1) (const_int 7))))]
15569   "TARGET_SHMEDIA64"
15570   "ldlo.q       %U1, %0"
15571   [(set_attr "type" "load_media")])
15573 (define_insn "sthi_l64"
15574   [(set (zero_extract:SI
15575          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15576                                   (const_int 3))
15577                           (const_int -3)))
15578          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15579          (const_int 0))
15580         (match_operand:SI 1 "arith_reg_operand" "r"))]
15581   "TARGET_SHMEDIA64"
15582   "sthi.l       %U0, %1"
15583   [(set_attr "type" "ustore_media")])
15585 (define_insn "sthi_q64"
15586   [(set (zero_extract:DI
15587          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15588                                   (const_int 7))
15589                           (const_int -7)))
15590          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15591          (const_int 0))
15592         (match_operand:DI 1 "arith_reg_operand" "r"))]
15593   "TARGET_SHMEDIA64"
15594   "sthi.q       %U0, %1"
15595   [(set_attr "type" "ustore_media")])
15597 (define_insn "stlo_l64"
15598   [(set (zero_extract:SI
15599          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15600                          (const_int -4)))
15601          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15602          (and:DI (match_dup 0) (const_int 3)))
15603         (match_operand:SI 1 "arith_reg_operand" "r"))]
15604   "TARGET_SHMEDIA64"
15605   "stlo.l       %U0, %1"
15606   [(set_attr "type" "ustore_media")])
15608 (define_insn "stlo_q64"
15609   [(set (zero_extract:DI
15610          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15611                          (const_int -8)))
15612          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15613          (and:DI (match_dup 0) (const_int 7)))
15614         (match_operand:DI 1 "arith_reg_operand" "r"))]
15615   "TARGET_SHMEDIA64"
15616   "stlo.q       %U0, %1"
15617   [(set_attr "type" "ustore_media")])
15619 (define_insn "nsb"
15620   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15621         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15622                    UNSPEC_NSB))]
15623   "TARGET_SHMEDIA"
15624   "nsb  %1, %0"
15625   [(set_attr "type" "arith_media")])
15627 (define_insn "nsbsi"
15628   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15629         (zero_extend:SI
15630          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15631                     UNSPEC_NSB)))]
15632   "TARGET_SHMEDIA"
15633   "nsb  %1, %0"
15634   [(set_attr "type" "arith_media")])
15636 (define_insn "nsbdi"
15637   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15638         (zero_extend:DI
15639          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15640                     UNSPEC_NSB)))]
15641   "TARGET_SHMEDIA"
15642   "nsb  %1, %0"
15643   [(set_attr "type" "arith_media")])
15645 (define_expand "ffsdi2"
15646   [(set (match_operand:DI 0 "arith_reg_dest" "")
15647         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15648   "TARGET_SHMEDIA"
15650   rtx scratch = gen_reg_rtx (DImode);
15651   rtx last;
15653   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15654   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15655   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15656   emit_insn (gen_nsbdi (scratch, scratch));
15657   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15658   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15659   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15660   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15662   DONE;
15665 (define_expand "ffssi2"
15666   [(set (match_operand:SI 0 "arith_reg_dest" "")
15667         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15668   "TARGET_SHMEDIA"
15670   rtx scratch = gen_reg_rtx (SImode);
15671   rtx discratch = gen_reg_rtx (DImode);
15672   rtx last;
15674   emit_insn (gen_adddi3 (discratch,
15675                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
15676                          constm1_rtx));
15677   emit_insn (gen_andcdi3 (discratch,
15678                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
15679                           discratch));
15680   emit_insn (gen_nsbsi (scratch, discratch));
15681   last = emit_insn (gen_subsi3 (operands[0],
15682                                 force_reg (SImode, GEN_INT (63)), scratch));
15683   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15685   DONE;
15688 (define_insn "byterev"
15689   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15690         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15691                          (parallel [(const_int 7) (const_int 6) (const_int 5)
15692                                     (const_int 4) (const_int 3) (const_int 2)
15693                                     (const_int 1) (const_int 0)])))]
15694   "TARGET_SHMEDIA"
15695   "byterev      %1, %0"
15696   [(set_attr "type" "arith_media")])
15698 ;; In user mode, the "pref" instruction will raise a RADDERR exception
15699 ;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
15700 ;; implementation of __builtin_prefetch for VxWorks RTPs.
15701 (define_expand "prefetch"
15702   [(prefetch (match_operand 0 "address_operand" "")
15703              (match_operand:SI 1 "const_int_operand" "")
15704              (match_operand:SI 2 "const_int_operand" ""))]
15705   "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15706    && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15708 (define_insn "*prefetch"
15709   [(prefetch (match_operand:SI 0 "register_operand" "r")
15710              (match_operand:SI 1 "const_int_operand" "n")
15711              (match_operand:SI 2 "const_int_operand" "n"))]
15712   "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15713   "pref @%0"
15714   [(set_attr "type" "other")])
15716 (define_insn "*prefetch_media"
15717   [(prefetch (match_operand:QI 0 "address_operand" "p")
15718              (match_operand:SI 1 "const_int_operand" "n")
15719              (match_operand:SI 2 "const_int_operand" "n"))]
15720   "TARGET_SHMEDIA"
15722   operands[0] = gen_rtx_MEM (QImode, operands[0]);
15723   output_asm_insn ("ld%M0.b     %m0,r63", operands);
15724   return "";
15726   [(set_attr "type" "other")])
15728 (define_insn "alloco_i"
15729   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15730         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15731   "TARGET_SHMEDIA32"
15733   rtx xops[2];
15735   if (GET_CODE (operands[0]) == PLUS)
15736     {
15737       xops[0] = XEXP (operands[0], 0);
15738       xops[1] = XEXP (operands[0], 1);
15739     }
15740   else
15741     {
15742       xops[0] = operands[0];
15743       xops[1] = const0_rtx;
15744     }
15745   output_asm_insn ("alloco      %0, %1", xops);
15746   return "";
15748   [(set_attr "type" "other")])
15750 (define_split
15751   [(set (match_operand 0 "any_register_operand" "")
15752         (match_operand 1 "" ""))]
15753   "TARGET_SHMEDIA && reload_completed"
15754   [(set (match_dup 0) (match_dup 1))]
15756   int n_changes = 0;
15758   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15759   if (!n_changes)
15760     FAIL;
15763 ;; -------------------------------------------------------------------------
15764 ;; Stack Protector Patterns
15765 ;; -------------------------------------------------------------------------
15767 (define_expand "stack_protect_set"
15768   [(set (match_operand 0 "memory_operand" "")
15769         (match_operand 1 "memory_operand" ""))]
15770   ""
15772   if (TARGET_SHMEDIA)
15773     {
15774       if (TARGET_SHMEDIA64)
15775         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15776       else
15777         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15778     }
15779   else
15780     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15782   DONE;
15785 (define_insn "stack_protect_set_si"
15786   [(set (match_operand:SI 0 "memory_operand" "=m")
15787         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15788    (set (match_scratch:SI 2 "=&r") (const_int 0))]
15789   "!TARGET_SHMEDIA"
15791   return       "mov.l   %1,%2"  "\n"
15792          "      mov.l   %2,%0"  "\n"
15793          "      mov     #0,%2";
15795   [(set_attr "type" "other")
15796    (set_attr "length" "6")])
15798 (define_insn "stack_protect_set_si_media"
15799   [(set (match_operand:SI 0 "memory_operand" "=m")
15800         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15801    (set (match_scratch:SI 2 "=&r") (const_int 0))]
15802   "TARGET_SHMEDIA"
15804   return       "ld%M1.l %m1,%2" "\n"
15805          "      st%M0.l %m0,%2" "\n"
15806          "      movi    0,%2";
15808   [(set_attr "type" "other")
15809    (set_attr "length" "12")])
15811 (define_insn "stack_protect_set_di_media"
15812   [(set (match_operand:DI 0 "memory_operand" "=m")
15813         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15814    (set (match_scratch:DI 2 "=&r") (const_int 0))]
15815   "TARGET_SHMEDIA64"
15817   return       "ld%M1.q %m1,%2" "\n"
15818          "      st%M0.q %m0,%2" "\n"
15819          "      movi    0,%2";
15821   [(set_attr "type" "other")
15822    (set_attr "length" "12")])
15824 (define_expand "stack_protect_test"
15825   [(match_operand 0 "memory_operand" "")
15826    (match_operand 1 "memory_operand" "")
15827    (match_operand 2 "" "")]
15828   ""
15830   if (TARGET_SHMEDIA)
15831     {
15832       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15833       rtx test;
15835       test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15836       if (TARGET_SHMEDIA64)
15837         {
15838           emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15839                                                       operands[1]));
15840           emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15841         }
15842       else
15843         {
15844           emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15845                                                       operands[1]));
15846           emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15847         }
15848     }
15849   else
15850     {
15851       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15852       emit_jump_insn (gen_branch_true (operands[2]));
15853     }
15855   DONE;
15858 (define_insn "stack_protect_test_si"
15859   [(set (reg:SI T_REG)
15860         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15861                     (match_operand:SI 1 "memory_operand" "m")]
15862                    UNSPEC_SP_TEST))
15863   (set (match_scratch:SI 2 "=&r") (const_int 0))
15864   (set (match_scratch:SI 3 "=&r") (const_int 0))]
15865   "!TARGET_SHMEDIA"
15867   return       "mov.l   %0,%2"  "\n"
15868          "      mov.l   %1,%3"  "\n"
15869          "      cmp/eq  %2,%3"  "\n"
15870          "      mov     #0,%2"  "\n"
15871          "      mov     #0,%3";
15873   [(set_attr "type" "other")
15874    (set_attr "length" "10")])
15876 (define_insn "stack_protect_test_si_media"
15877   [(set (match_operand:SI 0 "register_operand" "=&r")
15878         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15879                     (match_operand:SI 2 "memory_operand" "m")]
15880                    UNSPEC_SP_TEST))
15881   (set (match_scratch:SI 3 "=&r") (const_int 0))]
15882   "TARGET_SHMEDIA"
15884   return       "ld%M1.l %m1,%0"         "\n"
15885          "      ld%M2.l %m2,%3"         "\n"
15886          "      cmpeq   %0,%3,%0"       "\n"
15887          "      movi    0,%3";
15889   [(set_attr "type" "other")
15890    (set_attr "length" "16")])
15892 (define_insn "stack_protect_test_di_media"
15893   [(set (match_operand:DI 0 "register_operand" "=&r")
15894         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15895                     (match_operand:DI 2 "memory_operand" "m")]
15896                    UNSPEC_SP_TEST))
15897   (set (match_scratch:DI 3 "=&r") (const_int 0))]
15898   "TARGET_SHMEDIA64"
15900   return       "ld%M1.q %m1,%0"         "\n"
15901          "      ld%M2.q %m2,%3"         "\n"
15902          "      cmpeq   %0,%3,%0"       "\n"
15903          "      movi    0,%3";
15905   [(set_attr "type" "other")
15906    (set_attr "length" "16")])
15908 ;; -------------------------------------------------------------------------
15909 ;; Atomic operations
15910 ;; -------------------------------------------------------------------------
15912 (include "sync.md")