OSDN Git Service

a10774a06fbb073c0b038ce71df75087ccbba648
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;;  2003, 2004, 2005 Free Software Foundation, Inc.
4 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
5 ;;  Improved by Jim Wilson (wilson@cygnus.com).
6
7 ;; This file is part of GCC.
8
9 ;; GCC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GCC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24
25 ;; ??? Should prepend a * to all pattern names which are not used.
26 ;; This will make the compiler smaller, and rebuilds after changes faster.
27
28 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
29 ;; sequences.  Especially the sequences for arithmetic right shifts.
30
31 ;; ??? Should check all DImode patterns for consistency and usefulness.
32
33 ;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
34 ;; way to generate them.
35
36 ;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
37 ;; for a str* inline function.
38
39 ;; BSR is not generated by the compiler proper, but when relaxing, it
40 ;; generates .uses pseudo-ops that allow linker relaxation to create
41 ;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
42
43 ;; Special constraints for SH machine description:
44 ;;
45 ;;    t -- T
46 ;;    x -- mac
47 ;;    l -- pr
48 ;;    z -- r0
49 ;;
50 ;; Special formats used for outputting SH instructions:
51 ;;
52 ;;   %.  --  print a .s if insn needs delay slot
53 ;;   %@  --  print rte/rts if is/isn't an interrupt function
54 ;;   %#  --  output a nop if there is nothing to put in the delay slot
55 ;;   %O  --  print a constant without the #
56 ;;   %R  --  print the lsw reg of a double
57 ;;   %S  --  print the msw reg of a double
58 ;;   %T  --  print next word of a double REG or MEM
59 ;;
60 ;; Special predicates:
61 ;;
62 ;;  arith_operand          -- operand is valid source for arithmetic op
63 ;;  arith_reg_operand      -- operand is valid register for arithmetic op
64 ;;  general_movdst_operand -- operand is valid move destination
65 ;;  general_movsrc_operand -- operand is valid move source
66 ;;  logical_operand        -- operand is valid source for logical op
67
68 ;; -------------------------------------------------------------------------
69 ;; Constants
70 ;; -------------------------------------------------------------------------
71
72 (define_constants [
73   (AP_REG       145)
74   (PR_REG       146)
75   (T_REG        147)
76   (GBR_REG      144)
77   (MACH_REG     148)
78   (MACL_REG     149)
79   (FPUL_REG     150)
80   (RAP_REG      152)
81
82   (FPSCR_REG    151)
83
84   (PIC_REG      12)
85   (FP_REG       14)
86   (SP_REG       15)
87
88   (PR_MEDIA_REG 18)
89   (T_MEDIA_REG  19)
90
91   (R0_REG       0)
92   (R1_REG       1)
93   (R2_REG       2)
94   (R3_REG       3)
95   (R4_REG       4)
96   (R5_REG       5)
97   (R6_REG       6)
98   (R7_REG       7)
99   (R8_REG       8)
100   (R9_REG       9)
101   (R10_REG      10)
102   (R20_REG      20)
103   (R21_REG      21)
104   (R22_REG      22)
105   (R23_REG      23)
106
107   (DR0_REG      64)
108   (DR2_REG      66)
109   (DR4_REG      68)
110   (FR23_REG     87)
111
112   (TR0_REG      128)
113   (TR1_REG      129)
114   (TR2_REG      130)
115
116   (XD0_REG      136)
117
118   ;; These are used with unspec.
119   (UNSPEC_COMPACT_ARGS  0)
120   (UNSPEC_MOVA          1)
121   (UNSPEC_CASESI        2)
122   (UNSPEC_DATALABEL     3)
123   (UNSPEC_BBR           4)
124   (UNSPEC_SFUNC         5)
125   (UNSPEC_PIC           6)
126   (UNSPEC_GOT           7)
127   (UNSPEC_GOTOFF        8)
128   (UNSPEC_PLT           9)
129   (UNSPEC_CALLER        10)
130   (UNSPEC_GOTPLT        11)
131   (UNSPEC_ICACHE        12)
132   (UNSPEC_INIT_TRAMP    13)
133   (UNSPEC_FCOSA         14)
134   (UNSPEC_FSRRA         15)
135   (UNSPEC_FSINA         16)
136   (UNSPEC_NSB           17)
137   (UNSPEC_ALLOCO        18)
138   (UNSPEC_EH_RETURN     19)
139   (UNSPEC_TLSGD         20)
140   (UNSPEC_TLSLDM        21)
141   (UNSPEC_TLSIE         22)
142   (UNSPEC_DTPOFF        23)
143   (UNSPEC_GOTTPOFF      24)
144   (UNSPEC_TPOFF         25)
145   (UNSPEC_RA            26)
146
147   ;; These are used with unspec_volatile.
148   (UNSPECV_BLOCKAGE     0)
149   (UNSPECV_ALIGN        1)
150   (UNSPECV_CONST2       2)
151   (UNSPECV_CONST4       4)
152   (UNSPECV_CONST8       6)
153   (UNSPECV_WINDOW_END   10)
154   (UNSPECV_CONST_END    11)
155 ])
156
157 ;; -------------------------------------------------------------------------
158 ;; Attributes
159 ;; -------------------------------------------------------------------------
160
161 ;; Target CPU.
162
163 (define_attr "cpu"
164  "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
165   (const (symbol_ref "sh_cpu_attr")))
166
167 (define_attr "endian" "big,little"
168  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
169                       (const_string "little") (const_string "big"))))
170
171 ;; Indicate if the default fpu mode is single precision.
172 (define_attr "fpu_single" "yes,no"
173   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
174                          (const_string "yes") (const_string "no"))))
175
176 (define_attr "fmovd" "yes,no"
177   (const (if_then_else (symbol_ref "TARGET_FMOVD")
178                        (const_string "yes") (const_string "no"))))
179 ;; pipeline model
180 (define_attr "pipe_model" "sh1,sh4,sh5media"
181   (const
182    (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
183           (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
184          (const_string "sh1"))))
185
186 ;; cbranch      conditional branch instructions
187 ;; jump         unconditional jumps
188 ;; arith        ordinary arithmetic
189 ;; arith3       a compound insn that behaves similarly to a sequence of
190 ;;              three insns of type arith
191 ;; arith3b      like above, but might end with a redirected branch
192 ;; load         from memory
193 ;; load_si      Likewise, SImode variant for general register.
194 ;; fload        Likewise, but load to fp register.
195 ;; store        to memory
196 ;; move         general purpose register to register
197 ;; mt_group     other sh4 mt instructions
198 ;; fmove        register to register, floating point
199 ;; smpy         word precision integer multiply
200 ;; dmpy         longword or doublelongword precision integer multiply
201 ;; return       rts
202 ;; pload        load of pr reg, which can't be put into delay slot of rts
203 ;; prset        copy register to pr reg, ditto
204 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
205 ;; prget        copy pr to register, ditto
206 ;; pcload       pc relative load of constant value
207 ;; pcfload      Likewise, but load to fp register.
208 ;; pcload_si    Likewise, SImode variant for general register.
209 ;; rte          return from exception
210 ;; sfunc        special function call with known used registers
211 ;; call         function call
212 ;; fp           floating point
213 ;; fdiv         floating point divide (or square root)
214 ;; gp_fpul      move from general purpose register to fpul
215 ;; fpul_gp      move from fpul to general purpose register
216 ;; mac_gp       move from mac[lh] to general purpose register
217 ;; dfp_arith, dfp_cmp,dfp_conv
218 ;; ftrc_s       fix_truncsfsi2_i4
219 ;; dfdiv        double precision floating point divide (or square root)
220 ;; cwb          ic_invalidate_line_i
221 ;; movua        SH4a unaligned load
222 ;; fsrra        square root reciprocal approximate
223 ;; fsca         sine and cosine approximate
224 ;; tls_load     load TLS related address
225 ;; arith_media  SHmedia arithmetic, logical, and shift instructions
226 ;; cbranch_media SHmedia conditional branch instructions
227 ;; cmp_media    SHmedia compare instructions
228 ;; dfdiv_media  SHmedia double precision divide and square root
229 ;; dfmul_media  SHmedia double precision multiply instruction
230 ;; dfparith_media SHmedia double precision floating point arithmetic
231 ;; dfpconv_media SHmedia double precision floating point conversions
232 ;; dmpy_media   SHmedia longword multiply
233 ;; fcmp_media   SHmedia floating point compare instructions
234 ;; fdiv_media   SHmedia single precision divide and square root
235 ;; fload_media  SHmedia floating point register load instructions
236 ;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
237 ;; fparith_media SHmedia single precision floating point arithmetic
238 ;; fpconv_media SHmedia single precision floating point conversions
239 ;; fstore_media SHmedia floating point register store instructions
240 ;; gettr_media  SHmedia gettr instruction
241 ;; invalidate_line_media SHmedia invalidate_line sequence
242 ;; jump_media   SHmedia unconditional branch instructions
243 ;; load_media   SHmedia general register load instructions
244 ;; pt_media     SHmedia pt instruction (expanded by assembler)
245 ;; ptabs_media  SHmedia ptabs instruction
246 ;; store_media  SHmedia general register store instructions
247 ;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
248 ;; mac_media    SHmedia mac-style fixed point operations
249 ;; d2mpy_media  SHmedia: two 32 bit integer multiplies
250 ;; atrans       SHmedia approximate transcendental functions
251 ;; ustore_media SHmedia unaligned stores
252 ;; nil          no-op move, will be deleted.
253
254 (define_attr "type"
255  "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fdiv,ftrc_s,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
256   (const_string "other"))
257
258 ;; We define a new attribute namely "insn_class".We use
259 ;; this for the DFA based pipeline description.
260 ;;
261 ;; mt_group      SH4 "mt" group instructions.
262 ;;
263 ;; ex_group      SH4 "ex" group instructions.
264 ;;
265 ;; ls_group      SH4 "ls" group instructions.
266 ;;
267
268 (define_attr "insn_class"
269   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
270   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
271          (eq_attr "type" "arith,dyn_shift") (const_string "ex_group")
272          (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,gp_fpul,fpul_gp") (const_string "ls_group")
273          (eq_attr "type" "cbranch,jump") (const_string "br_group")
274          (eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
275            (const_string "fe_group")
276          (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb") (const_string "co_group")]
277         (const_string "none")))
278 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
279 ;; so these do not belong in an insn group, although they are modeled
280 ;; with their own define_insn_reservations.
281
282 ;; Indicate what precision must be selected in fpscr for this insn, if any.
283
284 (define_attr "fp_mode" "single,double,none" (const_string "none"))
285
286 ;; Indicate if the fpu mode is set by this instruction
287 ;; "unknown" must have the value as "none" in fp_mode, and means
288 ;; that the instruction/abi has left the processor in an unknown
289 ;; state.
290 ;; "none" means that nothing has changed and no mode is set.
291 ;; This attribute is only used for the Renesas ABI.
292 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
293
294 ; If a conditional branch destination is within -252..258 bytes away
295 ; from the instruction it can be 2 bytes long.  Something in the
296 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
297 ; branches are initially assumed to be 16 bytes long.
298 ; In machine_dependent_reorg, we split all branches that are longer than
299 ; 2 bytes.
300
301 ;; The maximum range used for SImode constant pool entries is 1018.  A final
302 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
303 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
304 ;; instruction around the pool table, 2 bytes of alignment before the table,
305 ;; and 30 bytes of alignment after the table.  That gives a maximum total
306 ;; pool size of 1058 bytes.
307 ;; Worst case code/pool content size ratio is 1:2 (using asms).
308 ;; Thus, in the worst case, there is one instruction in front of a maximum
309 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
310 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
311 ;; If we have a forward branch, the initial table will be put after the
312 ;; unconditional branch.
313 ;;
314 ;; ??? We could do much better by keeping track of the actual pcloads within
315 ;; the branch range and in the pcload range in front of the branch range.
316
317 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
318 ;; inside an le.
319 (define_attr "short_cbranch_p" "no,yes"
320   (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
321          (const_string "no")
322          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
323          (const_string "yes")
324          (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
325          (const_string "no")
326          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
327          (const_string "yes")
328          ] (const_string "no")))
329
330 (define_attr "med_branch_p" "no,yes"
331   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
332               (const_int 1988))
333          (const_string "yes")
334          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
335          (const_string "no")
336          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
337               (const_int 8186))
338          (const_string "yes")
339          ] (const_string "no")))
340
341 (define_attr "med_cbranch_p" "no,yes"
342   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
343               (const_int 1986))
344          (const_string "yes")
345          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
346          (const_string "no")
347          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
348                (const_int 8184))
349          (const_string "yes")
350          ] (const_string "no")))
351
352 (define_attr "braf_branch_p" "no,yes"
353   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
354          (const_string "no")
355          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
356               (const_int 20660))
357          (const_string "yes")
358          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
359          (const_string "no")
360          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
361               (const_int 65530))
362          (const_string "yes")
363          ] (const_string "no")))
364
365 (define_attr "braf_cbranch_p" "no,yes"
366   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
367          (const_string "no")
368          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
369               (const_int 20658))
370          (const_string "yes")
371          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
372          (const_string "no")
373          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
374               (const_int 65528))
375          (const_string "yes")
376          ] (const_string "no")))
377
378 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
379 ; For wider ranges, we need a combination of a code and a data part.
380 ; If we can get a scratch register for a long range jump, the code
381 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
382 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
383 ; long; otherwise, it must be 6 bytes long.
384
385 ; All other instructions are two bytes long by default.
386
387 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
388 ;; but getattrtab doesn't understand this.
389 (define_attr "length" ""
390   (cond [(eq_attr "type" "cbranch")
391          (cond [(eq_attr "short_cbranch_p" "yes")
392                 (const_int 2)
393                 (eq_attr "med_cbranch_p" "yes")
394                 (const_int 6)
395                 (eq_attr "braf_cbranch_p" "yes")
396                 (const_int 12)
397 ;; ??? using pc is not computed transitively.
398                 (ne (match_dup 0) (match_dup 0))
399                 (const_int 14)
400                 (ne (symbol_ref ("flag_pic")) (const_int 0))
401                 (const_int 24)
402                 ] (const_int 16))
403          (eq_attr "type" "jump")
404          (cond [(eq_attr "med_branch_p" "yes")
405                 (const_int 2)
406                 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
407                          (symbol_ref "INSN"))
408                      (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
409                          (symbol_ref "code_for_indirect_jump_scratch")))
410                 (cond [(eq_attr "braf_branch_p" "yes")
411                        (const_int 6)
412                        (eq (symbol_ref "flag_pic") (const_int 0))
413                        (const_int 10)
414                        (ne (symbol_ref "TARGET_SH2") (const_int 0))
415                        (const_int 10)] (const_int 18))
416                 (eq_attr "braf_branch_p" "yes")
417                 (const_int 10)
418 ;; ??? using pc is not computed transitively.
419                 (ne (match_dup 0) (match_dup 0))
420                 (const_int 12)
421                 (ne (symbol_ref ("flag_pic")) (const_int 0))
422                 (const_int 22)
423                 ] (const_int 14))
424          (eq_attr "type" "pt_media")
425          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
426                        (const_int 20) (const_int 12))
427          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
428                          (const_int 4)
429                          (const_int 2))))
430
431 ;; DFA descriptions for the pipelines
432
433 (include "sh1.md")
434 (include "shmedia.md")
435 (include "sh4.md")
436
437 ;; Definitions for filling delay slots
438
439 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
440
441 ;; ??? This should be (nil) instead of (const_int 0)
442 (define_attr "hit_stack" "yes,no"
443         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
444                    (const_int 0))
445                (const_string "no")]
446               (const_string "yes")))
447
448 (define_attr "interrupt_function" "no,yes"
449   (const (symbol_ref "current_function_interrupt")))
450
451 (define_attr "in_delay_slot" "yes,no"
452   (cond [(eq_attr "type" "cbranch") (const_string "no")
453          (eq_attr "type" "pcload,pcload_si") (const_string "no")
454          (eq_attr "needs_delay_slot" "yes") (const_string "no")
455          (eq_attr "length" "2") (const_string "yes")
456          ] (const_string "no")))
457
458 (define_attr "cond_delay_slot" "yes,no"
459   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
460          ] (const_string "no")))
461
462 (define_attr "is_sfunc" ""
463   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
464
465 (define_attr "is_mac_media" ""
466   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
467
468 (define_attr "branch_zero" "yes,no"
469   (cond [(eq_attr "type" "!cbranch") (const_string "no")
470          (ne (symbol_ref "(next_active_insn (insn)\
471                            == (prev_active_insn\
472                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
473                           && get_attr_length (next_active_insn (insn)) == 2")
474              (const_int 0))
475          (const_string "yes")]
476         (const_string "no")))
477
478 ;; SH4 Double-precision computation with double-precision result -
479 ;; the two halves are ready at different times.
480 (define_attr "dfp_comp" "yes,no"
481   (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")]
482         (const_string "no")))
483
484 ;; Insns for which the latency of a preceding fp insn is decreased by one.
485 (define_attr "late_fp_use" "yes,no" (const_string "no"))
486 ;; And feeding insns for which this relevant.
487 (define_attr "any_fp_comp" "yes,no"
488   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
489          (const_string "yes")]
490         (const_string "no")))
491
492 (define_attr "any_int_load" "yes,no"
493   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
494          (const_string "yes")]
495         (const_string "no")))
496
497 (define_delay
498   (eq_attr "needs_delay_slot" "yes")
499   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
500
501 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
502 ;; and thus we can't put a pop instruction in its delay slot.
503 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
504 ;; instruction can go in the delay slot.
505
506 ;; Since a normal return (rts) implicitly uses the PR register,
507 ;; we can't allow PR register loads in an rts delay slot.
508
509 (define_delay
510   (eq_attr "type" "return")
511   [(and (eq_attr "in_delay_slot" "yes")
512         (ior (and (eq_attr "interrupt_function" "no")
513                   (eq_attr "type" "!pload,prset"))
514              (and (eq_attr "interrupt_function" "yes")
515                   (ior
516                    (ne (symbol_ref "TARGET_SH3") (const_int 0))
517                    (eq_attr "hit_stack" "no"))))) (nil) (nil)])
518
519 ;; Since a call implicitly uses the PR register, we can't allow
520 ;; a PR register store in a jsr delay slot.
521
522 (define_delay
523   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
524   [(and (eq_attr "in_delay_slot" "yes")
525         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
526
527 ;; Say that we have annulled true branches, since this gives smaller and
528 ;; faster code when branches are predicted as not taken.
529
530 ;; ??? The non-annulled condition should really be "in_delay_slot",
531 ;; but insns that can be filled in non-annulled get priority over insns
532 ;; that can only be filled in anulled.
533
534 (define_delay
535   (and (eq_attr "type" "cbranch")
536        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
537   ;; SH2e has a hardware bug that pretty much prohibits the use of
538   ;; annuled delay slots.
539   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
540                                         (not (eq_attr "cpu" "sh2e"))) (nil)])
541 \f
542 ;; -------------------------------------------------------------------------
543 ;; SImode signed integer comparisons
544 ;; -------------------------------------------------------------------------
545
546 (define_insn ""
547   [(set (reg:SI T_REG)
548         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
549                        (match_operand:SI 1 "arith_operand" "K08,r"))
550                (const_int 0)))]
551   "TARGET_SH1"
552   "tst  %1,%0"
553   [(set_attr "type" "mt_group")])
554
555 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
556 ;; That would still allow reload to create cmpi instructions, but would
557 ;; perhaps allow forcing the constant into a register when that is better.
558 ;; Probably should use r0 for mem/imm compares, but force constant into a
559 ;; register for pseudo/imm compares.
560
561 (define_insn "cmpeqsi_t"
562   [(set (reg:SI T_REG)
563         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
564                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
565   "TARGET_SH1"
566   "@
567         tst     %0,%0
568         cmp/eq  %1,%0
569         cmp/eq  %1,%0"
570    [(set_attr "type" "mt_group")])
571
572 (define_insn "cmpgtsi_t"
573   [(set (reg:SI T_REG)
574         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
575                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
576   "TARGET_SH1"
577   "@
578         cmp/gt  %1,%0
579         cmp/pl  %0"
580    [(set_attr "type" "mt_group")])
581
582 (define_insn "cmpgesi_t"
583   [(set (reg:SI T_REG)
584         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
585                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
586   "TARGET_SH1"
587   "@
588         cmp/ge  %1,%0
589         cmp/pz  %0"
590    [(set_attr "type" "mt_group")])
591
592 ;; -------------------------------------------------------------------------
593 ;; SImode unsigned integer comparisons
594 ;; -------------------------------------------------------------------------
595
596 (define_insn "cmpgeusi_t"
597   [(set (reg:SI T_REG)
598         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
599                 (match_operand:SI 1 "arith_reg_operand" "r")))]
600   "TARGET_SH1"
601   "cmp/hs       %1,%0"
602    [(set_attr "type" "mt_group")])
603
604 (define_insn "cmpgtusi_t"
605   [(set (reg:SI T_REG)
606         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
607                 (match_operand:SI 1 "arith_reg_operand" "r")))]
608   "TARGET_SH1"
609   "cmp/hi       %1,%0"
610    [(set_attr "type" "mt_group")])
611
612 ;; We save the compare operands in the cmpxx patterns and use them when
613 ;; we generate the branch.
614
615 (define_expand "cmpsi"
616   [(set (reg:SI T_REG)
617         (compare (match_operand:SI 0 "cmpsi_operand" "")
618                  (match_operand:SI 1 "arith_operand" "")))]
619   "TARGET_SH1"
620   "
621 {
622   if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
623       && GET_CODE (operands[1]) != CONST_INT)
624     operands[0] = copy_to_mode_reg (SImode, operands[0]);
625   sh_compare_op0 = operands[0];
626   sh_compare_op1 = operands[1];
627   DONE;
628 }")
629 \f
630 ;; -------------------------------------------------------------------------
631 ;; DImode signed integer comparisons
632 ;; -------------------------------------------------------------------------
633
634 ;; ??? Could get better scheduling by splitting the initial test from the
635 ;; rest of the insn after reload.  However, the gain would hardly justify
636 ;; the sh.md size increase necessary to do that.
637
638 (define_insn ""
639   [(set (reg:SI T_REG)
640         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
641                        (match_operand:DI 1 "arith_operand" "r"))
642                (const_int 0)))]
643   "TARGET_SH1"
644   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
645                                  insn, operands);"
646   [(set_attr "length" "6")
647    (set_attr "type" "arith3b")])
648
649 (define_insn "cmpeqdi_t"
650   [(set (reg:SI T_REG)
651         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
652                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
653   "TARGET_SH1"
654   "@
655         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
656         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
657   [(set_attr "length" "6")
658    (set_attr "type" "arith3b")])
659
660 (define_split
661   [(set (reg:SI T_REG)
662         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
663                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
664 ;; If we applied this split when not optimizing, it would only be
665 ;; applied during the machine-dependent reorg, when no new basic blocks
666 ;; may be created.
667   "TARGET_SH1 && reload_completed && optimize"
668   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
669    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
670                            (label_ref (match_dup 6))
671                            (pc)))
672    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
673    (match_dup 6)]
674   "
675 {
676   operands[2]
677     = gen_rtx_REG (SImode,
678                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
679   operands[3]
680     = (operands[1] == const0_rtx
681        ? const0_rtx
682        : gen_rtx_REG (SImode,
683                       true_regnum (operands[1])
684                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
685   operands[4] = gen_lowpart (SImode, operands[0]);
686   operands[5] = gen_lowpart (SImode, operands[1]);
687   operands[6] = gen_label_rtx ();
688 }")
689
690 (define_insn "cmpgtdi_t"
691   [(set (reg:SI T_REG)
692         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
693                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
694   "TARGET_SH2"
695   "@
696         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
697         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
698   [(set_attr "length" "8")
699    (set_attr "type" "arith3")])
700
701 (define_insn "cmpgedi_t"
702   [(set (reg:SI T_REG)
703         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
704                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
705   "TARGET_SH2"
706   "@
707         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
708         cmp/pz\\t%S0"
709   [(set_attr "length" "8,2")
710    (set_attr "type" "arith3,mt_group")])
711 \f
712 ;; -------------------------------------------------------------------------
713 ;; DImode unsigned integer comparisons
714 ;; -------------------------------------------------------------------------
715
716 (define_insn "cmpgeudi_t"
717   [(set (reg:SI T_REG)
718         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
719                 (match_operand:DI 1 "arith_reg_operand" "r")))]
720   "TARGET_SH2"
721   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
722   [(set_attr "length" "8")
723    (set_attr "type" "arith3")])
724
725 (define_insn "cmpgtudi_t"
726   [(set (reg:SI T_REG)
727         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
728                 (match_operand:DI 1 "arith_reg_operand" "r")))]
729   "TARGET_SH2"
730   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
731   [(set_attr "length" "8")
732    (set_attr "type" "arith3")])
733
734 (define_insn "cmpeqdi_media"
735   [(set (match_operand:DI 0 "register_operand" "=r")
736         (eq:DI (match_operand:DI 1 "register_operand" "%r")
737                (match_operand:DI 2 "arith_reg_or_0_operand" "Nr")))]
738   "TARGET_SHMEDIA"
739   "cmpeq        %1, %N2, %0"
740   [(set_attr "type" "cmp_media")])
741
742 (define_insn "cmpgtdi_media"
743   [(set (match_operand:DI 0 "register_operand" "=r")
744         (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
745                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
746   "TARGET_SHMEDIA"
747   "cmpgt        %N1, %N2, %0"
748   [(set_attr "type" "cmp_media")])
749
750 (define_insn "cmpgtudi_media"
751   [(set (match_operand:DI 0 "register_operand" "=r")
752         (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
753                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
754   "TARGET_SHMEDIA"
755   "cmpgtu       %N1, %N2, %0"
756   [(set_attr "type" "cmp_media")])
757
758 ;; We save the compare operands in the cmpxx patterns and use them when
759 ;; we generate the branch.
760
761 (define_expand "cmpdi"
762   [(set (reg:SI T_REG)
763         (compare (match_operand:DI 0 "arith_operand" "")
764                  (match_operand:DI 1 "arith_operand" "")))]
765   "TARGET_SH2 || TARGET_SHMEDIA"
766   "
767 {
768   sh_compare_op0 = operands[0];
769   sh_compare_op1 = operands[1];
770   DONE;
771 }")
772 ;; -------------------------------------------------------------------------
773 ;; Conditional move instructions
774 ;; -------------------------------------------------------------------------
775
776 ;; The insn names may seem reversed, but note that cmveq performs the move
777 ;; if op1 == 0, and cmvne does it if op1 != 0.
778
779 (define_insn "movdicc_false"
780   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
781         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
782                              (const_int 0))
783          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
784          (match_operand:DI 3 "arith_reg_operand" "0")))]
785   "TARGET_SHMEDIA"
786   "cmveq        %1, %N2, %0"
787   [(set_attr "type" "arith_media")])
788
789 (define_insn "movdicc_true"
790   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
791         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
792                              (const_int 0))
793          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
794          (match_operand:DI 3 "arith_reg_operand" "0")))]
795   "TARGET_SHMEDIA"
796   "cmvne        %1, %N2, %0"
797   [(set_attr "type" "arith_media")])
798
799 (define_expand "movdicc"
800   [(set (match_operand:DI 0 "register_operand" "")
801         (if_then_else:DI (match_operand 1 "comparison_operator" "")
802                          (match_operand:DI 2 "register_operand" "")
803                          (match_operand:DI 3 "register_operand" "")))]
804   "TARGET_SHMEDIA"
805   "
806 {
807   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
808       && GET_MODE (sh_compare_op0) == DImode
809       && sh_compare_op1 == const0_rtx)
810     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
811                                   sh_compare_op0, sh_compare_op1);
812   else
813     {
814       rtx tmp;
815
816       if (no_new_pseudos)
817         FAIL;
818
819       tmp = gen_reg_rtx (DImode);
820
821       switch (GET_CODE (operands[1]))
822         {
823         case EQ:
824           emit_insn (gen_seq (tmp));
825           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
826           break;
827
828         case NE:
829           emit_insn (gen_seq (tmp));
830           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
831           break;
832
833         case GT:
834           emit_insn (gen_sgt (tmp));
835           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
836           break;
837
838         case LT:
839           emit_insn (gen_slt (tmp));
840           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
841           break;
842
843         case GE:
844           emit_insn (gen_slt (tmp));
845           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
846           break;
847
848         case LE:
849           emit_insn (gen_sgt (tmp));
850           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
851           break;
852
853         case GTU:
854           emit_insn (gen_sgtu (tmp));
855           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
856           break;
857
858         case LTU:
859           emit_insn (gen_sltu (tmp));
860           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
861           break;
862
863         case GEU:
864           emit_insn (gen_sltu (tmp));
865           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
866           break;
867
868         case LEU:
869           emit_insn (gen_sgtu (tmp));
870           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
871           break;
872
873         case UNORDERED:
874           emit_insn (gen_sunordered (tmp));
875           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
876           break;
877
878         case ORDERED:
879           emit_insn (gen_sunordered (tmp));
880           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
881           break;
882
883         case UNEQ:
884         case UNGE:
885         case UNGT:
886         case UNLE:
887         case UNLT:
888         case LTGT:
889           FAIL;
890
891         default:
892           gcc_unreachable ();
893         }
894     }
895 }")
896 \f
897 ;; -------------------------------------------------------------------------
898 ;; Addition instructions
899 ;; -------------------------------------------------------------------------
900
901 (define_expand "adddi3"
902   [(set (match_operand:DI 0 "arith_reg_operand" "")
903         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
904                  (match_operand:DI 2 "arith_operand" "")))]
905   ""
906   "
907 {
908   if (TARGET_SH1)
909     {
910       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
911         FAIL;
912       operands[2] = force_reg (DImode, operands[2]);
913       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
914       DONE;
915     }
916 }")
917
918 (define_insn "*adddi3_media"
919   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
920         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
921                  (match_operand:DI 2 "arith_operand" "r,I10")))]
922   "TARGET_SHMEDIA"
923   "@
924         add     %1, %2, %0
925         addi    %1, %2, %0"
926   [(set_attr "type" "arith_media")])
927
928 (define_insn "adddi3z_media"
929   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
930         (zero_extend:DI
931          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
932                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
933   "TARGET_SHMEDIA"
934   "addz.l       %1, %N2, %0"
935   [(set_attr "type" "arith_media")])
936
937 (define_insn "adddi3_compact"
938   [(set (match_operand:DI 0 "arith_reg_operand" "=&r")
939         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
940                  (match_operand:DI 2 "arith_reg_operand" "r")))
941    (clobber (reg:SI T_REG))]
942   "TARGET_SH1"
943   "#"
944   [(set_attr "length" "6")])
945
946 (define_split
947   [(set (match_operand:DI 0 "arith_reg_operand" "")
948         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
949                  (match_operand:DI 2 "arith_reg_operand" "")))
950    (clobber (reg:SI T_REG))]
951   "TARGET_SH1 && reload_completed"
952   [(const_int 0)]
953   "
954 {
955   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
956   high0 = gen_rtx_REG (SImode,
957                        true_regnum (operands[0])
958                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
959   high2 = gen_rtx_REG (SImode,
960                        true_regnum (operands[2])
961                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
962   emit_insn (gen_clrt ());
963   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
964   emit_insn (gen_addc1 (high0, high0, high2));
965   DONE;
966 }")
967
968 (define_insn "addc"
969   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
970         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
971                           (match_operand:SI 2 "arith_reg_operand" "r"))
972                  (reg:SI T_REG)))
973    (set (reg:SI T_REG)
974         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
975   "TARGET_SH1"
976   "addc %2,%0"
977   [(set_attr "type" "arith")])
978
979 (define_insn "addc1"
980   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
981         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
982                           (match_operand:SI 2 "arith_reg_operand" "r"))
983                  (reg:SI T_REG)))
984    (clobber (reg:SI T_REG))]
985   "TARGET_SH1"
986   "addc %2,%0"
987   [(set_attr "type" "arith")])
988
989 (define_expand "addsi3"
990   [(set (match_operand:SI 0 "arith_reg_operand" "")
991         (plus:SI (match_operand:SI 1 "arith_operand" "")
992                  (match_operand:SI 2 "arith_operand" "")))]
993   ""
994   "
995 {
996   if (TARGET_SHMEDIA)
997     operands[1] = force_reg (SImode, operands[1]);
998 }")
999
1000 (define_insn "addsi3_media"
1001   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
1002         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1003                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1004   "TARGET_SHMEDIA"
1005   "@
1006         add.l   %1, %2, %0
1007         addi.l  %1, %2, %0"
1008   [(set_attr "type" "arith_media")])
1009
1010 (define_insn "*addsi3_compact"
1011   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1012         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1013                  (match_operand:SI 2 "arith_operand" "rI08")))]
1014   "TARGET_SH1"
1015   "add  %2,%0"
1016   [(set_attr "type" "arith")])
1017
1018 ;; -------------------------------------------------------------------------
1019 ;; Subtraction instructions
1020 ;; -------------------------------------------------------------------------
1021
1022 (define_expand "subdi3"
1023   [(set (match_operand:DI 0 "arith_reg_operand" "")
1024         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1025                   (match_operand:DI 2 "arith_reg_operand" "")))]
1026   ""
1027   "
1028 {
1029   if (TARGET_SH1)
1030     {
1031       operands[1] = force_reg (DImode, operands[1]);
1032       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1033       DONE;
1034     }
1035 }")
1036
1037 (define_insn "*subdi3_media"
1038   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1039         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1040                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1041   "TARGET_SHMEDIA"
1042   "sub  %N1, %2, %0"
1043   [(set_attr "type" "arith_media")])
1044
1045 (define_insn "subdi3_compact"
1046   [(set (match_operand:DI 0 "arith_reg_operand" "=&r")
1047         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1048                  (match_operand:DI 2 "arith_reg_operand" "r")))
1049    (clobber (reg:SI T_REG))]
1050   "TARGET_SH1"
1051   "#"
1052   [(set_attr "length" "6")])
1053
1054 (define_split
1055   [(set (match_operand:DI 0 "arith_reg_operand" "")
1056         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1057                   (match_operand:DI 2 "arith_reg_operand" "")))
1058    (clobber (reg:SI T_REG))]
1059   "TARGET_SH1 && reload_completed"
1060   [(const_int 0)]
1061   "
1062 {
1063   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1064   high0 = gen_rtx_REG (SImode,
1065                        true_regnum (operands[0])
1066                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1067   high2 = gen_rtx_REG (SImode,
1068                        true_regnum (operands[2])
1069                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1070   emit_insn (gen_clrt ());
1071   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1072   emit_insn (gen_subc1 (high0, high0, high2));
1073   DONE;
1074 }")
1075
1076 (define_insn "subc"
1077   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1078         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1079                             (match_operand:SI 2 "arith_reg_operand" "r"))
1080                   (reg:SI T_REG)))
1081    (set (reg:SI T_REG)
1082         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1083                           (reg:SI T_REG))
1084                 (match_dup 1)))]
1085   "TARGET_SH1"
1086   "subc %2,%0"
1087   [(set_attr "type" "arith")])
1088
1089 (define_insn "subc1"
1090   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1091         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1092                             (match_operand:SI 2 "arith_reg_operand" "r"))
1093                   (reg:SI T_REG)))
1094    (clobber (reg:SI T_REG))]
1095   "TARGET_SH1"
1096   "subc %2,%0"
1097   [(set_attr "type" "arith")])
1098
1099 (define_insn "*subsi3_internal"
1100   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1101         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1102                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1103   "TARGET_SH1"
1104   "sub  %2,%0"
1105   [(set_attr "type" "arith")])
1106
1107 (define_insn "*subsi3_media"
1108   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1109         (minus:SI (match_operand:SI 1 "extend_reg_or_0_operand" "rN")
1110                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1111   "TARGET_SHMEDIA"
1112   "sub.l        %N1, %2, %0"
1113   [(set_attr "type" "arith_media")])
1114
1115 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1116 ;; will sometimes save one instruction.  Otherwise we might get
1117 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1118 ;; are the same.
1119
1120 (define_expand "subsi3"
1121   [(set (match_operand:SI 0 "arith_reg_operand" "")
1122         (minus:SI (match_operand:SI 1 "arith_operand" "")
1123                   (match_operand:SI 2 "arith_reg_operand" "")))]
1124   ""
1125   "
1126 {
1127   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1128     {
1129       emit_insn (gen_negsi2 (operands[0], operands[2]));
1130       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1131       DONE;
1132     }
1133   if (TARGET_SHMEDIA)
1134     {
1135       if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1136         FAIL;
1137       if (operands[1] != const0_rtx)
1138         operands[1] = force_reg (SImode, operands[1]);
1139     }
1140 }")
1141 \f
1142 ;; -------------------------------------------------------------------------
1143 ;; Division instructions
1144 ;; -------------------------------------------------------------------------
1145
1146 ;; We take advantage of the library routines which don't clobber as many
1147 ;; registers as a normal function call would.
1148
1149 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1150 ;; also has an effect on the register that holds the address of the sfunc.
1151 ;; To make this work, we have an extra dummy insn that shows the use
1152 ;; of this register for reorg.
1153
1154 (define_insn "use_sfunc_addr"
1155   [(set (reg:SI PR_REG)
1156         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1157   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1158   ""
1159   [(set_attr "length" "0")])
1160
1161 (define_insn "udivsi3_sh2a"
1162   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1163         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1164                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1165   "TARGET_SH2A"
1166   "divu %2,%1"
1167   [(set_attr "type" "arith")
1168    (set_attr "in_delay_slot" "no")])
1169
1170 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1171 ;; hard register 0.  If we used hard register 0, then the next instruction
1172 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1173 ;; gets allocated to a stack slot that needs its address reloaded, then
1174 ;; there is nothing to prevent reload from using r0 to reload the address.
1175 ;; This reload would clobber the value in r0 we are trying to store.
1176 ;; If we let reload allocate r0, then this problem can never happen.
1177
1178 (define_insn "udivsi3_i1"
1179   [(set (match_operand:SI 0 "register_operand" "=z")
1180         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1181    (clobber (reg:SI T_REG))
1182    (clobber (reg:SI PR_REG))
1183    (clobber (reg:SI R4_REG))
1184    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1185   "TARGET_SH1 && ! TARGET_SH4"
1186   "jsr  @%1%#"
1187   [(set_attr "type" "sfunc")
1188    (set_attr "needs_delay_slot" "yes")])
1189
1190 ; Since shmedia-nofpu code could be linked against shcompact code, and
1191 ; the udivsi3 libcall has the same name, we must consider all registers
1192 ; clobbered that are in the union of the registers clobbered by the
1193 ; shmedia and the shcompact implementation.  Note, if the shcompact
1194 ; implementation actually used shcompact code, we'd need to clobber
1195 ; also r23 and fr23.
1196 (define_insn "udivsi3_i1_media"
1197   [(set (match_operand:SI 0 "register_operand" "=z")
1198         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1199    (clobber (reg:SI T_MEDIA_REG))
1200    (clobber (reg:SI PR_MEDIA_REG))
1201    (clobber (reg:SI R20_REG))
1202    (clobber (reg:SI R21_REG))
1203    (clobber (reg:SI R22_REG))
1204    (clobber (reg:DI TR0_REG))
1205    (clobber (reg:DI TR1_REG))
1206    (clobber (reg:DI TR2_REG))
1207    (use (match_operand:DI 1 "target_operand" "b"))]
1208   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1209   "blink        %1, r18"
1210   [(set_attr "type" "sfunc")
1211    (set_attr "needs_delay_slot" "yes")])
1212
1213 (define_expand "udivsi3_i4_media"
1214   [(set (match_dup 3)
1215         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1216    (set (match_dup 4)
1217         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1218    (set (match_dup 5) (float:DF (match_dup 3)))
1219    (set (match_dup 6) (float:DF (match_dup 4)))
1220    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1221    (set (match_dup 8) (fix:DI (match_dup 7)))
1222    (set (match_operand:SI 0 "register_operand" "")
1223         (truncate:SI (match_dup 8)))]
1224   "TARGET_SHMEDIA_FPU"
1225   "
1226 {
1227   operands[3] = gen_reg_rtx (DImode);
1228   operands[4] = gen_reg_rtx (DImode);
1229   operands[5] = gen_reg_rtx (DFmode);
1230   operands[6] = gen_reg_rtx (DFmode);
1231   operands[7] = gen_reg_rtx (DFmode);
1232   operands[8] = gen_reg_rtx (DImode);
1233 }")
1234
1235 (define_insn "udivsi3_i4"
1236   [(set (match_operand:SI 0 "register_operand" "=y")
1237         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1238    (clobber (reg:SI T_REG))
1239    (clobber (reg:SI PR_REG))
1240    (clobber (reg:DF DR0_REG))
1241    (clobber (reg:DF DR2_REG))
1242    (clobber (reg:DF DR4_REG))
1243    (clobber (reg:SI R0_REG))
1244    (clobber (reg:SI R1_REG))
1245    (clobber (reg:SI R4_REG))
1246    (clobber (reg:SI R5_REG))
1247    (use (reg:PSI FPSCR_REG))
1248    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1249   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1250   "jsr  @%1%#"
1251   [(set_attr "type" "sfunc")
1252    (set_attr "fp_mode" "double")
1253    (set_attr "needs_delay_slot" "yes")])
1254
1255 (define_insn "udivsi3_i4_single"
1256   [(set (match_operand:SI 0 "register_operand" "=y")
1257         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1258    (clobber (reg:SI T_REG))
1259    (clobber (reg:SI PR_REG))
1260    (clobber (reg:DF DR0_REG))
1261    (clobber (reg:DF DR2_REG))
1262    (clobber (reg:DF DR4_REG))
1263    (clobber (reg:SI R0_REG))
1264    (clobber (reg:SI R1_REG))
1265    (clobber (reg:SI R4_REG))
1266    (clobber (reg:SI R5_REG))
1267    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1268   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1269   "jsr  @%1%#"
1270   [(set_attr "type" "sfunc")
1271    (set_attr "needs_delay_slot" "yes")])
1272
1273 (define_expand "udivsi3"
1274   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1275    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1276    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1277    (parallel [(set (match_operand:SI 0 "register_operand" "")
1278                    (udiv:SI (reg:SI R4_REG)
1279                             (reg:SI R5_REG)))
1280               (clobber (reg:SI T_REG))
1281               (clobber (reg:SI PR_REG))
1282               (clobber (reg:SI R4_REG))
1283               (use (match_dup 3))])]
1284   ""
1285   "
1286 {
1287   rtx first, last;
1288
1289   operands[3] = gen_reg_rtx (Pmode);
1290   /* Emit the move of the address to a pseudo outside of the libcall.  */
1291   if (TARGET_HARD_SH4 && TARGET_SH2E)
1292     {
1293       emit_move_insn (operands[3], function_symbol (\"__udivsi3_i4\"));
1294       if (TARGET_FPU_SINGLE)
1295         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1296       else
1297         last = gen_udivsi3_i4 (operands[0], operands[3]);
1298     }
1299   else if (TARGET_SHMEDIA_FPU)
1300     {
1301       operands[1] = force_reg (SImode, operands[1]);
1302       operands[2] = force_reg (SImode, operands[2]);
1303       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1304       DONE;
1305     }
1306   else if (TARGET_SH2A)
1307     {
1308       operands[1] = force_reg (SImode, operands[1]);
1309       operands[2] = force_reg (SImode, operands[2]);
1310       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1311       DONE;
1312     }
1313   else if (TARGET_SH5)
1314     {
1315       emit_move_insn (operands[3],
1316                       function_symbol (TARGET_FPU_ANY
1317                                        ? \"__udivsi3_i4\"
1318                                        : \"__udivsi3\"));
1319
1320       if (TARGET_SHMEDIA)
1321         last = gen_udivsi3_i1_media (operands[0],
1322                                      Pmode == DImode
1323                                      ? operands[3]
1324                                      : gen_rtx_SUBREG (DImode, operands[3],
1325                                                        0));
1326       else if (TARGET_FPU_ANY)
1327         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1328       else
1329         last = gen_udivsi3_i1 (operands[0], operands[3]);
1330     }
1331   else
1332     {
1333       emit_move_insn (operands[3], function_symbol (\"__udivsi3\"));
1334       last = gen_udivsi3_i1 (operands[0], operands[3]);
1335     }
1336   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1337   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1338   last = emit_insn (last);
1339   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1340      invariant code motion can move it.  */
1341   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1342   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1343   DONE;
1344 }")
1345
1346 (define_insn "divsi3_sh2a"
1347   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1348         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1349                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1350   "TARGET_SH2A"
1351   "divs %2,%1"
1352   [(set_attr "type" "arith")
1353    (set_attr "in_delay_slot" "no")])
1354
1355 (define_insn "divsi3_i1"
1356   [(set (match_operand:SI 0 "register_operand" "=z")
1357         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1358    (clobber (reg:SI T_REG))
1359    (clobber (reg:SI PR_REG))
1360    (clobber (reg:SI R1_REG))
1361    (clobber (reg:SI R2_REG))
1362    (clobber (reg:SI R3_REG))
1363    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1364   "TARGET_SH1 && ! TARGET_SH4"
1365   "jsr  @%1%#"
1366   [(set_attr "type" "sfunc")
1367    (set_attr "needs_delay_slot" "yes")])
1368
1369 ; Since shmedia-nofpu code could be linked against shcompact code, and
1370 ; the sdivsi3 libcall has the same name, we must consider all registers
1371 ; clobbered that are in the union of the registers clobbered by the
1372 ; shmedia and the shcompact implementation.  Note, if the shcompact
1373 ; implementation actually used shcompact code, we'd need to clobber
1374 ; also r22, r23 and fr23.
1375 (define_insn "divsi3_i1_media"
1376   [(set (match_operand:SI 0 "register_operand" "=z")
1377         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1378    (clobber (reg:SI T_MEDIA_REG))
1379    (clobber (reg:SI PR_MEDIA_REG))
1380    (clobber (reg:SI R1_REG))
1381    (clobber (reg:SI R2_REG))
1382    (clobber (reg:SI R3_REG))
1383    (clobber (reg:SI R20_REG))
1384    (clobber (reg:SI R21_REG))
1385    (clobber (reg:DI TR0_REG))
1386    (clobber (reg:DI TR1_REG))
1387    (clobber (reg:DI TR2_REG))
1388    (use (match_operand:DI 1 "target_operand" "b"))]
1389   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1390   "blink        %1, r18"
1391   [(set_attr "type" "sfunc")])
1392
1393 (define_expand "divsi3_i4_media"
1394   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
1395    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
1396    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
1397    (set (match_operand:SI 0 "register_operand" "=r")
1398         (fix:SI (match_dup 5)))]
1399   "TARGET_SHMEDIA_FPU"
1400   "
1401 {
1402   operands[3] = gen_reg_rtx (DFmode);
1403   operands[4] = gen_reg_rtx (DFmode);
1404   operands[5] = gen_reg_rtx (DFmode);
1405 }")
1406
1407 (define_insn "divsi3_i4"
1408   [(set (match_operand:SI 0 "register_operand" "=y")
1409         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1410    (clobber (reg:SI PR_REG))
1411    (clobber (reg:DF DR0_REG))
1412    (clobber (reg:DF DR2_REG))
1413    (use (reg:PSI FPSCR_REG))
1414    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1415   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1416   "jsr  @%1%#"
1417   [(set_attr "type" "sfunc")
1418    (set_attr "fp_mode" "double")
1419    (set_attr "needs_delay_slot" "yes")])
1420
1421 (define_insn "divsi3_i4_single"
1422   [(set (match_operand:SI 0 "register_operand" "=y")
1423         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1424    (clobber (reg:SI PR_REG))
1425    (clobber (reg:DF DR0_REG))
1426    (clobber (reg:DF DR2_REG))
1427    (clobber (reg:SI R2_REG))
1428    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1429   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1430   "jsr  @%1%#"
1431   [(set_attr "type" "sfunc")
1432    (set_attr "needs_delay_slot" "yes")])
1433
1434 (define_expand "divsi3"
1435   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
1436    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1437    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1438    (parallel [(set (match_operand:SI 0 "register_operand" "")
1439                    (div:SI (reg:SI R4_REG)
1440                            (reg:SI R5_REG)))
1441               (clobber (reg:SI T_REG))
1442               (clobber (reg:SI PR_REG))
1443               (clobber (reg:SI R1_REG))
1444               (clobber (reg:SI R2_REG))
1445               (clobber (reg:SI R3_REG))
1446               (use (match_dup 3))])]
1447   ""
1448   "
1449 {
1450   rtx first, last;
1451
1452   operands[3] = gen_reg_rtx (Pmode);
1453   /* Emit the move of the address to a pseudo outside of the libcall.  */
1454   if (TARGET_HARD_SH4 && TARGET_SH2E)
1455     {
1456       emit_move_insn (operands[3], function_symbol (\"__sdivsi3_i4\"));
1457       if (TARGET_FPU_SINGLE)
1458         last = gen_divsi3_i4_single (operands[0], operands[3]);
1459       else
1460         last = gen_divsi3_i4 (operands[0], operands[3]);
1461     }
1462   else if (TARGET_SH2A)
1463     {
1464       operands[1] = force_reg (SImode, operands[1]);
1465       operands[2] = force_reg (SImode, operands[2]);
1466       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
1467       DONE;
1468     }
1469   else if (TARGET_SHMEDIA_FPU)
1470     {
1471       operands[1] = force_reg (SImode, operands[1]);
1472       operands[2] = force_reg (SImode, operands[2]);
1473       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
1474       DONE;
1475     }
1476   else if (TARGET_SH5)
1477     {
1478       emit_move_insn (operands[3],
1479                       function_symbol (TARGET_FPU_ANY
1480                                        ? \"__sdivsi3_i4\"
1481                                        : \"__sdivsi3\"));
1482
1483       if (TARGET_SHMEDIA)
1484         last = gen_divsi3_i1_media (operands[0],
1485                                     Pmode == DImode
1486                                     ? operands[3]
1487                                     : gen_rtx_SUBREG (DImode, operands[3],
1488                                                       0));
1489       else if (TARGET_FPU_ANY)
1490         last = gen_divsi3_i4_single (operands[0], operands[3]);
1491       else
1492         last = gen_divsi3_i1 (operands[0], operands[3]);
1493     }
1494   else
1495     {
1496       emit_move_insn (operands[3], function_symbol (\"__sdivsi3\"));
1497       last = gen_divsi3_i1 (operands[0], operands[3]);
1498     }
1499   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1500   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1501   last = emit_insn (last);
1502   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1503      invariant code motion can move it.  */
1504   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1505   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1506   DONE;
1507 }")
1508 \f
1509 ;; -------------------------------------------------------------------------
1510 ;; Multiplication instructions
1511 ;; -------------------------------------------------------------------------
1512
1513 (define_insn "umulhisi3_i"
1514   [(set (reg:SI MACL_REG)
1515         (mult:SI (zero_extend:SI
1516                   (match_operand:HI 0 "arith_reg_operand" "r"))
1517                  (zero_extend:SI
1518                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1519   "TARGET_SH1"
1520   "mulu.w       %1,%0"
1521   [(set_attr "type" "smpy")])
1522
1523 (define_insn "mulhisi3_i"
1524   [(set (reg:SI MACL_REG)
1525         (mult:SI (sign_extend:SI
1526                   (match_operand:HI 0 "arith_reg_operand" "r"))
1527                  (sign_extend:SI
1528                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1529   "TARGET_SH1"
1530   "muls.w       %1,%0"
1531   [(set_attr "type" "smpy")])
1532
1533 (define_expand "mulhisi3"
1534   [(set (reg:SI MACL_REG)
1535         (mult:SI (sign_extend:SI
1536                   (match_operand:HI 1 "arith_reg_operand" ""))
1537                  (sign_extend:SI
1538                   (match_operand:HI 2 "arith_reg_operand" ""))))
1539    (set (match_operand:SI 0 "arith_reg_operand" "")
1540         (reg:SI MACL_REG))]
1541   "TARGET_SH1"
1542   "
1543 {
1544   rtx first, last;
1545
1546   first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
1547   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1548   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1549      invariant code motion can move it.  */
1550   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1551   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1552   /* expand_binop can't find a suitable code in umul_widen_optab to
1553      make a REG_EQUAL note from, so make one here.
1554      See also smulsi3_highpart.
1555      ??? Alternatively, we could put this at the calling site of expand_binop,
1556      i.e. expand_expr.  */
1557   REG_NOTES (last)
1558     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1559                          REG_NOTES (last));
1560   DONE;
1561 }")
1562
1563 (define_expand "umulhisi3"
1564   [(set (reg:SI MACL_REG)
1565         (mult:SI (zero_extend:SI
1566                   (match_operand:HI 1 "arith_reg_operand" ""))
1567                  (zero_extend:SI
1568                   (match_operand:HI 2 "arith_reg_operand" ""))))
1569    (set (match_operand:SI 0 "arith_reg_operand" "")
1570         (reg:SI MACL_REG))]
1571   "TARGET_SH1"
1572   "
1573 {
1574   rtx first, last;
1575
1576   first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
1577   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1578   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1579      invariant code motion can move it.  */
1580   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1581   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1582   /* expand_binop can't find a suitable code in umul_widen_optab to
1583      make a REG_EQUAL note from, so make one here.
1584      See also smulsi3_highpart.
1585      ??? Alternatively, we could put this at the calling site of expand_binop,
1586      i.e. expand_expr.  */
1587   REG_NOTES (last)
1588     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1589                          REG_NOTES (last));
1590   DONE;
1591 }")
1592
1593 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
1594 ;; a call to a routine which clobbers known registers.
1595
1596 (define_insn ""
1597   [(set (match_operand:SI 1 "register_operand" "=z")
1598         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1599    (clobber (reg:SI MACL_REG))
1600    (clobber (reg:SI T_REG))
1601    (clobber (reg:SI PR_REG))
1602    (clobber (reg:SI R3_REG))
1603    (clobber (reg:SI R2_REG))
1604    (clobber (reg:SI R1_REG))
1605    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
1606   "TARGET_SH1"
1607   "jsr  @%0%#"
1608   [(set_attr "type" "sfunc")
1609    (set_attr "needs_delay_slot" "yes")])
1610
1611 (define_expand "mulsi3_call"
1612   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1613    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1614    (parallel[(set (match_operand:SI 0 "register_operand" "")
1615                   (mult:SI (reg:SI R4_REG)
1616                            (reg:SI R5_REG)))
1617              (clobber (reg:SI MACL_REG))
1618              (clobber (reg:SI T_REG))
1619              (clobber (reg:SI PR_REG))
1620              (clobber (reg:SI R3_REG))
1621              (clobber (reg:SI R2_REG))
1622              (clobber (reg:SI R1_REG))
1623              (use (match_operand:SI 3 "register_operand" ""))])]
1624   "TARGET_SH1"
1625   "")
1626
1627 (define_insn "mul_r"
1628   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1629         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
1630                  (match_operand:SI 2 "arith_reg_operand" "z")))]
1631   "TARGET_SH2A"
1632   "mulr %2,%0"
1633   [(set_attr "type" "dmpy")])
1634
1635 (define_insn "mul_l"
1636   [(set (reg:SI MACL_REG)
1637         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
1638                  (match_operand:SI 1 "arith_reg_operand" "r")))]
1639   "TARGET_SH2"
1640   "mul.l        %1,%0"
1641   [(set_attr "type" "dmpy")])
1642
1643 (define_expand "mulsi3"
1644   [(set (reg:SI MACL_REG)
1645         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
1646                   (match_operand:SI 2 "arith_reg_operand" "")))
1647    (set (match_operand:SI 0 "arith_reg_operand" "")
1648         (reg:SI MACL_REG))]
1649   "TARGET_SH1"
1650   "
1651 {
1652   rtx first, last;
1653
1654   if (!TARGET_SH2)
1655     {
1656       /* The address must be set outside the libcall,
1657          since it goes into a pseudo.  */
1658       rtx sym = function_symbol (\"__mulsi3\");
1659       rtx addr = force_reg (SImode, sym);
1660       rtx insns = gen_mulsi3_call (operands[0], operands[1],
1661                                    operands[2], addr);
1662       first = insns;
1663       last = emit_insn (insns);
1664     }
1665   else
1666     {
1667       rtx macl = gen_rtx_REG (SImode, MACL_REG);
1668
1669       first = emit_insn (gen_mul_l (operands[1], operands[2]));
1670       /* consec_sets_giv can only recognize the first insn that sets a
1671          giv as the giv insn.  So we must tag this also with a REG_EQUAL
1672          note.  */
1673       last = emit_insn (gen_movsi_i ((operands[0]), macl));
1674     }
1675   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1676      invariant code motion can move it.  */
1677   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1678   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1679   DONE;
1680 }")
1681
1682 (define_insn "mulsidi3_i"
1683   [(set (reg:SI MACH_REG)
1684         (truncate:SI
1685          (lshiftrt:DI
1686           (mult:DI
1687            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1688            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1689           (const_int 32))))
1690    (set (reg:SI MACL_REG)
1691         (mult:SI (match_dup 0)
1692                  (match_dup 1)))]
1693   "TARGET_SH2"
1694   "dmuls.l      %1,%0"
1695   [(set_attr "type" "dmpy")])
1696
1697 (define_expand "mulsidi3"
1698   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1699         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1700                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1701   "TARGET_SH2 || TARGET_SHMEDIA"
1702   "
1703 {
1704   if (TARGET_SH2)
1705     {
1706        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
1707                                         operands[2]));
1708        DONE;
1709     }
1710 }")
1711
1712 (define_insn "mulsidi3_media"
1713   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1714         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
1715                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
1716   "TARGET_SHMEDIA"
1717   "muls.l       %1, %2, %0"
1718   [(set_attr "type" "dmpy_media")])
1719
1720 (define_insn "mulsidi3_compact"
1721   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1722         (mult:DI
1723          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1724          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1725    (clobber (reg:SI MACH_REG))
1726    (clobber (reg:SI MACL_REG))]
1727   "TARGET_SH2"
1728   "#")
1729
1730 (define_split
1731   [(set (match_operand:DI 0 "arith_reg_operand" "")
1732         (mult:DI
1733          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1734          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1735    (clobber (reg:SI MACH_REG))
1736    (clobber (reg:SI MACL_REG))]
1737   "TARGET_SH2"
1738   [(const_int 0)]
1739   "
1740 {
1741   rtx low_dst = gen_lowpart (SImode, operands[0]);
1742   rtx high_dst = gen_highpart (SImode, operands[0]);
1743
1744   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
1745
1746   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1747   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1748   /* We need something to tag the possible REG_EQUAL notes on to.  */
1749   emit_move_insn (operands[0], operands[0]);
1750   DONE;
1751 }")
1752
1753 (define_insn "umulsidi3_i"
1754   [(set (reg:SI MACH_REG)
1755         (truncate:SI
1756          (lshiftrt:DI
1757           (mult:DI
1758            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1759            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1760           (const_int 32))))
1761    (set (reg:SI MACL_REG)
1762         (mult:SI (match_dup 0)
1763                  (match_dup 1)))]
1764   "TARGET_SH2"
1765   "dmulu.l      %1,%0"
1766   [(set_attr "type" "dmpy")])
1767
1768 (define_expand "umulsidi3"
1769   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1770         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1771                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1772   "TARGET_SH2 || TARGET_SHMEDIA"
1773   "
1774 {
1775   if (TARGET_SH2)
1776     {
1777        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
1778                                          operands[2]));
1779        DONE;
1780     }
1781 }")
1782
1783 (define_insn "umulsidi3_media"
1784   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1785         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
1786                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
1787   "TARGET_SHMEDIA"
1788   "mulu.l       %1, %2, %0"
1789   [(set_attr "type" "dmpy_media")])
1790
1791 (define_insn "umulsidi3_compact"
1792   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1793         (mult:DI
1794          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1795          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1796    (clobber (reg:SI MACH_REG))
1797    (clobber (reg:SI MACL_REG))]
1798   "TARGET_SH2"
1799   "#")
1800
1801 (define_split
1802   [(set (match_operand:DI 0 "arith_reg_operand" "")
1803         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1804                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1805    (clobber (reg:SI MACH_REG))
1806    (clobber (reg:SI MACL_REG))]
1807   "TARGET_SH2"
1808   [(const_int 0)]
1809   "
1810 {
1811   rtx low_dst = gen_lowpart (SImode, operands[0]);
1812   rtx high_dst = gen_highpart (SImode, operands[0]);
1813
1814   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
1815
1816   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1817   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1818   /* We need something to tag the possible REG_EQUAL notes on to.  */
1819   emit_move_insn (operands[0], operands[0]);
1820   DONE;
1821 }")
1822
1823 (define_insn "smulsi3_highpart_i"
1824   [(set (reg:SI MACH_REG)
1825         (truncate:SI
1826          (lshiftrt:DI
1827           (mult:DI
1828            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1829            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1830           (const_int 32))))
1831    (clobber (reg:SI MACL_REG))]
1832   "TARGET_SH2"
1833   "dmuls.l      %1,%0"
1834   [(set_attr "type" "dmpy")])
1835
1836 (define_expand "smulsi3_highpart"
1837   [(parallel
1838     [(set (reg:SI MACH_REG)
1839           (truncate:SI
1840            (lshiftrt:DI
1841             (mult:DI
1842              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1843              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1844             (const_int 32))))
1845     (clobber (reg:SI MACL_REG))])
1846    (set (match_operand:SI 0 "arith_reg_operand" "")
1847         (reg:SI MACH_REG))]
1848   "TARGET_SH2"
1849   "
1850 {
1851   rtx first, last;
1852
1853   first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
1854   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1855   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1856      invariant code motion can move it.  */
1857   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1858   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1859   /* expand_binop can't find a suitable code in mul_highpart_optab to
1860      make a REG_EQUAL note from, so make one here.
1861      See also {,u}mulhisi.
1862      ??? Alternatively, we could put this at the calling site of expand_binop,
1863      i.e. expand_mult_highpart.  */
1864   REG_NOTES (last)
1865     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1866                          REG_NOTES (last));
1867   DONE;
1868 }")
1869
1870 (define_insn "umulsi3_highpart_i"
1871   [(set (reg:SI MACH_REG)
1872         (truncate:SI
1873          (lshiftrt:DI
1874           (mult:DI
1875            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1876            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1877           (const_int 32))))
1878    (clobber (reg:SI MACL_REG))]
1879   "TARGET_SH2"
1880   "dmulu.l      %1,%0"
1881   [(set_attr "type" "dmpy")])
1882
1883 (define_expand "umulsi3_highpart"
1884   [(parallel
1885     [(set (reg:SI MACH_REG)
1886           (truncate:SI
1887            (lshiftrt:DI
1888             (mult:DI
1889              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1890              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1891             (const_int 32))))
1892     (clobber (reg:SI MACL_REG))])
1893    (set (match_operand:SI 0 "arith_reg_operand" "")
1894         (reg:SI MACH_REG))]
1895   "TARGET_SH2"
1896   "
1897 {
1898   rtx first, last;
1899
1900   first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
1901   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1902   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1903      invariant code motion can move it.  */
1904   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1905   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1906   DONE;
1907 }")
1908 \f
1909 ;; -------------------------------------------------------------------------
1910 ;; Logical operations
1911 ;; -------------------------------------------------------------------------
1912
1913 (define_insn "*andsi3_compact"
1914   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1915         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1916                 (match_operand:SI 2 "logical_operand" "r,K08")))]
1917   "TARGET_SH1"
1918   "and  %2,%0"
1919   [(set_attr "type" "arith")])
1920
1921 ;; If the constant is 255, then emit an extu.b instruction instead of an
1922 ;; and, since that will give better code.
1923
1924 (define_expand "andsi3"
1925   [(set (match_operand:SI 0 "arith_reg_operand" "")
1926         (and:SI (match_operand:SI 1 "arith_reg_operand" "")
1927                 (match_operand:SI 2 "logical_operand" "")))]
1928   "TARGET_SH1"
1929   "
1930 {
1931   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
1932     {
1933       emit_insn (gen_zero_extendqisi2 (operands[0],
1934                                        gen_lowpart (QImode, operands[1])));
1935       DONE;
1936     }
1937 }")
1938
1939 (define_insn_and_split "anddi3"
1940   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r,r")
1941         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
1942                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
1943   "TARGET_SHMEDIA"
1944   "@
1945         and     %1, %2, %0
1946         andi    %1, %2, %0
1947         #"
1948   "reload_completed
1949    && ! logical_operand (operands[2], DImode)"
1950   [(const_int 0)]
1951   "
1952 {
1953   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
1954     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
1955   else
1956     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
1957   DONE;
1958 }"
1959   [(set_attr "type" "arith_media")])
1960
1961 (define_insn "andcdi3"
1962   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1963         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
1964                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
1965   "TARGET_SHMEDIA"
1966   "andc %1,%2,%0"
1967   [(set_attr "type" "arith_media")])
1968
1969 (define_insn "iorsi3"
1970   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1971         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1972                 (match_operand:SI 2 "logical_operand" "r,K08")))]
1973   "TARGET_SH1"
1974   "or   %2,%0"
1975   [(set_attr "type" "arith")])
1976
1977 (define_insn "iordi3"
1978   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1979         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1980                 (match_operand:DI 2 "logical_operand" "r,I10")))]
1981   "TARGET_SHMEDIA"
1982   "@
1983         or      %1, %2, %0
1984         ori     %1, %2, %0"
1985   [(set_attr "type" "arith_media")])
1986
1987 (define_insn "xorsi3"
1988   [(set (match_operand:SI 0 "arith_reg_operand" "=z,r")
1989         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1990                 (match_operand:SI 2 "logical_operand" "K08,r")))]
1991   "TARGET_SH1"
1992   "xor  %2,%0"
1993   [(set_attr "type" "arith")])
1994
1995 (define_insn "xordi3"
1996   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1997         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1998                 (match_operand:DI 2 "shmedia_6bit_operand" "r,I06")))]
1999   "TARGET_SHMEDIA"
2000   "@
2001         xor     %1, %2, %0
2002         xori    %1, %2, %0"
2003   [(set_attr "type" "arith_media")])
2004
2005 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
2006 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
2007 (define_split
2008   [(set (match_operand:DI 0 "arith_reg_operand" "")
2009         (sign_extend:DI (match_operator 4 "binary_logical_operator"
2010                           [(match_operand 1 "any_register_operand" "")
2011                            (match_operand 2 "any_register_operand" "")])))]
2012   "TARGET_SHMEDIA"
2013   [(set (match_dup 5) (match_dup 4))
2014    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
2015 "
2016 {
2017   enum machine_mode inmode = GET_MODE (operands[1]);
2018   int offset = 0;
2019
2020   if (GET_CODE (operands[0]) == SUBREG)
2021     {
2022       offset = SUBREG_BYTE (operands[0]);
2023       operands[0] = SUBREG_REG (operands[0]);
2024     }
2025   gcc_assert (GET_CODE (operands[0]) == REG);
2026   if (! TARGET_LITTLE_ENDIAN)
2027     offset += 8 - GET_MODE_SIZE (inmode);
2028   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
2029 }")
2030 \f
2031 ;; -------------------------------------------------------------------------
2032 ;; Shifts and rotates
2033 ;; -------------------------------------------------------------------------
2034
2035 (define_expand "rotldi3"
2036   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2037         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
2038                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
2039   "TARGET_SHMEDIA"
2040   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
2041
2042 (define_insn "rotldi3_mextr"
2043   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2044         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
2045                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
2046   "TARGET_SHMEDIA"
2047   "*
2048 {
2049   static char templ[16];
2050
2051   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
2052            8 - (int) (INTVAL (operands[2]) >> 3));
2053   return templ;
2054 }"
2055   [(set_attr "type" "arith_media")])
2056
2057 (define_expand "rotrdi3"
2058   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2059         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
2060                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
2061   "TARGET_SHMEDIA"
2062   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
2063
2064 (define_insn "rotrdi3_mextr"
2065   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2066         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
2067                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
2068   "TARGET_SHMEDIA"
2069   "*
2070 {
2071   static char templ[16];
2072
2073   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
2074   return templ;
2075 }"
2076   [(set_attr "type" "arith_media")])
2077
2078 (define_insn "rotlsi3_1"
2079   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2080         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
2081                    (const_int 1)))
2082    (set (reg:SI T_REG)
2083         (lshiftrt:SI (match_dup 1) (const_int 31)))]
2084   "TARGET_SH1"
2085   "rotl %0"
2086   [(set_attr "type" "arith")])
2087
2088 (define_insn "rotlsi3_31"
2089   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2090         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
2091                    (const_int 31)))
2092    (clobber (reg:SI T_REG))]
2093   "TARGET_SH1"
2094   "rotr %0"
2095   [(set_attr "type" "arith")])
2096
2097 (define_insn "rotlsi3_16"
2098   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2099         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
2100                    (const_int 16)))]
2101   "TARGET_SH1"
2102   "swap.w       %1,%0"
2103   [(set_attr "type" "arith")])
2104
2105 (define_expand "rotlsi3"
2106   [(set (match_operand:SI 0 "arith_reg_operand" "")
2107         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
2108                    (match_operand:SI 2 "immediate_operand" "")))]
2109   "TARGET_SH1"
2110   "
2111 {
2112   static const char rot_tab[] = {
2113     000, 000, 000, 000, 000, 000, 010, 001,
2114     001, 001, 011, 013, 003, 003, 003, 003,
2115     003, 003, 003, 003, 003, 013, 012, 002,
2116     002, 002, 010, 000, 000, 000, 000, 000,
2117   };
2118
2119   int count, choice;
2120
2121   if (GET_CODE (operands[2]) != CONST_INT)
2122     FAIL;
2123   count = INTVAL (operands[2]);
2124   choice = rot_tab[count];
2125   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
2126     FAIL;
2127   choice &= 7;
2128   switch (choice)
2129     {
2130     case 0:
2131       emit_move_insn (operands[0], operands[1]);
2132       count -= (count & 16) * 2;
2133       break;
2134     case 3:
2135      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
2136      count -= 16;
2137      break;
2138     case 1:
2139     case 2:
2140       {
2141         rtx parts[2];
2142         parts[0] = gen_reg_rtx (SImode);
2143         parts[1] = gen_reg_rtx (SImode);
2144         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
2145         emit_move_insn (parts[choice-1], operands[1]);
2146         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
2147         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
2148         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
2149         count = (count & ~16) - 8;
2150       }
2151     }
2152
2153   for (; count > 0; count--)
2154     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
2155   for (; count < 0; count++)
2156     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
2157
2158   DONE;
2159 }")
2160
2161 (define_insn "*rotlhi3_8"
2162   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2163         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
2164                    (const_int 8)))]
2165   "TARGET_SH1"
2166   "swap.b       %1,%0"
2167   [(set_attr "type" "arith")])
2168
2169 (define_expand "rotlhi3"
2170   [(set (match_operand:HI 0 "arith_reg_operand" "")
2171         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
2172                    (match_operand:HI 2 "immediate_operand" "")))]
2173   "TARGET_SH1"
2174   "
2175 {
2176   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
2177     FAIL;
2178 }")
2179
2180 ;;
2181 ;; shift left
2182
2183 (define_insn "ashlsi3_sh2a"
2184   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2185         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
2186                    (match_operand:SI 2 "arith_reg_operand" "r")))]
2187   "TARGET_SH2A"
2188   "shad %2,%0"
2189   [(set_attr "type" "arith")
2190    (set_attr "length" "4")])
2191
2192 ;; This pattern is used by init_expmed for computing the costs of shift
2193 ;; insns.
2194
2195 (define_insn_and_split "ashlsi3_std"
2196   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r,r,r")
2197         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
2198                    (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
2199    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
2200   "TARGET_SH3
2201    || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
2202        && CONST_OK_FOR_P27 (INTVAL (operands[2])))"
2203   "@
2204    shld %2,%0
2205    add  %0,%0
2206    shll%O2      %0
2207    #"
2208   "TARGET_SH3
2209    && reload_completed
2210    && GET_CODE (operands[2]) == CONST_INT
2211    && ! CONST_OK_FOR_P27 (INTVAL (operands[2]))"
2212   [(set (match_dup 3) (match_dup 2))
2213    (parallel
2214     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
2215      (clobber (match_dup 4))])]
2216   "operands[4] = gen_rtx_SCRATCH (SImode);"
2217   [(set_attr "length" "*,*,*,4")
2218    (set_attr "type" "dyn_shift,arith,arith,arith")])
2219
2220 (define_insn "ashlhi3_k"
2221   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
2222         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
2223                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
2224   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))"
2225   "@
2226         add     %0,%0
2227         shll%O2 %0"
2228   [(set_attr "type" "arith")])
2229
2230 (define_insn "ashlsi3_n"
2231   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2232         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
2233                    (match_operand:SI 2 "const_int_operand" "n")))
2234    (clobber (reg:SI T_REG))]
2235   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2236   "#"
2237   [(set (attr "length")
2238         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2239                (const_string "2")
2240                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2241                (const_string "4")
2242                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2243                (const_string "6")]
2244               (const_string "8")))
2245    (set_attr "type" "arith")])
2246
2247 (define_split
2248   [(set (match_operand:SI 0 "arith_reg_operand" "")
2249         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2250                    (match_operand:SI 2 "const_int_operand" "")))
2251    (clobber (reg:SI T_REG))]
2252   "TARGET_SH1 && reload_completed"
2253   [(use (reg:SI R0_REG))]
2254   "
2255 {
2256   gen_shifty_op (ASHIFT, operands);
2257   DONE;
2258 }")
2259
2260 (define_insn "ashlsi3_media"
2261   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2262         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2263                    (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2264   "TARGET_SHMEDIA"
2265   "@
2266         shlld.l %1, %2, %0
2267         shlli.l %1, %2, %0"
2268   [(set_attr "type" "arith_media")])
2269
2270 (define_expand "ashlsi3"
2271   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2272                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2273                               (match_operand:SI 2 "nonmemory_operand" "")))
2274               (clobber (reg:SI T_REG))])]
2275   ""
2276   "
2277 {
2278   if (TARGET_SHMEDIA)
2279     {
2280       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
2281       DONE;
2282     }
2283   if (GET_CODE (operands[2]) == CONST_INT
2284       && sh_dynamicalize_shift_p (operands[2]))
2285     operands[2] = force_reg (SImode, operands[2]);
2286   if (TARGET_SH3)
2287     {
2288       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
2289       DONE;
2290     }
2291   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2292     FAIL;
2293 }")
2294
2295 (define_insn "*ashlhi3_n"
2296   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2297         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
2298                    (match_operand:HI 2 "const_int_operand" "n")))
2299    (clobber (reg:SI T_REG))]
2300   "TARGET_SH1"
2301   "#"
2302   [(set (attr "length")
2303         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2304                (const_string "2")
2305                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2306                (const_string "4")]
2307               (const_string "6")))
2308    (set_attr "type" "arith")])
2309
2310 (define_expand "ashlhi3"
2311   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
2312                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
2313                               (match_operand:SI 2 "nonmemory_operand" "")))
2314               (clobber (reg:SI T_REG))])]
2315   "TARGET_SH1"
2316   "
2317 {
2318   if (GET_CODE (operands[2]) != CONST_INT)
2319     FAIL;
2320   /* It may be possible to call gen_ashlhi3 directly with more generic
2321      operands.  Make sure operands[1] is a HImode register here.  */
2322   if (!arith_reg_operand (operands[1], HImode))
2323     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2324 }")
2325
2326 (define_split
2327   [(set (match_operand:HI 0 "arith_reg_operand" "")
2328         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
2329                    (match_operand:HI 2 "const_int_operand" "")))
2330    (clobber (reg:SI T_REG))]
2331   "TARGET_SH1 && reload_completed"
2332   [(use (reg:SI R0_REG))]
2333   "
2334 {
2335   gen_shifty_hi_op (ASHIFT, operands);
2336   DONE;
2337 }")
2338
2339 ;
2340 ; arithmetic shift right
2341 ;
2342
2343 (define_insn "ashrsi3_sh2a"
2344   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2345         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2346                    (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2347   "TARGET_SH2A"
2348   "shad %2,%0"
2349   [(set_attr "type" "dyn_shift")
2350    (set_attr "length" "4")])
2351
2352 (define_insn "ashrsi3_k"
2353   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2354         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2355                      (match_operand:SI 2 "const_int_operand" "M")))
2356    (clobber (reg:SI T_REG))]
2357   "TARGET_SH1 && INTVAL (operands[2]) == 1"
2358   "shar %0"
2359   [(set_attr "type" "arith")])
2360
2361 ;; We can't do HImode right shifts correctly unless we start out with an
2362 ;; explicit zero / sign extension; doing that would result in worse overall
2363 ;; code, so just let the machine independent code widen the mode.
2364 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
2365
2366
2367 ;; ??? This should be a define expand.
2368
2369 (define_insn "ashrsi2_16"
2370   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2371         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
2372                      (const_int 16)))]
2373   "TARGET_SH1"
2374   "#"
2375   [(set_attr "length" "4")])
2376
2377 (define_split
2378   [(set (match_operand:SI 0 "arith_reg_operand" "")
2379         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2380                      (const_int 16)))]
2381   "TARGET_SH1"
2382   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
2383    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2384   "operands[2] = gen_lowpart (HImode, operands[0]);")
2385
2386 ;; ??? This should be a define expand.
2387
2388 (define_insn "ashrsi2_31"
2389   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2390         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2391                      (const_int 31)))
2392    (clobber (reg:SI T_REG))]
2393   "TARGET_SH1"
2394   "#"
2395   [(set_attr "length" "4")])
2396
2397 (define_split
2398   [(set (match_operand:SI 0 "arith_reg_operand" "")
2399         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2400                      (const_int 31)))
2401    (clobber (reg:SI T_REG))]
2402   "TARGET_SH1"
2403   [(const_int 0)]
2404   "
2405 {
2406   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
2407   emit_insn (gen_subc1 (operands[0], operands[0], operands[0]));
2408   DONE;
2409 }")
2410
2411 (define_insn "ashlsi_c"
2412   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2413         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
2414    (set (reg:SI T_REG)
2415         (lt:SI (match_dup 1) (const_int 0)))]
2416   "TARGET_SH1"
2417   "shll %0"
2418   [(set_attr "type" "arith")])
2419
2420 (define_insn "ashrsi3_d"
2421   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2422         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2423                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2424   "TARGET_SH3"
2425   "shad %2,%0"
2426   [(set_attr "type" "dyn_shift")])
2427
2428 (define_insn "ashrsi3_n"
2429   [(set (reg:SI R4_REG)
2430         (ashiftrt:SI (reg:SI R4_REG)
2431                      (match_operand:SI 0 "const_int_operand" "i")))
2432    (clobber (reg:SI T_REG))
2433    (clobber (reg:SI PR_REG))
2434    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2435   "TARGET_SH1"
2436   "jsr  @%1%#"
2437   [(set_attr "type" "sfunc")
2438    (set_attr "needs_delay_slot" "yes")])
2439
2440 (define_insn "ashrsi3_media"
2441   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2442         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2443                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2444   "TARGET_SHMEDIA"
2445   "@
2446         shard.l %1, %2, %0
2447         shari.l %1, %2, %0"
2448   [(set_attr "type" "arith_media")])
2449
2450 (define_expand "ashrsi3"
2451   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2452                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2453                                 (match_operand:SI 2 "nonmemory_operand" "")))
2454               (clobber (reg:SI T_REG))])]
2455   ""
2456   "
2457 {
2458   if (TARGET_SHMEDIA)
2459     {
2460       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
2461       DONE;
2462     }
2463   if (expand_ashiftrt (operands))
2464     DONE;
2465   else
2466     FAIL;
2467 }")
2468
2469 ;; logical shift right
2470
2471 (define_insn "lshrsi3_sh2a"
2472   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2473         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2474                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2475   "TARGET_SH2A"
2476   "shld %2,%0"
2477   [(set_attr "type" "dyn_shift")
2478    (set_attr "length" "4")])
2479
2480 (define_insn "lshrsi3_d"
2481   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2482         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2483                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2484   "TARGET_SH3"
2485   "shld %2,%0"
2486   [(set_attr "type" "dyn_shift")])
2487
2488 ;;  Only the single bit shift clobbers the T bit.
2489
2490 (define_insn "lshrsi3_m"
2491   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2492         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2493                      (match_operand:SI 2 "const_int_operand" "M")))
2494    (clobber (reg:SI T_REG))]
2495   "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
2496   "shlr %0"
2497   [(set_attr "type" "arith")])
2498
2499 (define_insn "lshrsi3_k"
2500   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2501         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2502                      (match_operand:SI 2 "const_int_operand" "P27")))]
2503   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))
2504    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
2505   "shlr%O2      %0"
2506   [(set_attr "type" "arith")])
2507
2508 (define_insn "lshrsi3_n"
2509   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2510         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2511                      (match_operand:SI 2 "const_int_operand" "n")))
2512    (clobber (reg:SI T_REG))]
2513   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2514   "#"
2515   [(set (attr "length")
2516         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2517                (const_string "2")
2518                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2519                (const_string "4")
2520                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2521                (const_string "6")]
2522               (const_string "8")))
2523    (set_attr "type" "arith")])
2524
2525 (define_split
2526   [(set (match_operand:SI 0 "arith_reg_operand" "")
2527         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2528                      (match_operand:SI 2 "const_int_operand" "")))
2529    (clobber (reg:SI T_REG))]
2530   "TARGET_SH1 && reload_completed"
2531   [(use (reg:SI R0_REG))]
2532   "
2533 {
2534   gen_shifty_op (LSHIFTRT, operands);
2535   DONE;
2536 }")
2537
2538 (define_insn "lshrsi3_media"
2539   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2540         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2541                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2542   "TARGET_SHMEDIA"
2543   "@
2544         shlrd.l %1, %2, %0
2545         shlri.l %1, %2, %0"
2546   [(set_attr "type" "arith_media")])
2547
2548 (define_expand "lshrsi3"
2549   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2550                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2551                                 (match_operand:SI 2 "nonmemory_operand" "")))
2552               (clobber (reg:SI T_REG))])]
2553   ""
2554   "
2555 {
2556   if (TARGET_SHMEDIA)
2557     {
2558       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
2559       DONE;
2560     }
2561   if (GET_CODE (operands[2]) == CONST_INT
2562       && sh_dynamicalize_shift_p (operands[2]))
2563     operands[2] = force_reg (SImode, operands[2]);
2564   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
2565     {
2566       rtx count = copy_to_mode_reg (SImode, operands[2]);
2567       emit_insn (gen_negsi2 (count, count));
2568       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
2569       DONE;
2570     }
2571   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2572     FAIL;
2573 }")
2574
2575 ;; ??? This should be a define expand.
2576
2577 (define_insn "ashldi3_k"
2578   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2579         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
2580                    (const_int 1)))
2581    (clobber (reg:SI T_REG))]
2582   "TARGET_SH1"
2583   "shll %R0\;rotcl      %S0"
2584   [(set_attr "length" "4")
2585    (set_attr "type" "arith")])
2586
2587 (define_insn "ashldi3_media"
2588   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2589         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2590                    (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2591   "TARGET_SHMEDIA"
2592   "@
2593         shlld   %1, %2, %0
2594         shlli   %1, %2, %0"
2595   [(set_attr "type" "arith_media")])
2596
2597 (define_expand "ashldi3"
2598   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2599                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
2600                               (match_operand:DI 2 "immediate_operand" "")))
2601               (clobber (reg:SI T_REG))])]
2602   ""
2603   "
2604 {
2605   if (TARGET_SHMEDIA)
2606     {
2607       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
2608       DONE;
2609     }
2610   if (GET_CODE (operands[2]) != CONST_INT
2611       || INTVAL (operands[2]) != 1)
2612     FAIL;
2613 }")
2614
2615 ;; ??? This should be a define expand.
2616
2617 (define_insn "lshrdi3_k"
2618   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2619         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2620                      (const_int 1)))
2621    (clobber (reg:SI T_REG))]
2622   "TARGET_SH1"
2623   "shlr %S0\;rotcr      %R0"
2624   [(set_attr "length" "4")
2625    (set_attr "type" "arith")])
2626
2627 (define_insn "lshrdi3_media"
2628   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2629         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2630                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2631   "TARGET_SHMEDIA"
2632   "@
2633         shlrd   %1, %2, %0
2634         shlri   %1, %2, %0"
2635   [(set_attr "type" "arith_media")])
2636
2637 (define_expand "lshrdi3"
2638   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2639                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2640                                (match_operand:DI 2 "immediate_operand" "")))
2641              (clobber (reg:SI T_REG))])]
2642   ""
2643   "
2644 {
2645   if (TARGET_SHMEDIA)
2646     {
2647       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
2648       DONE;
2649     }
2650   if (GET_CODE (operands[2]) != CONST_INT
2651       || INTVAL (operands[2]) != 1)
2652     FAIL;
2653 }")
2654
2655 ;; ??? This should be a define expand.
2656
2657 (define_insn "ashrdi3_k"
2658   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2659         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2660                      (const_int 1)))
2661    (clobber (reg:SI T_REG))]
2662   "TARGET_SH1"
2663   "shar %S0\;rotcr      %R0"
2664   [(set_attr "length" "4")
2665    (set_attr "type" "arith")])
2666
2667 (define_insn "ashrdi3_media"
2668   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2669         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2670                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2671   "TARGET_SHMEDIA"
2672   "@
2673         shard   %1, %2, %0
2674         shari   %1, %2, %0"
2675   [(set_attr "type" "arith_media")])
2676
2677 (define_expand "ashrdi3"
2678   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2679                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2680                                 (match_operand:DI 2 "immediate_operand" "")))
2681               (clobber (reg:SI T_REG))])]
2682   ""
2683   "
2684 {
2685   if (TARGET_SHMEDIA)
2686     {
2687       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
2688       DONE;
2689     }
2690   if (GET_CODE (operands[2]) != CONST_INT
2691       || INTVAL (operands[2]) != 1)
2692     FAIL;
2693 }")
2694
2695 ;; combined left/right shift
2696
2697 (define_split
2698   [(set (match_operand:SI 0 "register_operand" "")
2699         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2700                            (match_operand:SI 2 "const_int_operand" ""))
2701                 (match_operand:SI 3 "const_int_operand" "")))]
2702   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
2703   [(use (reg:SI R0_REG))]
2704   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2705    DONE;")
2706
2707 (define_split
2708   [(set (match_operand:SI 0 "register_operand" "")
2709         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2710                            (match_operand:SI 2 "const_int_operand" ""))
2711                 (match_operand:SI 3 "const_int_operand" "")))
2712    (clobber (reg:SI T_REG))]
2713   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
2714   [(use (reg:SI R0_REG))]
2715   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2716    DONE;")
2717
2718 (define_insn ""
2719   [(set (match_operand:SI 0 "register_operand" "=r")
2720         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2721                            (match_operand:SI 2 "const_int_operand" "n"))
2722                 (match_operand:SI 3 "const_int_operand" "n")))
2723    (clobber (reg:SI T_REG))]
2724   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
2725  "#"
2726   [(set (attr "length")
2727         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2728                (const_string "4")
2729                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2730                (const_string "6")
2731                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2732                (const_string "8")
2733                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
2734                (const_string "10")
2735                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
2736                (const_string "12")
2737                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
2738                (const_string "14")
2739                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
2740                (const_string "16")]
2741               (const_string "18")))
2742    (set_attr "type" "arith")])
2743
2744 (define_insn ""
2745   [(set (match_operand:SI 0 "register_operand" "=z")
2746         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2747                            (match_operand:SI 2 "const_int_operand" "n"))
2748                 (match_operand:SI 3 "const_int_operand" "n")))
2749    (clobber (reg:SI T_REG))]
2750   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
2751  "#"
2752   [(set (attr "length")
2753         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2754                (const_string "4")
2755                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2756                (const_string "6")
2757                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2758                (const_string "8")]
2759               (const_string "10")))
2760    (set_attr "type" "arith")])
2761
2762 ;; shift left / and combination with a scratch register: The combine pass
2763 ;; does not accept the individual instructions, even though they are
2764 ;; cheap.  But it needs a precise description so that it is usable after
2765 ;; reload.
2766 (define_insn "and_shl_scratch"
2767   [(set (match_operand:SI 0 "register_operand" "=r,&r")
2768         (lshiftrt:SI
2769          (ashift:SI
2770           (and:SI
2771            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
2772                         (match_operand:SI 2 "const_int_operand" "N,n"))
2773            (match_operand:SI 3 "" "0,r"))
2774           (match_operand:SI 4 "const_int_operand" "n,n"))
2775          (match_operand:SI 5 "const_int_operand" "n,n")))
2776    (clobber (reg:SI T_REG))]
2777   "TARGET_SH1"
2778   "#"
2779   [(set (attr "length")
2780         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
2781                (const_string "4")
2782                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
2783                (const_string "6")
2784                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
2785                (const_string "8")
2786                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
2787                (const_string "10")]
2788               (const_string "12")))
2789    (set_attr "type" "arith")])
2790
2791 (define_split
2792   [(set (match_operand:SI 0 "register_operand" "")
2793         (lshiftrt:SI
2794          (ashift:SI
2795           (and:SI
2796            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
2797                         (match_operand:SI 2 "const_int_operand" ""))
2798            (match_operand:SI 3 "register_operand" ""))
2799           (match_operand:SI 4 "const_int_operand" ""))
2800          (match_operand:SI 5 "const_int_operand" "")))
2801    (clobber (reg:SI T_REG))]
2802   "TARGET_SH1"
2803   [(use (reg:SI R0_REG))]
2804   "
2805 {
2806   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
2807
2808   if (INTVAL (operands[2]))
2809     {
2810       gen_shifty_op (LSHIFTRT, operands);
2811     }
2812   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
2813   operands[2] = operands[4];
2814   gen_shifty_op (ASHIFT, operands);
2815   if (INTVAL (operands[5]))
2816     {
2817       operands[2] = operands[5];
2818       gen_shifty_op (LSHIFTRT, operands);
2819     }
2820   DONE;
2821 }")
2822
2823 ;; signed left/right shift combination.
2824 (define_split
2825   [(set (match_operand:SI 0 "register_operand" "")
2826         (sign_extract:SI
2827          (ashift:SI (match_operand:SI 1 "register_operand" "")
2828                     (match_operand:SI 2 "const_int_operand" ""))
2829          (match_operand:SI 3 "const_int_operand" "")
2830          (const_int 0)))
2831    (clobber (reg:SI T_REG))]
2832   "TARGET_SH1"
2833   [(use (reg:SI R0_REG))]
2834   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
2835    DONE;")
2836
2837 (define_insn "shl_sext_ext"
2838   [(set (match_operand:SI 0 "register_operand" "=r")
2839         (sign_extract:SI
2840          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2841                     (match_operand:SI 2 "const_int_operand" "n"))
2842          (match_operand:SI 3 "const_int_operand" "n")
2843          (const_int 0)))
2844    (clobber (reg:SI T_REG))]
2845   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
2846   "#"
2847   [(set (attr "length")
2848         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
2849                (const_string "2")
2850                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
2851                (const_string "4")
2852                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2853                (const_string "6")
2854                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2855                (const_string "8")
2856                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2857                (const_string "10")
2858                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2859                (const_string "12")
2860                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
2861                (const_string "14")
2862                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
2863                (const_string "16")]
2864               (const_string "18")))
2865     (set_attr "type" "arith")])
2866
2867 (define_insn "shl_sext_sub"
2868   [(set (match_operand:SI 0 "register_operand" "=z")
2869         (sign_extract:SI
2870          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2871                     (match_operand:SI 2 "const_int_operand" "n"))
2872          (match_operand:SI 3 "const_int_operand" "n")
2873          (const_int 0)))
2874    (clobber (reg:SI T_REG))]
2875   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
2876   "#"
2877   [(set (attr "length")
2878         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2879                (const_string "6")
2880                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2881                (const_string "8")
2882                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2883                (const_string "10")
2884                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2885                (const_string "12")]
2886               (const_string "14")))
2887     (set_attr "type" "arith")])
2888
2889 ;; These patterns are found in expansions of DImode shifts by 16, and
2890 ;; allow the xtrct instruction to be generated from C source.
2891
2892 (define_insn "xtrct_left"
2893   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2894         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
2895                            (const_int 16))
2896                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
2897                              (const_int 16))))]
2898   "TARGET_SH1"
2899   "xtrct        %1,%0"
2900   [(set_attr "type" "arith")])
2901
2902 (define_insn "xtrct_right"
2903   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2904         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2905                              (const_int 16))
2906                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
2907                            (const_int 16))))]
2908   "TARGET_SH1"
2909   "xtrct        %2,%0"
2910   [(set_attr "type" "arith")])
2911
2912 ;; -------------------------------------------------------------------------
2913 ;; Unary arithmetic
2914 ;; -------------------------------------------------------------------------
2915
2916 (define_insn "negc"
2917   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2918         (neg:SI (plus:SI (reg:SI T_REG)
2919                          (match_operand:SI 1 "arith_reg_operand" "r"))))
2920    (set (reg:SI T_REG)
2921         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
2922                (const_int 0)))]
2923   "TARGET_SH1"
2924   "negc %1,%0"
2925   [(set_attr "type" "arith")])
2926
2927 (define_insn "*negdi_media"
2928   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2929         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
2930   "TARGET_SHMEDIA"
2931   "sub  r63, %1, %0"
2932   [(set_attr "type" "arith_media")])
2933
2934 (define_expand "negdi2"
2935   [(set (match_operand:DI 0 "arith_reg_operand" "")
2936         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
2937   ""
2938   "
2939 {
2940   if (TARGET_SH1)
2941     {
2942       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
2943       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
2944
2945       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
2946       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
2947
2948       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
2949       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
2950
2951       emit_insn (gen_clrt ());
2952       emit_insn (gen_negc (low_dst, low_src));
2953       emit_insn (gen_negc (high_dst, high_src));
2954       DONE;
2955     }
2956 }")
2957
2958 (define_insn "negsi2"
2959   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2960         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2961   "TARGET_SH1"
2962   "neg  %1,%0"
2963   [(set_attr "type" "arith")])
2964
2965 (define_insn "one_cmplsi2"
2966   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2967         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2968   "TARGET_SH1"
2969   "not  %1,%0"
2970   [(set_attr "type" "arith")])
2971
2972 (define_expand "one_cmpldi2"
2973   [(set (match_operand:DI 0 "arith_reg_operand" "")
2974         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
2975                 (const_int -1)))]
2976   "TARGET_SHMEDIA" "")
2977 \f
2978 ;; -------------------------------------------------------------------------
2979 ;; Zero extension instructions
2980 ;; -------------------------------------------------------------------------
2981
2982 (define_insn "zero_extendsidi2"
2983   [(set (match_operand:DI 0 "register_operand" "=r")
2984         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
2985   "TARGET_SHMEDIA"
2986   "addz.l       %1, r63, %0"
2987   [(set_attr "type" "arith_media")])
2988
2989 (define_insn "zero_extendhidi2"
2990   [(set (match_operand:DI 0 "register_operand" "=r,r")
2991         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
2992   "TARGET_SHMEDIA"
2993   "@
2994         #
2995         ld%M1.uw        %m1, %0"
2996   [(set_attr "type" "*,load_media")])
2997
2998 (define_split
2999   [(set (match_operand:DI 0 "register_operand" "")
3000         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
3001   "TARGET_SHMEDIA && reload_completed"
3002   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
3003    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
3004   "
3005 {
3006   if (GET_CODE (operands[1]) == TRUNCATE)
3007     operands[1] = XEXP (operands[1], 0);
3008 }")
3009
3010 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
3011 ;; reload the entire truncate expression.
3012 (define_insn_and_split "*loaddi_trunc"
3013   [(set (match_operand 0 "int_gpr_dest" "=r")
3014         (truncate (match_operand:DI 1 "memory_operand" "m")))]
3015   "TARGET_SHMEDIA && reload_completed"
3016   "#"
3017   "TARGET_SHMEDIA && reload_completed"
3018   [(set (match_dup 0) (match_dup 1))]
3019   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
3020
3021 (define_insn "zero_extendqidi2"
3022   [(set (match_operand:DI 0 "register_operand" "=r,r")
3023         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3024   "TARGET_SHMEDIA"
3025   "@
3026         andi    %1, 255, %0
3027         ld%M1.ub        %m1, %0"
3028   [(set_attr "type" "arith_media,load_media")])
3029
3030 (define_expand "zero_extendhisi2"
3031   [(set (match_operand:SI 0 "arith_reg_operand" "")
3032         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
3033   ""
3034   "
3035 {
3036   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
3037     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3038 }")
3039
3040 (define_insn "*zero_extendhisi2_compact"
3041   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3042         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
3043   "TARGET_SH1"
3044   "extu.w       %1,%0"
3045   [(set_attr "type" "arith")])
3046
3047 (define_insn "*zero_extendhisi2_media"
3048   [(set (match_operand:SI 0 "register_operand" "=r,r")
3049         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3050   "TARGET_SHMEDIA"
3051   "@
3052         #
3053         ld%M1.uw        %m1, %0"
3054   [(set_attr "type" "arith_media,load_media")])
3055
3056 (define_split
3057   [(set (match_operand:SI 0 "register_operand" "")
3058         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
3059   "TARGET_SHMEDIA && reload_completed"
3060   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16)))
3061    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
3062   "
3063 {
3064   if (GET_CODE (operands[1]) == TRUNCATE)
3065     operands[1] = XEXP (operands[1], 0);
3066 }")
3067
3068 (define_expand "zero_extendqisi2"
3069   [(set (match_operand:SI 0 "arith_reg_operand" "")
3070         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
3071   ""
3072   "
3073 {
3074   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
3075     operands[1] = copy_to_mode_reg (QImode, operands[1]);
3076 }")
3077
3078 (define_insn "*zero_extendqisi2_compact"
3079   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3080         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
3081   "TARGET_SH1"
3082   "extu.b       %1,%0"
3083   [(set_attr "type" "arith")])
3084
3085 (define_insn "*zero_extendqisi2_media"
3086   [(set (match_operand:SI 0 "register_operand" "=r,r")
3087         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3088   "TARGET_SHMEDIA"
3089   "@
3090         andi    %1, 255, %0
3091         ld%M1.ub        %m1, %0"
3092   [(set_attr "type" "arith_media,load_media")])
3093
3094 (define_insn "zero_extendqihi2"
3095   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
3096         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
3097   "TARGET_SH1"
3098   "extu.b       %1,%0"
3099   [(set_attr "type" "arith")])
3100
3101 ;; -------------------------------------------------------------------------
3102 ;; Sign extension instructions
3103 ;; -------------------------------------------------------------------------
3104
3105 ;; ??? This should be a define expand.
3106 ;; ??? Or perhaps it should be dropped?
3107
3108 ;; convert_move generates good code for SH[1-4].
3109 (define_insn "extendsidi2"
3110   [(set (match_operand:DI 0 "register_operand" "=r,r")
3111         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
3112   "TARGET_SHMEDIA"
3113   "@
3114         add.l   %1, r63, %0
3115         ld%M1.l %m1, %0"
3116   [(set_attr "type" "arith_media,load_media")])
3117
3118 (define_insn "extendhidi2"
3119   [(set (match_operand:DI 0 "register_operand" "=r,r")
3120         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3121   "TARGET_SHMEDIA"
3122   "@
3123         #
3124         ld%M1.w %m1, %0"
3125   [(set_attr "type" "*,load_media")])
3126
3127 (define_split
3128   [(set (match_operand:DI 0 "register_operand" "")
3129         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
3130   "TARGET_SHMEDIA && reload_completed"
3131   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
3132    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
3133   "
3134 {
3135   if (GET_CODE (operands[1]) == TRUNCATE)
3136     operands[1] = XEXP (operands[1], 0);
3137 }")
3138
3139 (define_insn "extendqidi2"
3140   [(set (match_operand:DI 0 "register_operand" "=r,r")
3141         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3142   "TARGET_SHMEDIA"
3143   "@
3144         #
3145         ld%M1.b %m1, %0"
3146   [(set_attr "type" "*,load_media")])
3147
3148 (define_split
3149   [(set (match_operand:DI 0 "register_operand" "")
3150         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
3151   "TARGET_SHMEDIA && reload_completed"
3152   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
3153    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
3154   "
3155 {
3156   if (GET_CODE (operands[1]) == TRUNCATE)
3157     operands[1] = XEXP (operands[1], 0);
3158 }")
3159
3160 (define_expand "extendhisi2"
3161   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3162         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3163   ""
3164   "")
3165
3166 (define_insn "*extendhisi2_compact"
3167   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3168         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
3169   "TARGET_SH1"
3170   "@
3171         exts.w  %1,%0
3172         mov.w   %1,%0"
3173   [(set_attr "type" "arith,load")])
3174
3175 (define_insn "*extendhisi2_media"
3176   [(set (match_operand:SI 0 "register_operand" "=r,r")
3177         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3178   "TARGET_SHMEDIA"
3179   "@
3180         #
3181         ld%M1.w %m1, %0"
3182   [(set_attr "type" "arith_media,load_media")])
3183
3184 (define_split
3185   [(set (match_operand:SI 0 "register_operand" "")
3186         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
3187   "TARGET_SHMEDIA && reload_completed"
3188   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16)))
3189    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
3190   "
3191 {
3192   if (GET_CODE (operands[1]) == TRUNCATE)
3193     operands[1] = XEXP (operands[1], 0);
3194 }")
3195
3196 (define_expand "extendqisi2"
3197   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3198         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3199   ""
3200   "")
3201
3202 (define_insn "*extendqisi2_compact"
3203   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3204         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
3205   "TARGET_SH1"
3206   "@
3207         exts.b  %1,%0
3208         mov.b   %1,%0"
3209   [(set_attr "type" "arith,load")])
3210
3211 (define_insn "*extendqisi2_media"
3212   [(set (match_operand:SI 0 "register_operand" "=r,r")
3213         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3214   "TARGET_SHMEDIA"
3215   "@
3216         #
3217         ld%M1.b %m1, %0"
3218   [(set_attr "type" "arith_media,load_media")])
3219
3220 (define_split
3221   [(set (match_operand:SI 0 "register_operand" "")
3222         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
3223   "TARGET_SHMEDIA && reload_completed"
3224   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 24)))
3225    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
3226    "
3227 {
3228   if (GET_CODE (operands[1]) == TRUNCATE)
3229     operands[1] = XEXP (operands[1], 0);
3230 }")
3231
3232 (define_insn "extendqihi2"
3233   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
3234         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
3235   "TARGET_SH1"
3236   "@
3237         exts.b  %1,%0
3238         mov.b   %1,%0"
3239   [(set_attr "type" "arith,load")])
3240
3241 /* It would seem useful to combine the truncXi patterns into the movXi
3242    patterns, but unary operators are ignored when matching constraints,
3243    so we need separate patterns.  */
3244 (define_insn "truncdisi2"
3245   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
3246         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
3247   "TARGET_SHMEDIA"
3248   "@
3249         add.l   %1, r63, %0
3250         st%M0.l %m0, %1
3251         fst%M0.s        %m0, %T1
3252         fmov.ls %1, %0
3253         fmov.sl %T1, %0
3254         fmov.s  %T1, %0"
3255   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")])
3256
3257
3258 (define_insn "truncdihi2"
3259   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
3260         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
3261   "TARGET_SHMEDIA"
3262   "@
3263         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
3264         st%M0.w %m0, %1"
3265   [(set_attr "type"   "arith_media,store_media")
3266    (set_attr "length" "8,4")])
3267
3268 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
3269 ; Because we use zero extension, we can't provide signed QImode compares
3270 ; using a simple compare or conditional banch insn.
3271 (define_insn "truncdiqi2"
3272   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
3273         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
3274   "TARGET_SHMEDIA"
3275   "@
3276         andi    %1, 255, %0
3277         st%M0.b %m0, %1"
3278   [(set_attr "type"   "arith_media,store")])
3279
3280 ;; -------------------------------------------------------------------------
3281 ;; Move instructions
3282 ;; -------------------------------------------------------------------------
3283
3284 ;; define push and pop so it is easy for sh.c
3285 ;; We can't use push and pop on SHcompact because the stack must always
3286 ;; be 8-byte aligned.
3287
3288 (define_expand "push"
3289   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
3290         (match_operand:SI 0 "register_operand" "r,l,x"))]
3291   "TARGET_SH1 && ! TARGET_SH5"
3292   "")
3293
3294 (define_expand "pop"
3295   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
3296         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
3297   "TARGET_SH1 && ! TARGET_SH5"
3298   "")
3299
3300 (define_expand "push_e"
3301   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
3302                    (match_operand:SF 0 "" ""))
3303               (use (reg:PSI FPSCR_REG))
3304               (clobber (scratch:SI))])]
3305   "TARGET_SH1 && ! TARGET_SH5"
3306   "")
3307
3308 (define_insn "push_fpul"
3309   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
3310   "TARGET_SH2E && ! TARGET_SH5"
3311   "sts.l        fpul,@-r15"
3312   [(set_attr "type" "store")
3313    (set_attr "late_fp_use" "yes")
3314    (set_attr "hit_stack" "yes")])
3315
3316 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
3317 ;; so use that.
3318 (define_expand "push_4"
3319   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
3320                    (match_operand:DF 0 "" ""))
3321               (use (reg:PSI FPSCR_REG))
3322               (clobber (scratch:SI))])]
3323   "TARGET_SH1 && ! TARGET_SH5"
3324   "")
3325
3326 (define_expand "pop_e"
3327   [(parallel [(set (match_operand:SF 0 "" "")
3328               (mem:SF (post_inc:SI (reg:SI SP_REG))))
3329               (use (reg:PSI FPSCR_REG))
3330               (clobber (scratch:SI))])]
3331   "TARGET_SH1 && ! TARGET_SH5"
3332   "")
3333
3334 (define_insn "pop_fpul"
3335   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
3336   "TARGET_SH2E && ! TARGET_SH5"
3337   "lds.l        @r15+,fpul"
3338   [(set_attr "type" "load")
3339    (set_attr "hit_stack" "yes")])
3340
3341 (define_expand "pop_4"
3342   [(parallel [(set (match_operand:DF 0 "" "")
3343                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
3344               (use (reg:PSI FPSCR_REG))
3345               (clobber (scratch:SI))])]
3346   "TARGET_SH1 && ! TARGET_SH5"
3347   "")
3348
3349 (define_expand "push_fpscr"
3350   [(const_int 0)]
3351   "TARGET_SH2E"
3352   "
3353 {
3354   rtx insn = emit_insn (gen_fpu_switch (gen_rtx_MEM (PSImode,
3355                                                  gen_rtx_PRE_DEC (Pmode,
3356                                                           stack_pointer_rtx)),
3357                                         get_fpscr_rtx ()));
3358   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
3359   DONE;
3360 }")
3361
3362 (define_expand "pop_fpscr"
3363   [(const_int 0)]
3364   "TARGET_SH2E"
3365   "
3366 {
3367   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
3368                                         gen_rtx_MEM (PSImode,
3369                                                  gen_rtx_POST_INC (Pmode,
3370                                                           stack_pointer_rtx))));
3371   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
3372   DONE;
3373 }")
3374
3375 ;; These two patterns can happen as the result of optimization, when
3376 ;; comparisons get simplified to a move of zero or 1 into the T reg.
3377 ;; They don't disappear completely, because the T reg is a fixed hard reg.
3378
3379 (define_insn "clrt"
3380   [(set (reg:SI T_REG) (const_int 0))]
3381   "TARGET_SH1"
3382   "clrt")
3383
3384 (define_insn "sett"
3385   [(set (reg:SI T_REG) (const_int 1))]
3386   "TARGET_SH1"
3387   "sett")
3388
3389 ;; t/r must come after r/r, lest reload will try to reload stuff like
3390 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
3391 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
3392 (define_insn "movsi_i"
3393   [(set (match_operand:SI 0 "general_movdst_operand"
3394             "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
3395         (match_operand:SI 1 "general_movsrc_operand"
3396          "Q,rI08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
3397   "TARGET_SH1
3398    && ! TARGET_SH2E
3399    && ! TARGET_SH2A
3400    && (register_operand (operands[0], SImode)
3401        || register_operand (operands[1], SImode))"
3402   "@
3403         mov.l   %1,%0
3404         mov     %1,%0
3405         cmp/pl  %1
3406         mov.l   %1,%0
3407         sts     %1,%0
3408         sts     %1,%0
3409         movt    %0
3410         mov.l   %1,%0
3411         sts.l   %1,%0
3412         sts.l   %1,%0
3413         lds     %1,%0
3414         lds     %1,%0
3415         lds.l   %1,%0
3416         lds.l   %1,%0
3417         fake    %1,%0"
3418   [(set_attr "type" "pcload_si,move,mt_group,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
3419    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
3420
3421 ;; t/r must come after r/r, lest reload will try to reload stuff like
3422 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
3423 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
3424 ;; will require a reload.
3425 ;; ??? We can't include f/f because we need the proper FPSCR setting when
3426 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
3427 (define_insn "movsi_ie"
3428   [(set (match_operand:SI 0 "general_movdst_operand"
3429             "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
3430         (match_operand:SI 1 "general_movsrc_operand"
3431          "Q,rI08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
3432   "(TARGET_SH2E || TARGET_SH2A)
3433    && (register_operand (operands[0], SImode)
3434        || register_operand (operands[1], SImode))"
3435   "@
3436         mov.l   %1,%0
3437         mov     %1,%0
3438         movi20  %1,%0
3439         cmp/pl  %1
3440         mov.l   %1,%0
3441         sts     %1,%0
3442         sts     %1,%0
3443         movt    %0
3444         mov.l   %1,%0
3445         sts.l   %1,%0
3446         sts.l   %1,%0
3447         lds     %1,%0
3448         lds     %1,%0
3449         lds.l   %1,%0
3450         lds.l   %1,%0
3451         lds.l   %1,%0
3452         sts.l   %1,%0
3453         fake    %1,%0
3454         lds     %1,%0
3455         sts     %1,%0
3456         fsts    fpul,%0
3457         flds    %1,fpul
3458         fmov    %1,%0
3459         ! move optimized away"
3460   [(set_attr "type" "pcload_si,move,move,*,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
3461    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
3462    (set_attr "length" "*,*,4,*,4,*,*,*,4,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
3463
3464 (define_insn "movsi_i_lowpart"
3465   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
3466         (match_operand:SI 1 "general_movsrc_operand" "Q,rI08,mr,x,l,t,r,i"))]
3467    "TARGET_SH1
3468     && (register_operand (operands[0], SImode)
3469         || register_operand (operands[1], SImode))"
3470   "@
3471         mov.l   %1,%0
3472         mov     %1,%0
3473         mov.l   %1,%0
3474         sts     %1,%0
3475         sts     %1,%0
3476         movt    %0
3477         mov.l   %1,%0
3478         fake    %1,%0"
3479   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
3480
3481 (define_insn_and_split "load_ra"
3482   [(set (match_operand:SI 0 "general_movdst_operand" "")
3483         (unspec:SI [(match_operand 1 "register_operand" "")] UNSPEC_RA))]
3484   "TARGET_SH1"
3485   "#"
3486   "&& ! currently_expanding_to_rtl"
3487   [(set (match_dup 0) (match_dup 1))]
3488   "
3489 {
3490   if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
3491     operands[1] = gen_rtx_MEM (SImode, return_address_pointer_rtx);
3492 }")
3493
3494 (define_insn "*movsi_media"
3495   [(set (match_operand:SI 0 "general_movdst_operand"
3496                 "=r,r,r,r,m,f,m,f,r,f,*b,r,b")
3497         (match_operand:SI 1 "general_movsrc_operand"
3498          "r,I16C16,nCpg,m,rZ,m,f,rZ,f,f,r,*b,Csy"))]
3499   "TARGET_SHMEDIA_FPU
3500    && (register_operand (operands[0], SImode)
3501        || sh_register_operand (operands[1], SImode))"
3502   "@
3503         add.l   %1, r63, %0
3504         movi    %1, %0
3505         #
3506         ld%M1.l %m1, %0
3507         st%M0.l %m0, %N1
3508         fld%M1.s        %m1, %0
3509         fst%M0.s        %m0, %1
3510         fmov.ls %N1, %0
3511         fmov.sl %1, %0
3512         fmov.s  %1, %0
3513         ptabs   %1, %0
3514         gettr   %1, %0
3515         pt      %1, %0"
3516   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
3517    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")])
3518
3519 (define_insn "*movsi_media_nofpu"
3520   [(set (match_operand:SI 0 "general_movdst_operand"
3521                 "=r,r,r,r,m,*b,r,b")
3522         (match_operand:SI 1 "general_movsrc_operand"
3523          "r,I16C16,nCpg,m,rZ,r,*b,Csy"))]
3524   "TARGET_SHMEDIA
3525    && (register_operand (operands[0], SImode)
3526        || sh_register_operand (operands[1], SImode))"
3527   "@
3528         add.l   %1, r63, %0
3529         movi    %1, %0
3530         #
3531         ld%M1.l %m1, %0
3532         st%M0.l %m0, %N1
3533         ptabs   %1, %0
3534         gettr   %1, %0
3535         pt      %1, %0"
3536   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3537    (set_attr "length" "4,4,8,4,4,4,4,12")])
3538
3539 (define_split
3540   [(set (match_operand:SI 0 "arith_reg_operand" "")
3541         (match_operand:SI 1 "immediate_operand" ""))]
3542   "TARGET_SHMEDIA && reload_completed
3543    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3544   [(set (subreg:DI (match_dup 0) 0) (match_dup 2))]
3545   "
3546 {
3547   operands[2] = shallow_copy_rtx (operands[1]);
3548   PUT_MODE (operands[2], DImode);
3549 }")
3550
3551 (define_split
3552   [(set (match_operand:SI 0 "register_operand" "")
3553         (match_operand:SI 1 "immediate_operand" ""))]
3554   "TARGET_SHMEDIA && reload_completed
3555    && ((GET_CODE (operands[1]) == CONST_INT
3556         && ! CONST_OK_FOR_I16 (INTVAL (operands[1])))
3557        || GET_CODE (operands[1]) == CONST_DOUBLE)"
3558   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3559
3560 (define_expand "movsi"
3561   [(set (match_operand:SI 0 "general_movdst_operand" "")
3562         (match_operand:SI 1 "general_movsrc_operand" ""))]
3563   ""
3564   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
3565
3566 (define_expand "ic_invalidate_line"
3567   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
3568                                 (match_dup 1)] UNSPEC_ICACHE)
3569               (clobber (scratch:SI))])]
3570   "TARGET_HARD_SH4 || TARGET_SH5"
3571   "
3572 {
3573   if (TARGET_SHMEDIA)
3574     {
3575       emit_insn (gen_ic_invalidate_line_media (operands[0]));
3576       DONE;
3577     }
3578   else if (TARGET_SHCOMPACT)
3579     {
3580       operands[1] = function_symbol (\"__ic_invalidate\");
3581       operands[1] = force_reg (Pmode, operands[1]);
3582       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
3583       DONE;
3584     }
3585   else if (TARGET_SH4A_ARCH)
3586     {
3587       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
3588       DONE;
3589     }
3590   operands[0] = force_reg (Pmode, operands[0]);
3591   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
3592                                                                Pmode)));
3593 }")
3594
3595 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
3596 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
3597 ;; the requirement *1*00 for associative address writes.  The alignment of
3598 ;; %0 implies that its least significant bit is cleared,
3599 ;; thus we clear the V bit of a matching entry if there is one.
3600 (define_insn "ic_invalidate_line_i"
3601   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
3602                      (match_operand:SI 1 "register_operand" "r")]
3603                      UNSPEC_ICACHE)
3604    (clobber (match_scratch:SI 2 "=&r"))]
3605   "TARGET_HARD_SH4"
3606   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
3607   [(set_attr "length" "8")
3608    (set_attr "type" "cwb")])
3609
3610 (define_insn "ic_invalidate_line_sh4a"
3611   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
3612                     UNSPEC_ICACHE)]
3613   "TARGET_SH4A_ARCH"
3614   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
3615   [(set_attr "length" "16")
3616    (set_attr "type" "cwb")])
3617
3618 ;; ??? could make arg 0 an offsettable memory operand to allow to save
3619 ;; an add in the code that calculates the address.
3620 (define_insn "ic_invalidate_line_media"
3621   [(unspec_volatile [(match_operand 0 "register_operand" "r")]
3622                     UNSPEC_ICACHE)]
3623   "TARGET_SHMEDIA"
3624   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
3625   [(set_attr "length" "16")
3626    (set_attr "type" "invalidate_line_media")])
3627
3628 (define_insn "ic_invalidate_line_compact"
3629   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3630                      (match_operand:SI 1 "register_operand" "r")]
3631                     UNSPEC_ICACHE)
3632    (clobber (reg:SI PR_REG))]
3633   "TARGET_SHCOMPACT"
3634   "jsr @%1%#"
3635   [(set_attr "type" "sfunc")
3636    (set_attr "needs_delay_slot" "yes")])
3637
3638 (define_expand "initialize_trampoline"
3639   [(match_operand:SI 0 "" "")
3640    (match_operand:SI 1 "" "")
3641    (match_operand:SI 2 "" "")]
3642   "TARGET_SHCOMPACT"
3643   "
3644 {
3645   rtx sfun, tramp;
3646
3647   tramp = force_reg (Pmode, operands[0]);
3648   sfun = force_reg (Pmode, function_symbol (\"__init_trampoline\"));
3649   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
3650   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
3651
3652   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
3653   DONE;
3654 }")
3655
3656 (define_insn "initialize_trampoline_compact"
3657   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3658                      (match_operand:SI 1 "register_operand" "r")
3659                      (reg:SI R2_REG) (reg:SI R3_REG)]
3660                     UNSPEC_INIT_TRAMP)
3661
3662    (clobber (reg:SI PR_REG))]
3663   "TARGET_SHCOMPACT"
3664   "jsr @%1%#"
3665   [(set_attr "type" "sfunc")
3666    (set_attr "needs_delay_slot" "yes")])
3667
3668 (define_insn "movqi_i"
3669   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
3670         (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
3671   "TARGET_SH1
3672    && (arith_reg_operand (operands[0], QImode)
3673        || arith_reg_operand (operands[1], QImode))"
3674   "@
3675         mov     %1,%0
3676         mov.b   %1,%0
3677         mov.b   %1,%0
3678         movt    %0
3679         sts     %1,%0
3680         lds     %1,%0"
3681  [(set_attr "type" "move,load,store,move,move,move")])
3682
3683 (define_insn "*movqi_media"
3684   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
3685         (match_operand:QI 1 "general_movsrc_operand" "r,I16C16,m,rZ"))]
3686   "TARGET_SHMEDIA
3687    && (arith_reg_operand (operands[0], QImode)
3688        || arith_reg_or_0_operand (operands[1], QImode))"
3689   "@
3690         add.l   %1, r63, %0
3691         movi    %1, %0
3692         ld%M1.ub        %m1, %0
3693         st%M0.b %m0, %N1"
3694   [(set_attr "type" "arith_media,arith_media,load_media,store_media")])
3695
3696 (define_expand "movqi"
3697   [(set (match_operand:QI 0 "general_operand" "")
3698         (match_operand:QI 1 "general_operand"  ""))]
3699   ""
3700   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
3701
3702 (define_expand "reload_inqi"
3703   [(set (match_operand:SI 2 "" "=&r")
3704         (match_operand:QI 1 "inqhi_operand" ""))
3705    (set (match_operand:QI 0 "arith_reg_operand" "=r")
3706         (truncate:QI (match_dup 3)))]
3707   "TARGET_SHMEDIA"
3708   "
3709 {
3710   rtx inner = XEXP (operands[1], 0);
3711   int regno = REGNO (inner);
3712
3713   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3714   operands[1] = gen_rtx_REG (SImode, regno);
3715   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3716 }")
3717
3718 /* When storing r0, we have to avoid reg+reg addressing.  */
3719 (define_insn "movhi_i"
3720   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
3721         (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
3722   "TARGET_SH1
3723    && (arith_reg_operand (operands[0], HImode)
3724        || arith_reg_operand (operands[1], HImode))
3725    && (GET_CODE (operands[0]) != MEM
3726        || GET_CODE (XEXP (operands[0], 0)) != PLUS
3727        || GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != REG
3728        || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
3729   "@
3730         mov.w   %1,%0
3731         mov     %1,%0
3732         mov.w   %1,%0
3733         movt    %0
3734         mov.w   %1,%0
3735         sts     %1,%0
3736         lds     %1,%0
3737         fake    %1,%0"
3738   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
3739
3740 (define_insn "*movhi_media"
3741   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
3742         (match_operand:HI 1 "general_movsrc_operand" "r,I16C16,n,m,rZ"))]
3743   "TARGET_SHMEDIA
3744    && (arith_reg_operand (operands[0], HImode)
3745        || arith_reg_or_0_operand (operands[1], HImode))"
3746   "@
3747         add.l   %1, r63, %0
3748         movi    %1, %0
3749         #
3750         ld%M1.w %m1, %0
3751         st%M0.w %m0, %N1"
3752   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")])
3753
3754 (define_split
3755   [(set (match_operand:HI 0 "register_operand" "")
3756         (match_operand:HI 1 "immediate_operand" ""))]
3757   "TARGET_SHMEDIA && reload_completed
3758    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
3759   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3760
3761 (define_expand "movhi"
3762   [(set (match_operand:HI 0 "general_movdst_operand" "")
3763         (match_operand:HI 1 "general_movsrc_operand"  ""))]
3764   ""
3765   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
3766
3767 (define_expand "reload_inhi"
3768   [(set (match_operand:SI 2 "" "=&r")
3769         (match_operand:HI 1 "inqhi_operand" ""))
3770    (set (match_operand:HI 0 "arith_reg_operand" "=r")
3771         (truncate:HI (match_dup 3)))]
3772   "TARGET_SHMEDIA"
3773   "
3774 {
3775   rtx inner = XEXP (operands[1], 0);
3776   int regno = REGNO (inner);
3777
3778   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3779   operands[1] = gen_rtx_REG (SImode, regno);
3780   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3781 }")
3782
3783 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
3784 ;; compiled with -m2 -ml -O3 -funroll-loops
3785 (define_insn "*movdi_i"
3786   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
3787         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
3788   "TARGET_SH1
3789    && (arith_reg_operand (operands[0], DImode)
3790        || arith_reg_operand (operands[1], DImode))"
3791   "* return output_movedouble (insn, operands, DImode);"
3792   [(set_attr "length" "4")
3793    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
3794
3795 ;; If the output is a register and the input is memory or a register, we have
3796 ;; to be careful and see which word needs to be loaded first.
3797
3798 (define_split
3799   [(set (match_operand:DI 0 "general_movdst_operand" "")
3800         (match_operand:DI 1 "general_movsrc_operand" ""))]
3801   "TARGET_SH1 && reload_completed"
3802   [(set (match_dup 2) (match_dup 3))
3803    (set (match_dup 4) (match_dup 5))]
3804   "
3805 {
3806   int regno;
3807
3808   if ((GET_CODE (operands[0]) == MEM
3809        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
3810       || (GET_CODE (operands[1]) == MEM
3811           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
3812     FAIL;
3813
3814   switch (GET_CODE (operands[0]))
3815     {
3816     case REG:
3817       regno = REGNO (operands[0]);
3818       break;
3819     case SUBREG:
3820       regno = subreg_regno (operands[0]);
3821       break;
3822     case MEM:
3823       regno = -1;
3824       break;
3825     default:
3826       gcc_unreachable ();
3827     }
3828
3829   if (regno == -1
3830       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
3831     {
3832       operands[2] = operand_subword (operands[0], 0, 0, DImode);
3833       operands[3] = operand_subword (operands[1], 0, 0, DImode);
3834       operands[4] = operand_subword (operands[0], 1, 0, DImode);
3835       operands[5] = operand_subword (operands[1], 1, 0, DImode);
3836     }
3837   else
3838     {
3839       operands[2] = operand_subword (operands[0], 1, 0, DImode);
3840       operands[3] = operand_subword (operands[1], 1, 0, DImode);
3841       operands[4] = operand_subword (operands[0], 0, 0, DImode);
3842       operands[5] = operand_subword (operands[1], 0, 0, DImode);
3843     }
3844
3845   if (operands[2] == 0 || operands[3] == 0
3846       || operands[4] == 0 || operands[5] == 0)
3847     FAIL;
3848 }")
3849
3850 (define_insn "*movdi_media"
3851   [(set (match_operand:DI 0 "general_movdst_operand"
3852                  "=r,r,r,rl,m,f,m,f,r,f,*b,r,b")
3853         (match_operand:DI 1 "general_movsrc_operand"
3854          "r,I16C16,nCpgF,m,rlZ,m,f,rZ,f,f,r,*b,Csy"))]
3855   "TARGET_SHMEDIA_FPU
3856    && (register_operand (operands[0], DImode)
3857        || sh_register_operand (operands[1], DImode))"
3858   "@
3859         add     %1, r63, %0
3860         movi    %1, %0
3861         #
3862         ld%M1.q %m1, %0
3863         st%M0.q %m0, %N1
3864         fld%M1.d        %m1, %0
3865         fst%M0.d        %m0, %1
3866         fmov.qd %N1, %0
3867         fmov.dq %1, %0
3868         fmov.d  %1, %0
3869         ptabs   %1, %0
3870         gettr   %1, %0
3871         pt      %1, %0"
3872   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,dfpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
3873    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
3874
3875 (define_insn "*movdi_media_nofpu"
3876   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,b")
3877         (match_operand:DI 1 "general_movsrc_operand" "r,I16C16,nCpgF,m,rlZ,r,*b,Csy"))]
3878   "TARGET_SHMEDIA
3879    && (register_operand (operands[0], DImode)
3880        || sh_register_operand (operands[1], DImode))"
3881   "@
3882         add     %1, r63, %0
3883         movi    %1, %0
3884         #
3885         ld%M1.q %m1, %0
3886         st%M0.q %m0, %N1
3887         ptabs   %1, %0
3888         gettr   %1, %0
3889         pt      %1, %0"
3890   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3891    (set_attr "length" "4,4,16,4,4,4,4,*")])
3892
3893 (define_split
3894   [(set (match_operand:DI 0 "arith_reg_operand" "")
3895         (match_operand:DI 1 "immediate_operand" ""))]
3896   "TARGET_SHMEDIA && reload_completed
3897    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3898   [(set (match_dup 0) (match_dup 1))]
3899   "
3900 {
3901   rtx insn;
3902
3903   if (TARGET_SHMEDIA64)
3904     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
3905   else
3906     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
3907
3908   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
3909                                         REG_NOTES (insn));
3910
3911   DONE;
3912 }")
3913
3914 (define_expand "movdi_const"
3915   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3916         (const:DI (sign_extend:DI
3917                    (truncate:HI
3918                     (ashiftrt:DI
3919                      (match_operand:DI 1 "immediate_operand" "s")
3920                      (const_int 48))))))
3921    (set (match_dup 0)
3922         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3923                 (zero_extend:DI
3924                  (truncate:HI
3925                   (const:DI
3926                    (sign_extend:DI
3927                     (truncate:HI
3928                      (ashiftrt:SI
3929                       (match_dup 1)
3930                       (const_int 32)))))))))
3931    (set (match_dup 0)
3932         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3933                 (zero_extend:DI
3934                  (truncate:HI
3935                   (const:DI
3936                    (sign_extend:DI
3937                     (truncate:HI
3938                      (ashiftrt:SI
3939                       (match_dup 1)
3940                       (const_int 16)))))))))
3941    (set (match_dup 0)
3942         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3943                 (zero_extend:DI
3944                  (truncate:HI
3945                   (const:DI
3946                    (sign_extend:DI
3947                     (truncate:HI
3948                      (match_dup 1))))))))]
3949   "TARGET_SHMEDIA64 && reload_completed
3950    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3951   "
3952 {
3953   sh_mark_label (operands[1], 4);
3954 }")
3955
3956 (define_expand "movdi_const_32bit"
3957   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3958         (const:DI (sign_extend:DI
3959                    (truncate:HI
3960                     (ashiftrt:DI
3961                      (match_operand:DI 1 "immediate_operand" "s")
3962                      (const_int 16))))))
3963    (set (match_dup 0)
3964         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3965                 (zero_extend:DI
3966                  (truncate:HI
3967                   (const:DI
3968                    (sign_extend:DI
3969                     (truncate:HI
3970                      (match_dup 1))))))))]
3971   "TARGET_SHMEDIA32 && reload_completed
3972    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3973   "
3974 {
3975   sh_mark_label (operands[1], 2);
3976 }")
3977
3978 (define_expand "movdi_const_16bit"
3979   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3980         (const:DI (sign_extend:DI
3981                    (truncate:HI
3982                     (match_operand:DI 1 "immediate_operand" "s")))))]
3983   "TARGET_SHMEDIA && flag_pic && reload_completed
3984    && GET_CODE (operands[1]) == SYMBOL_REF"
3985   "")
3986
3987 (define_split
3988   [(set (match_operand:DI 0 "arith_reg_operand" "")
3989         (match_operand:DI 1 "immediate_operand" ""))]
3990   "TARGET_SHMEDIA && reload_completed
3991    && GET_CODE (operands[1]) == CONST_INT
3992    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
3993   [(set (match_dup 0) (match_dup 2))
3994    (match_dup 1)]
3995   "
3996 {
3997   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3998   unsigned HOST_WIDE_INT low = val;
3999   unsigned HOST_WIDE_INT high = val;
4000   unsigned HOST_WIDE_INT sign;
4001   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
4002
4003   /* Sign-extend the 16 least-significant bits.  */
4004   low &= 0xffff;
4005   low ^= 0x8000;
4006   low -= 0x8000;
4007
4008   /* Arithmetic shift right the word by 16 bits.  */
4009   high >>= 16;
4010   sign = 1;
4011   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
4012   high ^= sign;
4013   high -= sign;
4014   do
4015     {
4016       /* If we can't generate the constant with a two-insn movi / shori
4017          sequence, try some other strategies.  */
4018       if (! CONST_OK_FOR_I16 (high))
4019         {
4020           /* Try constant load / left shift.  We know VAL != 0.  */
4021           val2 = val ^ (val-1);
4022           if (val2 > 0x1ffff)
4023             {
4024               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
4025
4026               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
4027                   || (! CONST_OK_FOR_I16 (high >> 16)
4028                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
4029                 {
4030                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
4031                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
4032                                                    GEN_INT (trailing_zeroes));
4033                   break;
4034                 }
4035             }
4036           /* Try constant load / right shift.  */
4037           val2 = (val >> 15) + 1;
4038           if (val2 == (val2 & -val2))
4039             {
4040               int shift = 49 - exact_log2 (val2);
4041
4042               val2 = trunc_int_for_mode (val << shift, DImode);
4043               if (CONST_OK_FOR_I16 (val2))
4044                 {
4045                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
4046                                                    GEN_INT (shift));
4047                   break;
4048                 }
4049             }
4050           /* Try mperm.w .  */
4051           val2 = val & 0xffff;
4052           if ((val >> 16 & 0xffff) == val2
4053               && (val >> 32 & 0xffff) == val2
4054               && (val >> 48 & 0xffff) == val2)
4055             {
4056               val2 = (HOST_WIDE_INT) val >> 48;
4057               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
4058               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
4059               break;
4060             }
4061           /* Try movi / mshflo.l  */
4062           val2 = (HOST_WIDE_INT) val >> 32;
4063           if (val2 == ((unsigned HOST_WIDE_INT)
4064                         trunc_int_for_mode (val, SImode)))
4065             {
4066               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4067                                              operands[0]);
4068               break;
4069             }
4070           /* Try movi / mshflo.l w/ r63.  */
4071           val2 = val + ((HOST_WIDE_INT) -1 << 32);
4072           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
4073             {
4074               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4075                                              const0_rtx);
4076               break;
4077             }
4078         }
4079       val2 = high;
4080       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
4081     }
4082   while (0);
4083   operands[2] = GEN_INT (val2);
4084 }")
4085
4086 (define_split
4087   [(set (match_operand:DI 0 "arith_reg_operand" "")
4088         (match_operand:DI 1 "immediate_operand" ""))]
4089   "TARGET_SHMEDIA && reload_completed
4090    && GET_CODE (operands[1]) == CONST_DOUBLE"
4091   [(set (match_dup 0) (match_dup 2))
4092   (set (match_dup 0)
4093        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
4094                (zero_extend:DI (truncate:HI (match_dup 1)))))]
4095   "
4096 {
4097   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
4098   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
4099   unsigned HOST_WIDE_INT val = low;
4100   unsigned HOST_WIDE_INT sign;
4101
4102   /* Sign-extend the 16 least-significant bits.  */
4103   val &= 0xffff;
4104   val ^= 0x8000;
4105   val -= 0x8000;
4106   operands[1] = GEN_INT (val);
4107
4108   /* Arithmetic shift right the double-word by 16 bits.  */
4109   low >>= 16;
4110   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
4111   high >>= 16;
4112   sign = 1;
4113   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
4114   high ^= sign;
4115   high -= sign;
4116
4117   /* This will only be true if high is a sign-extension of low, i.e.,
4118      it must be either 0 or (unsigned)-1, and be zero iff the
4119      most-significant bit of low is set.  */
4120   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
4121     operands[2] = GEN_INT (low);
4122   else
4123     operands[2] = immed_double_const (low, high, DImode);
4124 }")
4125
4126 (define_insn "shori_media"
4127   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
4128         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
4129                            (const_int 16))
4130                 (zero_extend:DI
4131                  (truncate:HI
4132                   (match_operand:DI 2 "immediate_operand" "I16C16,nF")))))]
4133   "TARGET_SHMEDIA"
4134   "@
4135         shori   %u2, %0
4136         #"
4137   [(set_attr "type" "arith_media,*")])
4138
4139 (define_expand "movdi"
4140   [(set (match_operand:DI 0 "general_movdst_operand" "")
4141         (match_operand:DI 1 "general_movsrc_operand" ""))]
4142   ""
4143   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
4144
4145 (define_insn "movdf_media"
4146   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4147         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
4148   "TARGET_SHMEDIA_FPU
4149    && (register_operand (operands[0], DFmode)
4150        || sh_register_operand (operands[1], DFmode))"
4151   "@
4152         fmov.d  %1, %0
4153         fmov.qd %N1, %0
4154         fmov.dq %1, %0
4155         add     %1, r63, %0
4156         #
4157         fld%M1.d        %m1, %0
4158         fst%M0.d        %m0, %1
4159         ld%M1.q %m1, %0
4160         st%M0.q %m0, %N1"
4161   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4162
4163 (define_insn "movdf_media_nofpu"
4164   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4165         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
4166   "TARGET_SHMEDIA
4167    && (register_operand (operands[0], DFmode)
4168        || sh_register_operand (operands[1], DFmode))"
4169   "@
4170         add     %1, r63, %0
4171         #
4172         ld%M1.q %m1, %0
4173         st%M0.q %m0, %N1"
4174   [(set_attr "type" "arith_media,*,load_media,store_media")])
4175
4176 (define_split
4177   [(set (match_operand:DF 0 "arith_reg_operand" "")
4178         (match_operand:DF 1 "immediate_operand" ""))]
4179   "TARGET_SHMEDIA && reload_completed"
4180   [(set (match_dup 3) (match_dup 2))]
4181   "
4182 {
4183   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
4184   long values[2];
4185   REAL_VALUE_TYPE value;
4186
4187   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4188   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
4189
4190   if (HOST_BITS_PER_WIDE_INT >= 64)
4191     operands[2] = immed_double_const ((unsigned long) values[endian]
4192                                       | ((HOST_WIDE_INT) values[1 - endian]
4193                                          << 32), 0, DImode);
4194   else
4195     {
4196       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
4197       operands[2] = immed_double_const (values[endian], values[1 - endian],
4198                                         DImode);
4199     }
4200
4201   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4202 }")
4203
4204 ;; ??? This should be a define expand.
4205
4206 (define_insn "movdf_k"
4207   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4208         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
4209   "TARGET_SH1
4210    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
4211        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
4212        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4213        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4214    && (arith_reg_operand (operands[0], DFmode)
4215        || arith_reg_operand (operands[1], DFmode))"
4216   "* return output_movedouble (insn, operands, DFmode);"
4217   [(set_attr "length" "4")
4218    (set_attr "type" "move,pcload,load,store")])
4219
4220 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
4221 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
4222 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
4223 ;; the d/m/c/X alternative, which is split later into single-precision
4224 ;; instructions.  And when not optimizing, no splits are done before fixing
4225 ;; up pcloads, so we need usable length information for that.
4226 (define_insn "movdf_i4"
4227   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
4228         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
4229    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
4230    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
4231   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
4232    && (arith_reg_operand (operands[0], DFmode)
4233        || arith_reg_operand (operands[1], DFmode))"
4234   "@
4235         fmov    %1,%0
4236         #
4237         #
4238         fmov.d  %1,%0
4239         fmov.d  %1,%0
4240         #
4241         #
4242         #
4243         #
4244         #"
4245   [(set_attr_alternative "length"
4246      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
4247       (const_int 4)
4248       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4249       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4250       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4251       (const_int 4)
4252       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
4253       ;; We can't use 4-byte push/pop on SHcompact, so we have to
4254       ;; increment or decrement r15 explicitly.
4255       (if_then_else
4256        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4257        (const_int 10) (const_int 8))
4258       (if_then_else
4259        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4260        (const_int 10) (const_int 8))])
4261    (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
4262    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
4263    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4264                                            (const_string "double")
4265                                            (const_string "none")))])
4266
4267 ;; Moving DFmode between fp/general registers through memory
4268 ;; (the top of the stack) is faster than moving through fpul even for
4269 ;; little endian.  Because the type of an instruction is important for its
4270 ;; scheduling,  it is beneficial to split these operations, rather than
4271 ;; emitting them in one single chunk, even if this will expose a stack
4272 ;; use that will prevent scheduling of other stack accesses beyond this
4273 ;; instruction.
4274 (define_split
4275   [(set (match_operand:DF 0 "register_operand" "")
4276         (match_operand:DF 1 "register_operand" ""))
4277    (use (match_operand:PSI 2 "fpscr_operand" ""))
4278    (clobber (match_scratch:SI 3 "=X"))]
4279   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
4280    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
4281   [(const_int 0)]
4282   "
4283 {
4284   rtx insn, tos;
4285
4286   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
4287     {
4288       emit_move_insn (stack_pointer_rtx,
4289                       plus_constant (stack_pointer_rtx, -8));
4290       tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4291     }
4292   else
4293     tos = gen_rtx_MEM (DFmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
4294   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
4295   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
4296     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4297   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4298     tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4299   else
4300     tos = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
4301   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
4302   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4303     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
4304   else
4305     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4306   DONE;
4307 }")
4308
4309 ;; local-alloc sometimes allocates scratch registers even when not required,
4310 ;; so we must be prepared to handle these.
4311
4312 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
4313 (define_split
4314   [(set (match_operand:DF 0 "general_movdst_operand" "")
4315         (match_operand:DF 1 "general_movsrc_operand"  ""))
4316    (use (match_operand:PSI 2 "fpscr_operand" ""))
4317    (clobber (match_scratch:SI 3 ""))]
4318   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
4319    && reload_completed
4320    && true_regnum (operands[0]) < 16
4321    && true_regnum (operands[1]) < 16"
4322   [(set (match_dup 0) (match_dup 1))]
4323   "
4324 {
4325   /* If this was a reg <-> mem operation with base + index reg addressing,
4326      we have to handle this in a special way.  */
4327   rtx mem = operands[0];
4328   int store_p = 1;
4329   if (! memory_operand (mem, DFmode))
4330     {
4331       mem = operands[1];
4332       store_p = 0;
4333     }
4334   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
4335     mem = SUBREG_REG (mem);
4336   if (GET_CODE (mem) == MEM)
4337     {
4338       rtx addr = XEXP (mem, 0);
4339       if (GET_CODE (addr) == PLUS
4340           && GET_CODE (XEXP (addr, 0)) == REG
4341           && GET_CODE (XEXP (addr, 1)) == REG)
4342         {
4343           int offset;
4344           rtx reg0 = gen_rtx_REG (Pmode, 0);
4345           rtx regop = operands[store_p], word0 ,word1;
4346
4347           if (GET_CODE (regop) == SUBREG)
4348             alter_subreg (&regop);
4349           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
4350             offset = 2;
4351           else
4352             offset = 4;
4353           mem = copy_rtx (mem);
4354           PUT_MODE (mem, SImode);
4355           word0 = gen_rtx_SUBREG (SImode, regop, 0);
4356           alter_subreg (&word0);
4357           word1 = gen_rtx_SUBREG (SImode, regop, 4);
4358           alter_subreg (&word1);
4359           if (store_p || ! refers_to_regno_p (REGNO (word0),
4360                                               REGNO (word0) + 1, addr, 0))
4361             {
4362               emit_insn (store_p
4363                          ? gen_movsi_ie (mem, word0)
4364                          : gen_movsi_ie (word0, mem));
4365               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4366               mem = copy_rtx (mem);
4367               emit_insn (store_p
4368                          ? gen_movsi_ie (mem, word1)
4369                          : gen_movsi_ie (word1, mem));
4370               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4371             }
4372           else
4373             {
4374               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4375               emit_insn (gen_movsi_ie (word1, mem));
4376               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4377               mem = copy_rtx (mem);
4378               emit_insn (gen_movsi_ie (word0, mem));
4379             }
4380           DONE;
4381         }
4382     }
4383 }")
4384
4385 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
4386 (define_split
4387   [(set (match_operand:DF 0 "register_operand" "")
4388         (match_operand:DF 1 "memory_operand"  ""))
4389    (use (match_operand:PSI 2 "fpscr_operand" ""))
4390    (clobber (reg:SI R0_REG))]
4391   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
4392   [(parallel [(set (match_dup 0) (match_dup 1))
4393               (use (match_dup 2))
4394               (clobber (scratch:SI))])]
4395   "")
4396
4397 (define_expand "reload_indf"
4398   [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
4399                    (match_operand:DF 1 "immediate_operand" "FQ"))
4400               (use (reg:PSI FPSCR_REG))
4401               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4402   "TARGET_SH1"
4403   "")
4404
4405 (define_expand "reload_outdf"
4406   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
4407                    (match_operand:DF 1 "register_operand" "af,r"))
4408               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
4409   "TARGET_SH1"
4410   "")
4411
4412 ;; Simplify no-op moves.
4413 (define_split
4414   [(set (match_operand:SF 0 "register_operand" "")
4415         (match_operand:SF 1 "register_operand" ""))
4416    (use (match_operand:PSI 2 "fpscr_operand" ""))
4417    (clobber (match_scratch:SI 3 ""))]
4418   "TARGET_SH2E && reload_completed
4419    && true_regnum (operands[0]) == true_regnum (operands[1])"
4420   [(set (match_dup 0) (match_dup 0))]
4421   "")
4422
4423 ;; fmovd substitute post-reload splits
4424 (define_split
4425   [(set (match_operand:DF 0 "register_operand" "")
4426         (match_operand:DF 1 "register_operand" ""))
4427    (use (match_operand:PSI 2 "fpscr_operand" ""))
4428    (clobber (match_scratch:SI 3 ""))]
4429   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4430    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4431    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4432   [(const_int 0)]
4433   "
4434 {
4435   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
4436   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
4437                            gen_rtx_REG (SFmode, src), operands[2]));
4438   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
4439                            gen_rtx_REG (SFmode, src + 1), operands[2]));
4440   DONE;
4441 }")
4442
4443 (define_split
4444   [(set (match_operand:DF 0 "register_operand" "")
4445         (mem:DF (match_operand:SI 1 "register_operand" "")))
4446    (use (match_operand:PSI 2 "fpscr_operand" ""))
4447    (clobber (match_scratch:SI 3 ""))]
4448   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
4449    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4450    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
4451   [(const_int 0)]
4452   "
4453 {
4454   int regno = true_regnum (operands[0]);
4455   rtx insn;
4456   rtx mem2 = gen_rtx_MEM (SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
4457
4458   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
4459                                            regno + !! TARGET_LITTLE_ENDIAN),
4460                                   mem2, operands[2]));
4461   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
4462   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
4463                                            regno + ! TARGET_LITTLE_ENDIAN),
4464                                   gen_rtx_MEM (SFmode, operands[1]),
4465                                   operands[2]));
4466   DONE;
4467 }")
4468
4469 (define_split
4470   [(set (match_operand:DF 0 "register_operand" "")
4471         (match_operand:DF 1 "memory_operand" ""))
4472    (use (match_operand:PSI 2 "fpscr_operand" ""))
4473    (clobber (match_scratch:SI 3 ""))]
4474   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
4475    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
4476   [(const_int 0)]
4477   "
4478 {
4479   int regno = true_regnum (operands[0]);
4480   rtx addr, insn, adjust = NULL_RTX;
4481   rtx mem2 = copy_rtx (operands[1]);
4482   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
4483   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
4484
4485   PUT_MODE (mem2, SFmode);
4486   operands[1] = copy_rtx (mem2);
4487   addr = XEXP (mem2, 0);
4488   if (GET_CODE (addr) != POST_INC)
4489     {
4490       /* If we have to modify the stack pointer, the value that we have
4491          read with post-increment might be modified by an interrupt,
4492          so write it back.  */
4493       if (REGNO (addr) == STACK_POINTER_REGNUM)
4494         adjust = gen_push_e (reg0);
4495       else
4496         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
4497       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
4498     }
4499   addr = XEXP (addr, 0);
4500   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
4501   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4502   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
4503   if (adjust)
4504     emit_insn (adjust);
4505   else
4506     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4507   DONE;
4508 }")
4509
4510 (define_split
4511   [(set (match_operand:DF 0 "memory_operand" "")
4512         (match_operand:DF 1 "register_operand" ""))
4513    (use (match_operand:PSI 2 "fpscr_operand" ""))
4514    (clobber (match_scratch:SI 3 ""))]
4515   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
4516    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4517   [(const_int 0)]
4518   "
4519 {
4520   int regno = true_regnum (operands[1]);
4521   rtx insn, addr, adjust = NULL_RTX;
4522
4523   operands[0] = copy_rtx (operands[0]);
4524   PUT_MODE (operands[0], SFmode);
4525   insn = emit_insn (gen_movsf_ie (operands[0],
4526                                   gen_rtx_REG (SFmode,
4527                                            regno + ! TARGET_LITTLE_ENDIAN),
4528                                   operands[2]));
4529   operands[0] = copy_rtx (operands[0]);
4530   addr = XEXP (operands[0], 0);
4531   if (GET_CODE (addr) != PRE_DEC)
4532     {
4533       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
4534       emit_insn_before (adjust, insn);
4535       XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
4536     }
4537   addr = XEXP (addr, 0);
4538   if (! adjust)
4539     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4540   insn = emit_insn (gen_movsf_ie (operands[0],
4541                                   gen_rtx_REG (SFmode,
4542                                            regno + !! TARGET_LITTLE_ENDIAN),
4543                                   operands[2]));
4544   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4545   DONE;
4546 }")
4547
4548 ;; If the output is a register and the input is memory or a register, we have
4549 ;; to be careful and see which word needs to be loaded first.
4550
4551 (define_split
4552   [(set (match_operand:DF 0 "general_movdst_operand" "")
4553         (match_operand:DF 1 "general_movsrc_operand" ""))]
4554   "TARGET_SH1 && reload_completed"
4555   [(set (match_dup 2) (match_dup 3))
4556    (set (match_dup 4) (match_dup 5))]
4557   "
4558 {
4559   int regno;
4560
4561   if ((GET_CODE (operands[0]) == MEM
4562        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
4563       || (GET_CODE (operands[1]) == MEM
4564           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
4565     FAIL;
4566
4567   switch (GET_CODE (operands[0]))
4568     {
4569     case REG:
4570       regno = REGNO (operands[0]);
4571       break;
4572     case SUBREG:
4573       regno = subreg_regno (operands[0]);
4574       break;
4575     case MEM:
4576       regno = -1;
4577       break;
4578     default:
4579       gcc_unreachable ();
4580     }
4581
4582   if (regno == -1
4583       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
4584     {
4585       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
4586       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
4587       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
4588       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
4589     }
4590   else
4591     {
4592       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
4593       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
4594       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
4595       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
4596     }
4597
4598   if (operands[2] == 0 || operands[3] == 0
4599       || operands[4] == 0 || operands[5] == 0)
4600     FAIL;
4601 }")
4602
4603 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
4604 ;; used only once, let combine add in the index again.
4605
4606 (define_split
4607   [(set (match_operand:SI 0 "register_operand" "")
4608         (match_operand:SI 1 "" ""))
4609    (clobber (match_operand 2 "register_operand" ""))]
4610   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4611   [(use (reg:SI R0_REG))]
4612   "
4613 {
4614   rtx addr, reg, const_int;
4615
4616   if (GET_CODE (operands[1]) != MEM)
4617     FAIL;
4618   addr = XEXP (operands[1], 0);
4619   if (GET_CODE (addr) != PLUS)
4620     FAIL;
4621   reg = XEXP (addr, 0);
4622   const_int = XEXP (addr, 1);
4623   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4624          && GET_CODE (const_int) == CONST_INT))
4625     FAIL;
4626   emit_move_insn (operands[2], const_int);
4627   emit_move_insn (operands[0],
4628                   change_address (operands[1], VOIDmode,
4629                                   gen_rtx_PLUS (SImode, reg, operands[2])));
4630   DONE;
4631 }")
4632
4633 (define_split
4634   [(set (match_operand:SI 1 "" "")
4635         (match_operand:SI 0 "register_operand" ""))
4636    (clobber (match_operand 2 "register_operand" ""))]
4637   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4638   [(use (reg:SI R0_REG))]
4639   "
4640 {
4641   rtx addr, reg, const_int;
4642
4643   if (GET_CODE (operands[1]) != MEM)
4644     FAIL;
4645   addr = XEXP (operands[1], 0);
4646   if (GET_CODE (addr) != PLUS)
4647     FAIL;
4648   reg = XEXP (addr, 0);
4649   const_int = XEXP (addr, 1);
4650   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4651          && GET_CODE (const_int) == CONST_INT))
4652     FAIL;
4653   emit_move_insn (operands[2], const_int);
4654   emit_move_insn (change_address (operands[1], VOIDmode,
4655                                   gen_rtx_PLUS (SImode, reg, operands[2])),
4656                   operands[0]);
4657   DONE;
4658 }")
4659
4660 (define_expand "movdf"
4661   [(set (match_operand:DF 0 "general_movdst_operand" "")
4662         (match_operand:DF 1 "general_movsrc_operand" ""))]
4663   ""
4664   "
4665 {
4666   if (prepare_move_operands (operands, DFmode)) DONE;
4667   if (TARGET_SHMEDIA)
4668     {
4669       if (TARGET_SHMEDIA_FPU)
4670         emit_insn (gen_movdf_media (operands[0], operands[1]));
4671       else
4672         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
4673       DONE;
4674     }
4675   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
4676     {
4677       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
4678       DONE;
4679     }
4680 }")
4681
4682 ;;This is incompatible with the way gcc uses subregs.
4683 ;;(define_insn "movv2sf_i"
4684 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
4685 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
4686 ;;  "TARGET_SHMEDIA_FPU
4687 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
4688 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
4689 ;;  "@
4690 ;;      #
4691 ;;      fld%M1.p        %m1, %0
4692 ;;      fst%M0.p        %m0, %1"
4693 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
4694
4695 (define_insn_and_split "movv2sf_i"
4696   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
4697         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
4698   "TARGET_SHMEDIA_FPU"
4699   "#"
4700   "TARGET_SHMEDIA_FPU && reload_completed"
4701   [(set (match_dup 0) (match_dup 1))]
4702   "
4703 {
4704   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
4705   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
4706 }")
4707
4708 (define_expand "movv2sf"
4709   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
4710         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
4711   "TARGET_SHMEDIA_FPU"
4712   "
4713 {
4714   if (prepare_move_operands (operands, V2SFmode))
4715     DONE;
4716 }")
4717
4718 (define_expand "addv2sf3"
4719   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4720    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4721    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4722   "TARGET_SHMEDIA_FPU"
4723   "
4724 {
4725   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
4726   DONE;
4727 }")
4728
4729 (define_expand "subv2sf3"
4730   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4731    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4732    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4733   "TARGET_SHMEDIA_FPU"
4734   "
4735 {
4736   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
4737   DONE;
4738 }")
4739
4740 (define_expand "mulv2sf3"
4741   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4742    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4743    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4744   "TARGET_SHMEDIA_FPU"
4745   "
4746 {
4747   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
4748   DONE;
4749 }")
4750
4751 (define_expand "divv2sf3"
4752   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4753    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4754    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4755   "TARGET_SHMEDIA_FPU"
4756   "
4757 {
4758   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
4759   DONE;
4760 }")
4761
4762 (define_insn_and_split "*movv4sf_i"
4763   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
4764         (match_operand:V4SF 1 "general_operand" "fZ,m,fZ"))]
4765   "TARGET_SHMEDIA_FPU"
4766   "#"
4767   "&& reload_completed"
4768   [(const_int 0)]
4769   "
4770 {
4771   int i;
4772
4773   for (i = 0; i < 4/2; i++)
4774     {
4775       rtx x, y;
4776
4777       if (GET_CODE (operands[0]) == MEM)
4778         x = gen_rtx_MEM (V2SFmode,
4779                          plus_constant (XEXP (operands[0], 0),
4780                                         i * GET_MODE_SIZE (V2SFmode)));
4781       else
4782         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
4783
4784       if (GET_CODE (operands[1]) == MEM)
4785         y = gen_rtx_MEM (V2SFmode,
4786                          plus_constant (XEXP (operands[1], 0),
4787                                         i * GET_MODE_SIZE (V2SFmode)));
4788       else
4789         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
4790
4791       emit_insn (gen_movv2sf_i (x, y));
4792     }
4793
4794   DONE;
4795 }"
4796   [(set_attr "length" "8")])
4797
4798 (define_expand "movv4sf"
4799   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
4800         (match_operand:V4SF 1 "general_operand" ""))]
4801   "TARGET_SHMEDIA_FPU"
4802   "
4803 {
4804   if (prepare_move_operands (operands, V4SFmode))
4805     DONE;
4806 }")
4807
4808 (define_insn_and_split "*movv16sf_i"
4809   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4810         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4811   "TARGET_SHMEDIA_FPU"
4812   "#"
4813   "&& reload_completed"
4814   [(const_int 0)]
4815   "
4816 {
4817   int i;
4818
4819   for (i = 0; i < 16/2; i++)
4820     {
4821       rtx x,y;
4822
4823       if (GET_CODE (operands[0]) == MEM)
4824         x = gen_rtx_MEM (V2SFmode,
4825                          plus_constant (XEXP (operands[0], 0),
4826                                         i * GET_MODE_SIZE (V2SFmode)));
4827       else
4828         {
4829           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
4830           alter_subreg (&x);
4831         }
4832
4833       if (GET_CODE (operands[1]) == MEM)
4834         y = gen_rtx_MEM (V2SFmode,
4835                          plus_constant (XEXP (operands[1], 0),
4836                                         i * GET_MODE_SIZE (V2SFmode)));
4837       else
4838         {
4839           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
4840           alter_subreg (&y);
4841         }
4842
4843       emit_insn (gen_movv2sf_i (x, y));
4844     }
4845
4846   DONE;
4847 }"
4848   [(set_attr "length" "32")])
4849
4850 (define_expand "movv16sf"
4851   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4852         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4853   "TARGET_SHMEDIA_FPU"
4854   "
4855 {
4856   if (prepare_move_operands (operands, V16SFmode))
4857     DONE;
4858 }")
4859
4860 (define_insn "movsf_media"
4861   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4862         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
4863   "TARGET_SHMEDIA_FPU
4864    && (register_operand (operands[0], SFmode)
4865        || sh_register_operand (operands[1], SFmode))"
4866   "@
4867         fmov.s  %1, %0
4868         fmov.ls %N1, %0
4869         fmov.sl %1, %0
4870         add.l   %1, r63, %0
4871         #
4872         fld%M1.s        %m1, %0
4873         fst%M0.s        %m0, %1
4874         ld%M1.l %m1, %0
4875         st%M0.l %m0, %N1"
4876   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4877
4878 (define_insn "movsf_media_nofpu"
4879   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
4880         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
4881   "TARGET_SHMEDIA
4882    && (register_operand (operands[0], SFmode)
4883        || sh_register_operand (operands[1], SFmode))"
4884   "@
4885         add.l   %1, r63, %0
4886         #
4887         ld%M1.l %m1, %0
4888         st%M0.l %m0, %N1"
4889   [(set_attr "type" "arith_media,*,load_media,store_media")])
4890
4891 (define_split
4892   [(set (match_operand:SF 0 "arith_reg_operand" "")
4893         (match_operand:SF 1 "immediate_operand" ""))]
4894   "TARGET_SHMEDIA && reload_completed
4895    && ! FP_REGISTER_P (true_regnum (operands[0]))"
4896   [(set (match_dup 3) (match_dup 2))]
4897   "
4898 {
4899   long values;
4900   REAL_VALUE_TYPE value;
4901
4902   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4903   REAL_VALUE_TO_TARGET_SINGLE (value, values);
4904   operands[2] = GEN_INT (values);
4905
4906   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4907 }")
4908
4909 (define_insn "movsf_i"
4910   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
4911         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
4912   "TARGET_SH1
4913    && (! TARGET_SH2E
4914        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
4915        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4916        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4917    && (arith_reg_operand (operands[0], SFmode)
4918        || arith_reg_operand (operands[1], SFmode))"
4919   "@
4920         mov     %1,%0
4921         mov     #0,%0
4922         mov.l   %1,%0
4923         mov.l   %1,%0
4924         mov.l   %1,%0
4925         lds     %1,%0
4926         sts     %1,%0"
4927   [(set_attr "type" "move,move,pcload,load,store,move,move")])
4928
4929 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
4930 ;; update_flow_info would not know where to put REG_EQUAL notes
4931 ;; when the destination changes mode.
4932 (define_insn "movsf_ie"
4933   [(set (match_operand:SF 0 "general_movdst_operand"
4934          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
4935         (match_operand:SF 1 "general_movsrc_operand"
4936           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
4937    (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"))
4938    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
4939
4940   "TARGET_SH2E
4941    && (arith_reg_operand (operands[0], SFmode)
4942        || arith_reg_operand (operands[1], SFmode)
4943        || arith_reg_operand (operands[3], SImode)
4944        || (fpul_operand (operands[0], SFmode)
4945            && memory_operand (operands[1], SFmode)
4946            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
4947        || (fpul_operand (operands[1], SFmode)
4948            && memory_operand (operands[0], SFmode)
4949            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
4950   "@
4951         fmov    %1,%0
4952         mov     %1,%0
4953         fldi0   %0
4954         fldi1   %0
4955         #
4956         fmov.s  %1,%0
4957         fmov.s  %1,%0
4958         mov.l   %1,%0
4959         mov.l   %1,%0
4960         mov.l   %1,%0
4961         fsts    fpul,%0
4962         flds    %1,fpul
4963         lds.l   %1,%0
4964         #
4965         sts     %1,%0
4966         lds     %1,%0
4967         sts.l   %1,%0
4968         lds.l   %1,%0
4969         ! move optimized away"
4970   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
4971    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
4972    (set_attr "length" "*,*,*,*,4,4,4,*,*,*,2,2,2,4,2,2,2,2,0")
4973    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4974                                            (const_string "single")
4975                                            (const_string "none")))])
4976
4977 (define_split
4978   [(set (match_operand:SF 0 "register_operand" "")
4979         (match_operand:SF 1 "register_operand" ""))
4980    (use (match_operand:PSI 2 "fpscr_operand" ""))
4981    (clobber (reg:SI FPUL_REG))]
4982   "TARGET_SH1"
4983   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
4984               (use (match_dup 2))
4985               (clobber (scratch:SI))])
4986    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
4987               (use (match_dup 2))
4988               (clobber (scratch:SI))])]
4989   "")
4990
4991 (define_expand "movsf"
4992   [(set (match_operand:SF 0 "general_movdst_operand" "")
4993         (match_operand:SF 1 "general_movsrc_operand" ""))]
4994   ""
4995   "
4996 {
4997   if (prepare_move_operands (operands, SFmode))
4998     DONE;
4999   if (TARGET_SHMEDIA)
5000     {
5001       if (TARGET_SHMEDIA_FPU)
5002         emit_insn (gen_movsf_media (operands[0], operands[1]));
5003       else
5004         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
5005       DONE;
5006     }
5007   if (TARGET_SH2E)
5008     {
5009       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
5010       DONE;
5011     }
5012 }")
5013
5014 (define_insn "mov_nop"
5015   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
5016   "TARGET_SH2E"
5017   ""
5018   [(set_attr "length" "0")
5019    (set_attr "type" "nil")])
5020
5021 (define_expand "reload_insf"
5022   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
5023                    (match_operand:SF 1 "immediate_operand" "FQ"))
5024               (use (reg:PSI FPSCR_REG))
5025               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5026   "TARGET_SH1"
5027   "")
5028
5029 (define_expand "reload_insi"
5030   [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
5031                    (match_operand:SF 1 "immediate_operand" "FQ"))
5032               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5033   "TARGET_SH1"
5034   "")
5035
5036 (define_insn "*movsi_y"
5037   [(set (match_operand:SI 0 "register_operand" "=y,y")
5038         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
5039    (clobber (match_scratch:SI 2 "=&z,r"))]
5040   "TARGET_SH2E
5041    && (reload_in_progress || reload_completed)"
5042   "#"
5043   [(set_attr "length" "4")
5044    (set_attr "type" "pcload,move")])
5045
5046 (define_split
5047   [(set (match_operand:SI 0 "register_operand" "")
5048         (match_operand:SI 1 "immediate_operand" ""))
5049    (clobber (match_operand:SI 2 "register_operand" ""))]
5050   "TARGET_SH1"
5051   [(set (match_dup 2) (match_dup 1))
5052    (set (match_dup 0) (match_dup 2))]
5053   "")
5054
5055 (define_split
5056   [(set (match_operand:SI 0 "register_operand" "")
5057         (match_operand:SI 1 "memory_operand" ""))
5058    (clobber (reg:SI R0_REG))]
5059   "TARGET_SH1"
5060   [(set (match_dup 0) (match_dup 1))]
5061   "")
5062 \f
5063 ;; ------------------------------------------------------------------------
5064 ;; Define the real conditional branch instructions.
5065 ;; ------------------------------------------------------------------------
5066
5067 (define_insn "branch_true"
5068   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
5069                            (label_ref (match_operand 0 "" ""))
5070                            (pc)))]
5071   "TARGET_SH1"
5072   "* return output_branch (1, insn, operands);"
5073   [(set_attr "type" "cbranch")])
5074
5075 (define_insn "branch_false"
5076   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
5077                            (label_ref (match_operand 0 "" ""))
5078                            (pc)))]
5079   "TARGET_SH1"
5080   "* return output_branch (0, insn, operands);"
5081   [(set_attr "type" "cbranch")])
5082
5083 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
5084 ;; which destination is too far away.
5085 ;; The const_int_operand is distinct for each branch target; it avoids
5086 ;; unwanted matches with redundant_insn.
5087 (define_insn "block_branch_redirect"
5088   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
5089   "TARGET_SH1"
5090   ""
5091   [(set_attr "length" "0")])
5092
5093 ;; This one has the additional purpose to record a possible scratch register
5094 ;; for the following branch.
5095 ;; ??? Unfortunately, just setting the scratch register is not good enough,
5096 ;; because the insn then might be deemed dead and deleted.  And we can't
5097 ;; make the use in the jump insn explicit because that would disable
5098 ;; delay slot scheduling from the target.
5099 (define_insn "indirect_jump_scratch"
5100   [(set (match_operand:SI 0 "register_operand" "=r")
5101         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
5102    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
5103   "TARGET_SH1"
5104   ""
5105   [(set_attr "length" "0")])
5106
5107 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
5108 ;; being pulled into the delay slot of a condbranch that has been made to
5109 ;; jump around the unconditional jump because it was out of range.
5110 (define_insn "stuff_delay_slot"
5111   [(set (pc)
5112         (unspec [(match_operand 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
5113    (set (reg:SI T_REG) (match_operand 1 "const_int_operand" ""))]
5114   "TARGET_SH1"
5115   ""
5116   [(set_attr "length" "0")
5117    (set_attr "cond_delay_slot" "yes")])
5118 \f
5119 ;; Conditional branch insns
5120
5121 (define_expand "beq_media"
5122   [(set (pc)
5123         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
5124                           (match_operand:DI 2 "arith_operand" "r,I06"))
5125                       (label_ref:DI (match_operand 0 "" ""))
5126                       (pc)))]
5127   "TARGET_SHMEDIA"
5128   "")
5129
5130 (define_insn "*beq_media_i"
5131   [(set (pc)
5132         (if_then_else (match_operator 3 "equality_comparison_operator"
5133                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
5134                          (match_operand:DI 2 "arith_operand" "r,I06")])
5135                       (match_operand:DI 0 "target_operand" "b,b")
5136                       (pc)))]
5137   "TARGET_SHMEDIA"
5138   "@
5139         b%o3%'  %1, %2, %0
5140         b%o3i%' %1, %2, %0"
5141   [(set_attr "type" "cbranch_media")])
5142
5143 (define_expand "bne_media"
5144   [(set (pc)
5145         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
5146                           (match_operand:DI 2 "arith_operand" "r,I06"))
5147                       (label_ref:DI (match_operand 0 "" ""))
5148                       (pc)))]
5149   "TARGET_SHMEDIA"
5150   "")
5151
5152 (define_expand "bgt_media"
5153   [(set (pc)
5154         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5155                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5156                       (label_ref:DI (match_operand 0 "" ""))
5157                       (pc)))]
5158   "TARGET_SHMEDIA"
5159   "")
5160
5161 (define_expand "bge_media"
5162   [(set (pc)
5163         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5164                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5165                       (label_ref:DI (match_operand 0 "" ""))
5166                       (pc)))]
5167   "TARGET_SHMEDIA"
5168   "")
5169
5170 (define_expand "bgtu_media"
5171   [(set (pc)
5172         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5173                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5174                       (label_ref:DI (match_operand 0 "" ""))
5175                       (pc)))]
5176   "TARGET_SHMEDIA"
5177   "")
5178
5179 (define_expand "bgeu_media"
5180   [(set (pc)
5181         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5182                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5183                       (label_ref:DI (match_operand 0 "" ""))
5184                       (pc)))]
5185   "TARGET_SHMEDIA"
5186   "")
5187
5188 (define_insn "*bgt_media_i"
5189   [(set (pc)
5190         (if_then_else (match_operator 3 "greater_comparison_operator"
5191                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5192                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5193                       (match_operand:DI 0 "target_operand" "b")
5194                       (pc)))]
5195   "TARGET_SHMEDIA"
5196   "b%o3%'       %N1, %N2, %0"
5197   [(set_attr "type" "cbranch_media")])
5198
5199 ;; These are only needed to make invert_jump() happy.
5200 (define_insn "*blt_media_i"
5201   [(set (pc)
5202         (if_then_else (match_operator 3 "less_comparison_operator"
5203                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5204                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5205                       (match_operand:DI 0 "target_operand" "b")
5206                       (pc)))]
5207   "TARGET_SHMEDIA"
5208   "b%o3%'       %N2, %N1, %0"
5209   [(set_attr "type" "cbranch_media")])
5210
5211 (define_expand "beq"
5212   [(set (pc)
5213         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5214                       (label_ref (match_operand 0 "" ""))
5215                       (pc)))]
5216   ""
5217   "
5218 {
5219   if (TARGET_SHMEDIA)
5220     {
5221       if (GET_MODE (sh_compare_op0) != DImode)
5222         {
5223           rtx tmp = gen_reg_rtx (DImode);
5224
5225           emit_insn (gen_seq (tmp));
5226           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5227           DONE;
5228         }
5229
5230       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5231       emit_jump_insn (gen_beq_media (operands[0],
5232                                      sh_compare_op0, sh_compare_op1));
5233       DONE;
5234     }
5235
5236   from_compare (operands, EQ);
5237 }")
5238
5239 (define_expand "bne"
5240   [(set (pc)
5241         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5242                       (label_ref (match_operand 0 "" ""))
5243                       (pc)))]
5244   ""
5245   "
5246 {
5247   if (TARGET_SHMEDIA)
5248     {
5249       if (GET_MODE (sh_compare_op0) != DImode)
5250         {
5251           rtx tmp = gen_reg_rtx (DImode);
5252
5253           emit_insn (gen_seq (tmp));
5254           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
5255           DONE;
5256         }
5257
5258       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5259       emit_jump_insn (gen_bne_media (operands[0],
5260                                      sh_compare_op0, sh_compare_op1));
5261       DONE;
5262     }
5263
5264   from_compare (operands, EQ);
5265 }")
5266
5267 (define_expand "bgt"
5268   [(set (pc)
5269         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5270                       (label_ref (match_operand 0 "" ""))
5271                       (pc)))]
5272   ""
5273   "
5274 {
5275   if (TARGET_SHMEDIA)
5276     {
5277       if (GET_MODE (sh_compare_op0) != DImode)
5278         {
5279           rtx tmp = gen_reg_rtx (DImode);
5280
5281           emit_insn (gen_sgt (tmp));
5282           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5283           DONE;
5284         }
5285
5286       if (sh_compare_op0 != const0_rtx)
5287         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5288       if (sh_compare_op1 != const0_rtx)
5289         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5290       emit_jump_insn (gen_bgt_media (operands[0],
5291                                      sh_compare_op0, sh_compare_op1));
5292       DONE;
5293     }
5294
5295   from_compare (operands, GT);
5296 }")
5297
5298 (define_expand "blt"
5299   [(set (pc)
5300         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5301                       (label_ref (match_operand 0 "" ""))
5302                       (pc)))]
5303   ""
5304   "
5305 {
5306   if (TARGET_SHMEDIA)
5307     {
5308       if (GET_MODE (sh_compare_op0) != DImode)
5309         {
5310           rtx tmp = gen_reg_rtx (DImode);
5311
5312           emit_insn (gen_slt (tmp));
5313           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5314           DONE;
5315         }
5316
5317       if (sh_compare_op0 != const0_rtx)
5318         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5319       if (sh_compare_op1 != const0_rtx)
5320         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5321       emit_jump_insn (gen_bgt_media (operands[0],
5322                                      sh_compare_op1, sh_compare_op0));
5323       DONE;
5324     }
5325
5326   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5327     {
5328       rtx tmp = sh_compare_op0;
5329       sh_compare_op0 = sh_compare_op1;
5330       sh_compare_op1 = tmp;
5331       emit_insn (gen_bgt (operands[0]));
5332       DONE;
5333     }
5334   from_compare (operands, GE);
5335 }")
5336
5337 (define_expand "ble"
5338   [(set (pc)
5339         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5340                       (label_ref (match_operand 0 "" ""))
5341                       (pc)))]
5342   ""
5343   "
5344 {
5345   if (TARGET_SHMEDIA)
5346     {
5347       if (GET_MODE (sh_compare_op0) != DImode)
5348         {
5349           rtx tmp = gen_reg_rtx (DImode);
5350
5351           emit_insn (gen_sle (tmp));
5352           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5353           DONE;
5354         }
5355
5356       if (sh_compare_op0 != const0_rtx)
5357         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5358       if (sh_compare_op1 != const0_rtx)
5359         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5360       emit_jump_insn (gen_bge_media (operands[0],
5361                                      sh_compare_op1, sh_compare_op0));
5362       DONE;
5363     }
5364
5365   if (TARGET_SH2E
5366       && TARGET_IEEE
5367       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5368     {
5369       rtx tmp = sh_compare_op0;
5370       sh_compare_op0 = sh_compare_op1;
5371       sh_compare_op1 = tmp;
5372       emit_insn (gen_bge (operands[0]));
5373       DONE;
5374     }
5375   from_compare (operands, GT);
5376 }")
5377
5378 (define_expand "bge"
5379   [(set (pc)
5380         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5381                       (label_ref (match_operand 0 "" ""))
5382                       (pc)))]
5383   ""
5384   "
5385 {
5386   if (TARGET_SHMEDIA)
5387     {
5388       if (GET_MODE (sh_compare_op0) != DImode)
5389         {
5390           rtx tmp = gen_reg_rtx (DImode);
5391
5392           emit_insn (gen_sge (tmp));
5393           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5394           DONE;
5395         }
5396
5397       if (sh_compare_op0 != const0_rtx)
5398         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5399       if (sh_compare_op1 != const0_rtx)
5400         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5401       emit_jump_insn (gen_bge_media (operands[0],
5402                                      sh_compare_op0, sh_compare_op1));
5403       DONE;
5404     }
5405
5406   if (TARGET_SH2E
5407       && ! TARGET_IEEE
5408       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5409     {
5410       rtx tmp = sh_compare_op0;
5411       sh_compare_op0 = sh_compare_op1;
5412       sh_compare_op1 = tmp;
5413       emit_insn (gen_ble (operands[0]));
5414       DONE;
5415     }
5416   from_compare (operands, GE);
5417 }")
5418
5419 (define_expand "bgtu"
5420   [(set (pc)
5421         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5422                       (label_ref (match_operand 0 "" ""))
5423                       (pc)))]
5424   ""
5425   "
5426 {
5427   if (TARGET_SHMEDIA)
5428     {
5429       if (sh_compare_op0 != const0_rtx)
5430         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5431       if (sh_compare_op1 != const0_rtx)
5432         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5433       emit_jump_insn (gen_bgtu_media (operands[0],
5434                                       sh_compare_op0, sh_compare_op1));
5435       DONE;
5436     }
5437
5438   from_compare (operands, GTU);
5439 }")
5440
5441 (define_expand "bltu"
5442   [(set (pc)
5443         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5444                       (label_ref (match_operand 0 "" ""))
5445                       (pc)))]
5446   ""
5447   "
5448 {
5449   if (TARGET_SHMEDIA)
5450     {
5451       if (sh_compare_op0 != const0_rtx)
5452         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5453       if (sh_compare_op1 != const0_rtx)
5454         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5455       emit_jump_insn (gen_bgtu_media (operands[0],
5456                                       sh_compare_op1, sh_compare_op0));
5457       DONE;
5458     }
5459
5460   from_compare (operands, GEU);
5461 }")
5462
5463 (define_expand "bgeu"
5464   [(set (pc)
5465         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5466                       (label_ref (match_operand 0 "" ""))
5467                       (pc)))]
5468   ""
5469   "
5470 {
5471   if (TARGET_SHMEDIA)
5472     {
5473       if (sh_compare_op0 != const0_rtx)
5474         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5475       if (sh_compare_op1 != const0_rtx)
5476         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5477       emit_jump_insn (gen_bgeu_media (operands[0],
5478                                       sh_compare_op0, sh_compare_op1));
5479       DONE;
5480     }
5481
5482   from_compare (operands, GEU);
5483 }")
5484
5485 (define_expand "bleu"
5486   [(set (pc)
5487         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5488                       (label_ref (match_operand 0 "" ""))
5489                       (pc)))]
5490   ""
5491   "
5492 {
5493   if (TARGET_SHMEDIA)
5494     {
5495       if (sh_compare_op0 != const0_rtx)
5496         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5497       if (sh_compare_op1 != const0_rtx)
5498         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5499       emit_jump_insn (gen_bgeu_media (operands[0],
5500                                       sh_compare_op1, sh_compare_op0));
5501       DONE;
5502     }
5503
5504   from_compare (operands, GTU);
5505 }")
5506
5507 (define_expand "bunordered"
5508   [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
5509    (set (pc)
5510         (if_then_else (ne (match_dup 1) (const_int 0))
5511                       (label_ref:DI (match_operand 0 "" ""))
5512                       (pc)))]
5513   "TARGET_SHMEDIA"
5514   "
5515 {
5516   operands[1] = gen_reg_rtx (DImode);
5517   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
5518   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
5519 }")
5520 \f
5521 ;; ------------------------------------------------------------------------
5522 ;; Jump and linkage insns
5523 ;; ------------------------------------------------------------------------
5524
5525 (define_insn "jump_compact"
5526   [(set (pc)
5527         (label_ref (match_operand 0 "" "")))]
5528   "TARGET_SH1"
5529   "*
5530 {
5531   /* The length is 16 if the delay slot is unfilled.  */
5532   if (get_attr_length(insn) > 4)
5533     return output_far_jump(insn, operands[0]);
5534   else
5535     return   \"bra      %l0%#\";
5536 }"
5537   [(set_attr "type" "jump")
5538    (set_attr "needs_delay_slot" "yes")])
5539
5540 ;; ??? It would be much saner to explicitly use the scratch register
5541 ;; in the jump insn, and have indirect_jump_scratch only set it,
5542 ;; but fill_simple_delay_slots would refuse to do delay slot filling
5543 ;; from the target then, as it uses simplejump_p.
5544 ;;(define_insn "jump_compact_far"
5545 ;;  [(set (pc)
5546 ;;      (label_ref (match_operand 0 "" "")))
5547 ;;   (use (match_operand 1 "register_operand" "r")]
5548 ;;  "TARGET_SH1"
5549 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
5550 ;;  [(set_attr "type" "jump")
5551 ;;   (set_attr "needs_delay_slot" "yes")])
5552
5553 (define_insn "jump_media"
5554   [(set (pc)
5555         (match_operand:DI 0 "target_operand" "b"))]
5556   "TARGET_SHMEDIA"
5557   "blink        %0, r63"
5558   [(set_attr "type" "jump_media")])
5559
5560 (define_expand "jump"
5561   [(set (pc)
5562         (label_ref (match_operand 0 "" "")))]
5563   ""
5564   "
5565 {
5566   if (TARGET_SH1)
5567     emit_jump_insn (gen_jump_compact (operands[0]));
5568   else if (TARGET_SHMEDIA)
5569     {
5570       if (reload_in_progress || reload_completed)
5571         FAIL;
5572       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode,
5573                                                          operands[0])));
5574     }
5575   DONE;
5576 }")
5577
5578 (define_insn "force_mode_for_call"
5579   [(use (reg:PSI FPSCR_REG))]
5580   "TARGET_SHCOMPACT"
5581   ""
5582   [(set_attr "length" "0")
5583    (set (attr "fp_mode")
5584         (if_then_else (eq_attr "fpu_single" "yes")
5585                       (const_string "single") (const_string "double")))])
5586
5587 (define_insn "calli"
5588   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5589          (match_operand 1 "" ""))
5590    (use (reg:PSI FPSCR_REG))
5591    (clobber (reg:SI PR_REG))]
5592   "TARGET_SH1"
5593   "jsr  @%0%#"
5594   [(set_attr "type" "call")
5595    (set (attr "fp_mode")
5596         (if_then_else (eq_attr "fpu_single" "yes")
5597                       (const_string "single") (const_string "double")))
5598    (set_attr "needs_delay_slot" "yes")
5599    (set_attr "fp_set" "unknown")])
5600
5601 ;; This is a pc-rel call, using bsrf, for use with PIC.
5602
5603 (define_insn "calli_pcrel"
5604   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5605          (match_operand 1 "" ""))
5606    (use (reg:PSI FPSCR_REG))
5607    (use (reg:SI PIC_REG))
5608    (use (match_operand 2 "" ""))
5609    (clobber (reg:SI PR_REG))]
5610   "TARGET_SH2"
5611   "bsrf %0\\n%O2:%#"
5612   [(set_attr "type" "call")
5613    (set (attr "fp_mode")
5614         (if_then_else (eq_attr "fpu_single" "yes")
5615                       (const_string "single") (const_string "double")))
5616    (set_attr "needs_delay_slot" "yes")
5617    (set_attr "fp_set" "unknown")])
5618
5619 (define_insn_and_split "call_pcrel"
5620   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
5621          (match_operand 1 "" ""))
5622    (use (reg:PSI FPSCR_REG))
5623    (use (reg:SI PIC_REG))
5624    (clobber (reg:SI PR_REG))
5625    (clobber (match_scratch:SI 2 "=r"))]
5626   "TARGET_SH2"
5627   "#"
5628   "reload_completed"
5629   [(const_int 0)]
5630   "
5631 {
5632   rtx lab = PATTERN (gen_call_site ());
5633
5634   if (SYMBOL_REF_LOCAL_P (operands[0]))
5635     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
5636   else
5637     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
5638   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
5639   DONE;
5640 }"
5641   [(set_attr "type" "call")
5642    (set (attr "fp_mode")
5643         (if_then_else (eq_attr "fpu_single" "yes")
5644                       (const_string "single") (const_string "double")))
5645    (set_attr "needs_delay_slot" "yes")
5646    (set_attr "fp_set" "unknown")])
5647
5648 (define_insn "call_compact"
5649   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5650          (match_operand 1 "" ""))
5651    (match_operand 2 "immediate_operand" "n")
5652    (use (reg:SI R0_REG))
5653    (use (reg:SI R1_REG))
5654    (use (reg:PSI FPSCR_REG))
5655    (clobber (reg:SI PR_REG))]
5656   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5657   "jsr  @%0%#"
5658   [(set_attr "type" "call")
5659    (set (attr "fp_mode")
5660         (if_then_else (eq_attr "fpu_single" "yes")
5661                       (const_string "single") (const_string "double")))
5662    (set_attr "needs_delay_slot" "yes")])
5663
5664 (define_insn "call_compact_rettramp"
5665   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5666          (match_operand 1 "" ""))
5667    (match_operand 2 "immediate_operand" "n")
5668    (use (reg:SI R0_REG))
5669    (use (reg:SI R1_REG))
5670    (use (reg:PSI FPSCR_REG))
5671    (clobber (reg:SI R10_REG))
5672    (clobber (reg:SI PR_REG))]
5673   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5674   "jsr  @%0%#"
5675   [(set_attr "type" "call")
5676    (set (attr "fp_mode")
5677         (if_then_else (eq_attr "fpu_single" "yes")
5678                       (const_string "single") (const_string "double")))
5679    (set_attr "needs_delay_slot" "yes")])
5680
5681 (define_insn "call_media"
5682   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b"))
5683          (match_operand 1 "" ""))
5684    (clobber (reg:DI PR_MEDIA_REG))]
5685   "TARGET_SHMEDIA"
5686   "blink        %0, r18"
5687   [(set_attr "type" "jump_media")])
5688
5689 (define_insn "call_valuei"
5690   [(set (match_operand 0 "" "=rf")
5691         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5692               (match_operand 2 "" "")))
5693    (use (reg:PSI FPSCR_REG))
5694    (clobber (reg:SI PR_REG))]
5695   "TARGET_SH1"
5696   "jsr  @%1%#"
5697   [(set_attr "type" "call")
5698    (set (attr "fp_mode")
5699         (if_then_else (eq_attr "fpu_single" "yes")
5700                       (const_string "single") (const_string "double")))
5701    (set_attr "needs_delay_slot" "yes")
5702    (set_attr "fp_set" "unknown")])
5703
5704 (define_insn "call_valuei_pcrel"
5705   [(set (match_operand 0 "" "=rf")
5706         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5707               (match_operand 2 "" "")))
5708    (use (reg:PSI FPSCR_REG))
5709    (use (reg:SI PIC_REG))
5710    (use (match_operand 3 "" ""))
5711    (clobber (reg:SI PR_REG))]
5712   "TARGET_SH2"
5713   "bsrf %1\\n%O3:%#"
5714   [(set_attr "type" "call")
5715    (set (attr "fp_mode")
5716         (if_then_else (eq_attr "fpu_single" "yes")
5717                       (const_string "single") (const_string "double")))
5718    (set_attr "needs_delay_slot" "yes")
5719    (set_attr "fp_set" "unknown")])
5720
5721 (define_insn_and_split "call_value_pcrel"
5722   [(set (match_operand 0 "" "=rf")
5723         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
5724               (match_operand 2 "" "")))
5725    (use (reg:PSI FPSCR_REG))
5726    (use (reg:SI PIC_REG))
5727    (clobber (reg:SI PR_REG))
5728    (clobber (match_scratch:SI 3 "=r"))]
5729   "TARGET_SH2"
5730   "#"
5731   "reload_completed"
5732   [(const_int 0)]
5733   "
5734 {
5735   rtx lab = PATTERN (gen_call_site ());
5736
5737   if (SYMBOL_REF_LOCAL_P (operands[1]))
5738     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
5739   else
5740     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
5741   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
5742                                          operands[2], lab));
5743   DONE;
5744 }"
5745   [(set_attr "type" "call")
5746    (set (attr "fp_mode")
5747         (if_then_else (eq_attr "fpu_single" "yes")
5748                       (const_string "single") (const_string "double")))
5749    (set_attr "needs_delay_slot" "yes")
5750    (set_attr "fp_set" "unknown")])
5751
5752 (define_insn "call_value_compact"
5753   [(set (match_operand 0 "" "=rf")
5754         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5755               (match_operand 2 "" "")))
5756    (match_operand 3 "immediate_operand" "n")
5757    (use (reg:SI R0_REG))
5758    (use (reg:SI R1_REG))
5759    (use (reg:PSI FPSCR_REG))
5760    (clobber (reg:SI PR_REG))]
5761   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5762   "jsr  @%1%#"
5763   [(set_attr "type" "call")
5764    (set (attr "fp_mode")
5765         (if_then_else (eq_attr "fpu_single" "yes")
5766                       (const_string "single") (const_string "double")))
5767    (set_attr "needs_delay_slot" "yes")])
5768
5769 (define_insn "call_value_compact_rettramp"
5770   [(set (match_operand 0 "" "=rf")
5771         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5772               (match_operand 2 "" "")))
5773    (match_operand 3 "immediate_operand" "n")
5774    (use (reg:SI R0_REG))
5775    (use (reg:SI R1_REG))
5776    (use (reg:PSI FPSCR_REG))
5777    (clobber (reg:SI R10_REG))
5778    (clobber (reg:SI PR_REG))]
5779   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5780   "jsr  @%1%#"
5781   [(set_attr "type" "call")
5782    (set (attr "fp_mode")
5783         (if_then_else (eq_attr "fpu_single" "yes")
5784                       (const_string "single") (const_string "double")))
5785    (set_attr "needs_delay_slot" "yes")])
5786
5787 (define_insn "call_value_media"
5788   [(set (match_operand 0 "" "=rf")
5789         (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b"))
5790               (match_operand 2 "" "")))
5791    (clobber (reg:DI PR_MEDIA_REG))]
5792   "TARGET_SHMEDIA"
5793   "blink        %1, r18"
5794   [(set_attr "type" "jump_media")])
5795
5796 (define_expand "call"
5797   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5798                             (match_operand 1 "" ""))
5799               (match_operand 2 "" "")
5800               (use (reg:PSI FPSCR_REG))
5801               (clobber (reg:SI PR_REG))])]
5802   ""
5803   "
5804 {
5805   if (TARGET_SHMEDIA)
5806     {
5807       operands[0] = XEXP (operands[0], 0);
5808       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
5809         {
5810           if (! SYMBOL_REF_LOCAL_P (operands[0]))
5811             {
5812               rtx reg = gen_reg_rtx (Pmode);
5813
5814               emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5815               operands[0] = reg;
5816             }
5817           else
5818             {
5819               operands[0] = gen_sym2PIC (operands[0]);
5820               PUT_MODE (operands[0], Pmode);
5821             }
5822         }
5823       if (GET_MODE (operands[0]) == SImode)
5824         {
5825           if (GET_CODE (operands[0]) == REG)
5826             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5827           else if (GET_CODE (operands[0]) == SUBREG)
5828             {
5829               operands[0] = SUBREG_REG (operands[0]);
5830               if (GET_MODE (operands[0]) != DImode)
5831                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5832             }
5833           else if (TARGET_SHMEDIA64)
5834             {
5835               operands[0] = shallow_copy_rtx (operands[0]);
5836               PUT_MODE (operands[0], DImode);
5837             }
5838           else
5839             {
5840               rtx reg = gen_reg_rtx (DImode);
5841
5842               operands[0] = copy_to_mode_reg (SImode, operands[0]);
5843               emit_insn (gen_extendsidi2 (reg, operands[0]));
5844               operands[0] = reg;
5845             }
5846         }
5847       if (! target_reg_operand (operands[0], DImode))
5848         operands[0] = copy_to_mode_reg (DImode, operands[0]);
5849       emit_call_insn (gen_call_media (operands[0], operands[1]));
5850       DONE;
5851     }
5852   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
5853     {
5854       rtx cookie_rtx = operands[2];
5855       long cookie = INTVAL (cookie_rtx);
5856       rtx func = XEXP (operands[0], 0);
5857       rtx r0, r1;
5858
5859       if (flag_pic)
5860         {
5861           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
5862             {
5863               rtx reg = gen_reg_rtx (Pmode);
5864
5865               emit_insn (gen_symGOTPLT2reg (reg, func));
5866               func = reg;
5867             }
5868           else
5869             func = legitimize_pic_address (func, Pmode, 0);
5870         }
5871
5872       r0 = gen_rtx_REG (SImode, R0_REG);
5873       r1 = gen_rtx_REG (SImode, R1_REG);
5874
5875       /* Since such a call function may use all call-clobbered
5876          registers, we force a mode switch earlier, so that we don't
5877          run out of registers when adjusting fpscr for the call.  */
5878       emit_insn (gen_force_mode_for_call ());
5879
5880       operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\");
5881       if (flag_pic)
5882         {
5883           rtx reg = gen_reg_rtx (Pmode);
5884
5885           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5886           operands[0] = reg;
5887         }
5888       operands[0] = force_reg (SImode, operands[0]);
5889
5890       emit_move_insn (r0, func);
5891       emit_move_insn (r1, cookie_rtx);
5892
5893       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5894         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
5895                                                    operands[2]));
5896       else
5897         emit_call_insn (gen_call_compact (operands[0], operands[1],
5898                                           operands[2]));
5899
5900       DONE;
5901     }
5902   else if (TARGET_SHCOMPACT && flag_pic
5903            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5904            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
5905     {
5906       rtx reg = gen_reg_rtx (Pmode);
5907
5908       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
5909       XEXP (operands[0], 0) = reg;
5910     }
5911   if (flag_pic && TARGET_SH2
5912       && GET_CODE (operands[0]) == MEM
5913       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5914     {
5915       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
5916       DONE;
5917     }
5918   else
5919   {
5920     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
5921     operands[1] = operands[2];
5922   }
5923
5924   emit_call_insn (gen_calli (operands[0], operands[1]));
5925   DONE;
5926 }")
5927
5928 (define_insn "call_pop_compact"
5929   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5930          (match_operand 1 "" ""))
5931    (match_operand 2 "immediate_operand" "n")
5932    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5933                                  (match_operand 3 "immediate_operand" "n")))
5934    (use (reg:SI R0_REG))
5935    (use (reg:SI R1_REG))
5936    (use (reg:PSI FPSCR_REG))
5937    (clobber (reg:SI PR_REG))]
5938   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5939   "jsr  @%0%#"
5940   [(set_attr "type" "call")
5941    (set (attr "fp_mode")
5942         (if_then_else (eq_attr "fpu_single" "yes")
5943                       (const_string "single") (const_string "double")))
5944    (set_attr "needs_delay_slot" "yes")])
5945
5946 (define_insn "call_pop_compact_rettramp"
5947   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5948          (match_operand 1 "" ""))
5949    (match_operand 2 "immediate_operand" "n")
5950    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5951                                  (match_operand 3 "immediate_operand" "n")))
5952    (use (reg:SI R0_REG))
5953    (use (reg:SI R1_REG))
5954    (use (reg:PSI FPSCR_REG))
5955    (clobber (reg:SI R10_REG))
5956    (clobber (reg:SI PR_REG))]
5957   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5958   "jsr  @%0%#"
5959   [(set_attr "type" "call")
5960    (set (attr "fp_mode")
5961         (if_then_else (eq_attr "fpu_single" "yes")
5962                       (const_string "single") (const_string "double")))
5963    (set_attr "needs_delay_slot" "yes")])
5964
5965 (define_expand "call_pop"
5966   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5967                     (match_operand 1 "" ""))
5968              (match_operand 2 "" "")
5969              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5970                                            (match_operand 3 "" "")))])]
5971   "TARGET_SHCOMPACT"
5972   "
5973 {
5974   rtx cookie_rtx;
5975   long cookie;
5976   rtx func;
5977   rtx r0, r1;
5978
5979   gcc_assert (operands[2] && INTVAL (operands[2]));
5980   cookie_rtx = operands[2];
5981   cookie = INTVAL (cookie_rtx);
5982   func = XEXP (operands[0], 0);
5983
5984   if (flag_pic)
5985     {
5986       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
5987         {
5988           rtx reg = gen_reg_rtx (Pmode);
5989           emit_insn (gen_symGOTPLT2reg (reg, func));
5990           func = reg;
5991         }
5992       else
5993         func = legitimize_pic_address (func, Pmode, 0);
5994     }
5995
5996   r0 = gen_rtx_REG (SImode, R0_REG);
5997   r1 = gen_rtx_REG (SImode, R1_REG);
5998
5999   /* Since such a call function may use all call-clobbered
6000      registers, we force a mode switch earlier, so that we don't
6001      run out of registers when adjusting fpscr for the call.  */
6002   emit_insn (gen_force_mode_for_call ());
6003
6004   operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6005   if (flag_pic)
6006     {
6007       rtx reg = gen_reg_rtx (Pmode);
6008
6009       emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
6010       operands[0] = reg;
6011     }
6012   operands[0] = force_reg (SImode, operands[0]);
6013
6014   emit_move_insn (r0, func);
6015   emit_move_insn (r1, cookie_rtx);
6016
6017   if (cookie & CALL_COOKIE_RET_TRAMP (1))
6018     emit_call_insn (gen_call_pop_compact_rettramp
6019                      (operands[0], operands[1], operands[2], operands[3]));
6020   else
6021     emit_call_insn (gen_call_pop_compact
6022                      (operands[0], operands[1], operands[2], operands[3]));
6023
6024   DONE;
6025 }")
6026
6027 (define_expand "call_value"
6028   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
6029                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
6030                                  (match_operand 2 "" "")))
6031               (match_operand 3 "" "")
6032               (use (reg:PSI FPSCR_REG))
6033               (clobber (reg:SI PR_REG))])]
6034   ""
6035   "
6036 {
6037   if (TARGET_SHMEDIA)
6038     {
6039       operands[1] = XEXP (operands[1], 0);
6040       if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
6041         {
6042           if (! SYMBOL_REF_LOCAL_P (operands[1]))
6043             {
6044               rtx reg = gen_reg_rtx (Pmode);
6045
6046               emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6047               operands[1] = reg;
6048             }
6049           else
6050             {
6051               operands[1] = gen_sym2PIC (operands[1]);
6052               PUT_MODE (operands[1], Pmode);
6053             }
6054         }
6055       if (GET_MODE (operands[1]) == SImode)
6056         {
6057           if (GET_CODE (operands[1]) == REG)
6058             operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6059           else if (GET_CODE (operands[1]) == SUBREG)
6060             {
6061               operands[1] = SUBREG_REG (operands[1]);
6062               if (GET_MODE (operands[1]) != DImode)
6063                 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6064             }
6065           else if (TARGET_SHMEDIA64)
6066             {
6067               operands[1] = shallow_copy_rtx (operands[1]);
6068               PUT_MODE (operands[1], DImode);
6069             }
6070           else
6071             {
6072               rtx reg = gen_reg_rtx (DImode);
6073
6074               operands[1] = copy_to_mode_reg (SImode, operands[1]);
6075               emit_insn (gen_extendsidi2 (reg, operands[1]));
6076               operands[1] = reg;
6077             }
6078         }
6079       if (! target_reg_operand (operands[1], DImode))
6080         operands[1] = copy_to_mode_reg (DImode, operands[1]);
6081       emit_call_insn (gen_call_value_media (operands[0], operands[1],
6082                                             operands[2]));
6083       DONE;
6084     }
6085   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
6086     {
6087       rtx cookie_rtx = operands[3];
6088       long cookie = INTVAL (cookie_rtx);
6089       rtx func = XEXP (operands[1], 0);
6090       rtx r0, r1;
6091
6092       if (flag_pic)
6093         {
6094           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
6095             {
6096               rtx reg = gen_reg_rtx (Pmode);
6097
6098               emit_insn (gen_symGOTPLT2reg (reg, func));
6099               func = reg;
6100             }
6101           else
6102             func = legitimize_pic_address (func, Pmode, 0);
6103         }
6104
6105       r0 = gen_rtx_REG (SImode, R0_REG);
6106       r1 = gen_rtx_REG (SImode, R1_REG);
6107
6108       /* Since such a call function may use all call-clobbered
6109          registers, we force a mode switch earlier, so that we don't
6110          run out of registers when adjusting fpscr for the call.  */
6111       emit_insn (gen_force_mode_for_call ());
6112
6113       operands[1] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6114       if (flag_pic)
6115         {
6116           rtx reg = gen_reg_rtx (Pmode);
6117
6118           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6119           operands[1] = reg;
6120         }
6121       operands[1] = force_reg (SImode, operands[1]);
6122
6123       emit_move_insn (r0, func);
6124       emit_move_insn (r1, cookie_rtx);
6125
6126       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6127         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
6128                                                          operands[1],
6129                                                          operands[2],
6130                                                          operands[3]));
6131       else
6132         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
6133                                                 operands[2], operands[3]));
6134
6135       DONE;
6136     }
6137   else if (TARGET_SHCOMPACT && flag_pic
6138            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6139            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
6140     {
6141       rtx reg = gen_reg_rtx (Pmode);
6142
6143       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
6144       XEXP (operands[1], 0) = reg;
6145     }
6146   if (flag_pic && TARGET_SH2
6147       && GET_CODE (operands[1]) == MEM
6148       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6149     {
6150       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
6151                                             operands[2]));
6152       DONE;
6153     }
6154   else
6155     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
6156
6157   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
6158   DONE;
6159 }")
6160
6161 (define_insn "sibcalli"
6162   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
6163          (match_operand 1 "" ""))
6164    (use (reg:PSI FPSCR_REG))
6165    (return)]
6166   "TARGET_SH1"
6167   "jmp  @%0%#"
6168   [(set_attr "needs_delay_slot" "yes")
6169    (set (attr "fp_mode")
6170         (if_then_else (eq_attr "fpu_single" "yes")
6171                       (const_string "single") (const_string "double")))
6172    (set_attr "type" "jump_ind")])
6173
6174 (define_insn "sibcalli_pcrel"
6175   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
6176          (match_operand 1 "" ""))
6177    (use (match_operand 2 "" ""))
6178    (use (reg:PSI FPSCR_REG))
6179    (return)]
6180   "TARGET_SH2"
6181   "braf %0\\n%O2:%#"
6182   [(set_attr "needs_delay_slot" "yes")
6183    (set (attr "fp_mode")
6184         (if_then_else (eq_attr "fpu_single" "yes")
6185                       (const_string "single") (const_string "double")))
6186    (set_attr "type" "jump_ind")])
6187
6188 (define_insn_and_split "sibcall_pcrel"
6189   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
6190          (match_operand 1 "" ""))
6191    (use (reg:PSI FPSCR_REG))
6192    (clobber (match_scratch:SI 2 "=k"))
6193    (return)]
6194   "TARGET_SH2"
6195   "#"
6196   "reload_completed"
6197   [(const_int 0)]
6198   "
6199 {
6200   rtx lab = PATTERN (gen_call_site ());
6201   rtx call_insn;
6202
6203   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
6204   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
6205                                                   lab));
6206   SIBLING_CALL_P (call_insn) = 1;
6207   DONE;
6208 }"
6209   [(set_attr "needs_delay_slot" "yes")
6210    (set (attr "fp_mode")
6211         (if_then_else (eq_attr "fpu_single" "yes")
6212                       (const_string "single") (const_string "double")))
6213    (set_attr "type" "jump_ind")])
6214
6215 (define_insn "sibcall_compact"
6216   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
6217          (match_operand 1 "" ""))
6218    (return)
6219    (use (match_operand:SI 2 "register_operand" "z,x"))
6220    (use (reg:SI R1_REG))
6221    (use (reg:PSI FPSCR_REG))
6222    ;; We want to make sure the `x' above will only match MACH_REG
6223    ;; because sibcall_epilogue may clobber MACL_REG.
6224    (clobber (reg:SI MACL_REG))]
6225   "TARGET_SHCOMPACT"
6226   "@
6227         jmp     @%0%#
6228         jmp     @%0\\n  sts     %2, r0"
6229   [(set_attr "needs_delay_slot" "yes,no")
6230    (set_attr "length" "2,4")
6231    (set (attr "fp_mode") (const_string "single"))
6232    (set_attr "type" "jump_ind")])
6233
6234 (define_insn "sibcall_media"
6235   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
6236          (match_operand 1 "" ""))
6237    (use (reg:SI PR_MEDIA_REG))
6238    (return)]
6239   "TARGET_SHMEDIA"
6240   "blink        %0, r63"
6241   [(set_attr "type" "jump_media")])
6242
6243 (define_expand "sibcall"
6244   [(parallel
6245     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
6246            (match_operand 1 "" ""))
6247      (match_operand 2 "" "")
6248      (use (reg:PSI FPSCR_REG))
6249      (return)])]
6250   ""
6251   "
6252 {
6253   if (TARGET_SHMEDIA)
6254     {
6255       operands[0] = XEXP (operands[0], 0);
6256       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
6257         {
6258           if (! SYMBOL_REF_LOCAL_P (operands[0]))
6259             {
6260               rtx reg = gen_reg_rtx (Pmode);
6261
6262               /* We must not use GOTPLT for sibcalls, because PIC_REG
6263                  must be restored before the PLT code gets to run.  */
6264               emit_insn (gen_symGOT2reg (reg, operands[0]));
6265               operands[0] = reg;
6266             }
6267           else
6268             {
6269               operands[0] = gen_sym2PIC (operands[0]);
6270               PUT_MODE (operands[0], Pmode);
6271             }
6272         }
6273       if (GET_MODE (operands[0]) == SImode)
6274         {
6275           if (GET_CODE (operands[0]) == REG)
6276             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6277           else if (GET_CODE (operands[0]) == SUBREG)
6278             {
6279               operands[0] = SUBREG_REG (operands[0]);
6280               if (GET_MODE (operands[0]) != DImode)
6281                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6282             }
6283           else
6284             {
6285               operands[0] = shallow_copy_rtx (operands[0]);
6286               PUT_MODE (operands[0], DImode);
6287             }
6288         }
6289       if (! target_reg_operand (operands[0], DImode))
6290         operands[0] = copy_to_mode_reg (DImode, operands[0]);
6291       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
6292       DONE;
6293     }
6294   else if (TARGET_SHCOMPACT && operands[2]
6295            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
6296     {
6297       rtx cookie_rtx = operands[2];
6298       long cookie = INTVAL (cookie_rtx);
6299       rtx func = XEXP (operands[0], 0);
6300       rtx mach, r1;
6301
6302       if (flag_pic)
6303         {
6304           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
6305             {
6306               rtx reg = gen_reg_rtx (Pmode);
6307
6308               emit_insn (gen_symGOT2reg (reg, func));
6309               func = reg;
6310             }
6311           else
6312             func = legitimize_pic_address (func, Pmode, 0);
6313         }
6314
6315       /* FIXME: if we could tell whether all argument registers are
6316          already taken, we could decide whether to force the use of
6317          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
6318          simple way to tell.  We could use the CALL_COOKIE, but we
6319          can't currently tell a register used for regular argument
6320          passing from one that is unused.  If we leave it up to reload
6321          to decide which register to use, it seems to always choose
6322          R0_REG, which leaves no available registers in SIBCALL_REGS
6323          to hold the address of the trampoline.  */
6324       mach = gen_rtx_REG (SImode, MACH_REG);
6325       r1 = gen_rtx_REG (SImode, R1_REG);
6326
6327       /* Since such a call function may use all call-clobbered
6328          registers, we force a mode switch earlier, so that we don't
6329          run out of registers when adjusting fpscr for the call.  */
6330       emit_insn (gen_force_mode_for_call ());
6331
6332       operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6333       if (flag_pic)
6334         {
6335           rtx reg = gen_reg_rtx (Pmode);
6336
6337           emit_insn (gen_symGOT2reg (reg, operands[0]));
6338           operands[0] = reg;
6339         }
6340       operands[0] = force_reg (SImode, operands[0]);
6341
6342       /* We don't need a return trampoline, since the callee will
6343          return directly to the upper caller.  */
6344       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6345         {
6346           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
6347           cookie_rtx = GEN_INT (cookie);
6348         }
6349
6350       emit_move_insn (mach, func);
6351       emit_move_insn (r1, cookie_rtx);
6352
6353       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
6354       DONE;
6355     }
6356   else if (TARGET_SHCOMPACT && flag_pic
6357            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6358            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
6359     {
6360       rtx reg = gen_reg_rtx (Pmode);
6361
6362       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
6363       XEXP (operands[0], 0) = reg;
6364     }
6365   if (flag_pic && TARGET_SH2
6366       && GET_CODE (operands[0]) == MEM
6367       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6368       /* The PLT needs the PIC register, but the epilogue would have
6369          to restore it, so we can only use PC-relative PIC calls for
6370          static functions.  */
6371       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
6372     {
6373       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
6374       DONE;
6375     }
6376   else
6377     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
6378
6379   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
6380   DONE;
6381 }")
6382
6383 (define_expand "sibcall_value"
6384   [(set (match_operand 0 "" "")
6385         (call (match_operand 1 "" "")
6386               (match_operand 2 "" "")))
6387    (match_operand 3 "" "")]
6388   ""
6389   "
6390 {
6391   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
6392   DONE;
6393 }")
6394
6395 (define_insn "call_value_pop_compact"
6396   [(set (match_operand 0 "" "=rf")
6397         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6398               (match_operand 2 "" "")))
6399    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6400                                  (match_operand 4 "immediate_operand" "n")))
6401    (match_operand 3 "immediate_operand" "n")
6402    (use (reg:SI R0_REG))
6403    (use (reg:SI R1_REG))
6404    (use (reg:PSI FPSCR_REG))
6405    (clobber (reg:SI PR_REG))]
6406   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6407   "jsr  @%1%#"
6408   [(set_attr "type" "call")
6409    (set (attr "fp_mode")
6410         (if_then_else (eq_attr "fpu_single" "yes")
6411                       (const_string "single") (const_string "double")))
6412    (set_attr "needs_delay_slot" "yes")])
6413
6414 (define_insn "call_value_pop_compact_rettramp"
6415   [(set (match_operand 0 "" "=rf")
6416         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6417               (match_operand 2 "" "")))
6418    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6419                                  (match_operand 4 "immediate_operand" "n")))
6420    (match_operand 3 "immediate_operand" "n")
6421    (use (reg:SI R0_REG))
6422    (use (reg:SI R1_REG))
6423    (use (reg:PSI FPSCR_REG))
6424    (clobber (reg:SI R10_REG))
6425    (clobber (reg:SI PR_REG))]
6426   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6427   "jsr  @%1%#"
6428   [(set_attr "type" "call")
6429    (set (attr "fp_mode")
6430         (if_then_else (eq_attr "fpu_single" "yes")
6431                       (const_string "single") (const_string "double")))
6432    (set_attr "needs_delay_slot" "yes")])
6433
6434 (define_expand "call_value_pop"
6435   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
6436                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
6437                                  (match_operand 2 "" "")))
6438               (match_operand 3 "" "")
6439               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6440                                             (match_operand 4 "" "")))])]
6441   "TARGET_SHCOMPACT"
6442   "
6443 {
6444   rtx cookie_rtx;
6445   long cookie;
6446   rtx func;
6447   rtx r0, r1;
6448
6449   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
6450   cookie_rtx = operands[3];
6451   cookie = INTVAL (cookie_rtx);
6452   func = XEXP (operands[1], 0);
6453
6454   if (flag_pic)
6455     {
6456       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
6457         {
6458           rtx reg = gen_reg_rtx (Pmode);
6459
6460           emit_insn (gen_symGOTPLT2reg (reg, func));
6461           func = reg;
6462         }
6463       else
6464         func = legitimize_pic_address (func, Pmode, 0);
6465     }
6466
6467   r0 = gen_rtx_REG (SImode, R0_REG);
6468   r1 = gen_rtx_REG (SImode, R1_REG);
6469
6470   /* Since such a call function may use all call-clobbered
6471      registers, we force a mode switch earlier, so that we don't
6472      run out of registers when adjusting fpscr for the call.  */
6473   emit_insn (gen_force_mode_for_call ());
6474
6475   operands[1] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6476   if (flag_pic)
6477     {
6478       rtx reg = gen_reg_rtx (Pmode);
6479
6480       emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6481       operands[1] = reg;
6482     }
6483   operands[1] = force_reg (SImode, operands[1]);
6484
6485   emit_move_insn (r0, func);
6486   emit_move_insn (r1, cookie_rtx);
6487
6488   if (cookie & CALL_COOKIE_RET_TRAMP (1))
6489     emit_call_insn (gen_call_value_pop_compact_rettramp
6490                         (operands[0], operands[1], operands[2],
6491                          operands[3], operands[4]));
6492   else
6493     emit_call_insn (gen_call_value_pop_compact
6494                         (operands[0], operands[1], operands[2],
6495                          operands[3], operands[4]));
6496
6497   DONE;
6498 }")
6499
6500 (define_expand "sibcall_epilogue"
6501   [(return)]
6502   ""
6503   "
6504 {
6505   sh_expand_epilogue (1);
6506   if (TARGET_SHCOMPACT)
6507     {
6508       rtx insn, set;
6509
6510       /* If epilogue clobbers r0, preserve it in macl.  */
6511       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6512         if ((set = single_set (insn))
6513             && GET_CODE (SET_DEST (set)) == REG
6514             && REGNO (SET_DEST (set)) == R0_REG)
6515           {
6516             rtx r0 = gen_rtx_REG (SImode, R0_REG);
6517             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
6518             rtx i;
6519
6520             /* We can't tell at this point whether the sibcall is a
6521                sibcall_compact and, if it is, whether it uses r0 or
6522                mach as operand 2, so let the instructions that
6523                preserve r0 be optimized away if r0 turns out to be
6524                dead.  */
6525             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
6526             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6527                                                REG_NOTES (i));
6528             i = emit_move_insn (r0, tmp);
6529             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6530                                                REG_NOTES (i));
6531             break;
6532           }
6533     }
6534   DONE;
6535 }")
6536
6537 (define_insn "indirect_jump_compact"
6538   [(set (pc)
6539         (match_operand:SI 0 "arith_reg_operand" "r"))]
6540   "TARGET_SH1"
6541   "jmp  @%0%#"
6542   [(set_attr "needs_delay_slot" "yes")
6543    (set_attr "type" "jump_ind")])
6544
6545 (define_expand "indirect_jump"
6546   [(set (pc)
6547         (match_operand 0 "register_operand" ""))]
6548   ""
6549   "
6550 {
6551   if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode)
6552     operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6553 }")
6554
6555 ;; The use of operand 1 / 2 helps us distinguish case table jumps
6556 ;; which can be present in structured code from indirect jumps which can not
6557 ;; be present in structured code.  This allows -fprofile-arcs to work.
6558
6559 ;; For SH1 processors.
6560 (define_insn "casesi_jump_1"
6561   [(set (pc)
6562         (match_operand:SI 0 "register_operand" "r"))
6563    (use (label_ref (match_operand 1 "" "")))]
6564   "TARGET_SH1"
6565   "jmp  @%0%#"
6566   [(set_attr "needs_delay_slot" "yes")
6567    (set_attr "type" "jump_ind")])
6568
6569 ;; For all later processors.
6570 (define_insn "casesi_jump_2"
6571   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
6572                       (label_ref (match_operand 1 "" ""))))
6573    (use (label_ref (match_operand 2 "" "")))]
6574   "TARGET_SH2
6575    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
6576   "braf %0%#"
6577   [(set_attr "needs_delay_slot" "yes")
6578    (set_attr "type" "jump_ind")])
6579
6580 (define_insn "casesi_jump_media"
6581   [(set (pc) (match_operand:DI 0 "target_reg_operand" "b"))
6582    (use (label_ref (match_operand 1 "" "")))]
6583   "TARGET_SHMEDIA"
6584   "blink        %0, r63"
6585   [(set_attr "type" "jump_media")])
6586
6587 ;; Call subroutine returning any type.
6588 ;; ??? This probably doesn't work.
6589
6590 (define_expand "untyped_call"
6591   [(parallel [(call (match_operand 0 "" "")
6592                     (const_int 0))
6593               (match_operand 1 "" "")
6594               (match_operand 2 "" "")])]
6595   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
6596   "
6597 {
6598   int i;
6599
6600   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
6601
6602   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6603     {
6604       rtx set = XVECEXP (operands[2], 0, i);
6605       emit_move_insn (SET_DEST (set), SET_SRC (set));
6606     }
6607
6608   /* The optimizer does not know that the call sets the function value
6609      registers we stored in the result block.  We avoid problems by
6610      claiming that all hard registers are used and clobbered at this
6611      point.  */
6612   emit_insn (gen_blockage ());
6613
6614   DONE;
6615 }")
6616 \f
6617 ;; ------------------------------------------------------------------------
6618 ;; Misc insns
6619 ;; ------------------------------------------------------------------------
6620
6621 (define_insn "dect"
6622   [(set (reg:SI T_REG)
6623         (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1)))
6624    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
6625   "TARGET_SH2"
6626   "dt   %0"
6627   [(set_attr "type" "arith")])
6628
6629 (define_insn "nop"
6630   [(const_int 0)]
6631   ""
6632   "nop")
6633
6634 ;; Load address of a label. This is only generated by the casesi expand,
6635 ;; and by machine_dependent_reorg (fixing up fp moves).
6636 ;; This must use unspec, because this only works for labels that are
6637 ;; within range,
6638
6639 (define_insn "mova"
6640   [(set (reg:SI R0_REG)
6641         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
6642   "TARGET_SH1"
6643   "mova %O0,r0"
6644   [(set_attr "in_delay_slot" "no")
6645    (set_attr "type" "arith")])
6646
6647 ;; machine_dependent_reorg will make this a `mova'.
6648 (define_insn "mova_const"
6649   [(set (reg:SI R0_REG)
6650         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
6651   "TARGET_SH1"
6652   "#"
6653   [(set_attr "in_delay_slot" "no")
6654    (set_attr "type" "arith")])
6655
6656 (define_expand "GOTaddr2picreg"
6657   [(set (reg:SI R0_REG)
6658         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
6659                    UNSPEC_MOVA))
6660    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
6661    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6662   "" "
6663 {
6664   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
6665   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
6666
6667   if (TARGET_SH5)
6668     operands[1] = gen_datalabel_ref (operands[1]);
6669
6670   if (TARGET_SHMEDIA)
6671     {
6672       rtx tr = gen_rtx_REG (DImode, TR0_REG);
6673       rtx dipic = operands[0];
6674       rtx lab = PATTERN (gen_call_site ());
6675       rtx insn, equiv;
6676
6677       equiv = operands[1];
6678       operands[1] = gen_rtx_MINUS (DImode,
6679                                    operands[1],
6680                                    gen_rtx_CONST
6681                                    (DImode,
6682                                     gen_rtx_MINUS (DImode,
6683                                                    gen_rtx_CONST (DImode,
6684                                                                   lab),
6685                                                    pc_rtx)));
6686       operands[1] = gen_sym2PIC (operands[1]);
6687       PUT_MODE (operands[1], DImode);
6688
6689       if (GET_MODE (dipic) != DImode)
6690         dipic = gen_rtx_SUBREG (DImode, dipic, 0);
6691
6692       if (TARGET_SHMEDIA64)
6693         emit_insn (gen_movdi_const (dipic, operands[1]));
6694       else
6695         emit_insn (gen_movdi_const_32bit (dipic, operands[1]));
6696
6697       emit_insn (gen_ptrel (tr, dipic, lab));
6698
6699       if (GET_MODE (operands[0]) != GET_MODE (tr))
6700         tr = gen_lowpart (GET_MODE (operands[0]), tr);
6701
6702       insn = emit_move_insn (operands[0], tr);
6703
6704       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
6705                                             REG_NOTES (insn));
6706
6707       DONE;
6708     }
6709 }
6710 ")
6711
6712 (define_insn "*ptb"
6713   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6714         (const:DI (unspec:DI [(match_operand:DI 1 "" "Csy")]
6715                              UNSPEC_DATALABEL)))]
6716   "TARGET_SHMEDIA && flag_pic
6717    && EXTRA_CONSTRAINT_Csy (operands[1])"
6718   "ptb/u        datalabel %1, %0"
6719   [(set_attr "type" "pt_media")
6720    (set_attr "length" "*")])
6721
6722 (define_insn "ptrel"
6723   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6724         (plus:DI (match_operand:DI 1 "register_operand" "r")
6725               (pc)))
6726    (match_operand:DI 2 "" "")]
6727   "TARGET_SHMEDIA"
6728   "%O2: ptrel/u %1, %0"
6729   [(set_attr "type" "ptabs_media")])
6730
6731 (define_expand "builtin_setjmp_receiver"
6732   [(match_operand 0 "" "")]
6733   "flag_pic"
6734   "
6735 {
6736   emit_insn (gen_GOTaddr2picreg ());
6737   DONE;
6738 }")
6739
6740 (define_expand "call_site"
6741   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
6742   "TARGET_SH1"
6743   "
6744 {
6745   static HOST_WIDE_INT i = 0;
6746   operands[0] = GEN_INT (i);
6747   i++;
6748 }")
6749
6750 (define_expand "sym_label2reg"
6751   [(set (match_operand:SI 0 "" "")
6752         (const:SI (minus:SI
6753                    (const:SI
6754                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
6755                    (const:SI
6756                     (plus:SI
6757                      (match_operand:SI 2 "" "")
6758                      (const_int 2))))))]
6759   "TARGET_SH1" "")
6760
6761 (define_expand "symGOT_load"
6762   [(set (match_dup 2) (match_operand 1 "" ""))
6763    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
6764    (set (match_operand 0 "" "") (mem (match_dup 3)))]
6765   ""
6766   "
6767 {
6768   rtx insn;
6769
6770   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6771   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6772
6773   if (TARGET_SHMEDIA)
6774     {
6775       rtx reg = operands[2];
6776
6777       if (GET_MODE (reg) != DImode)
6778         reg = gen_rtx_SUBREG (DImode, reg, 0);
6779
6780       if (flag_pic > 1)
6781         emit_insn (gen_movdi_const_32bit (reg, operands[1]));
6782       else
6783         emit_insn (gen_movdi_const_16bit (reg, operands[1]));
6784     }
6785   else
6786     emit_move_insn (operands[2], operands[1]);
6787
6788   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
6789                                              operands[2],
6790                                              gen_rtx_REG (Pmode, PIC_REG)));
6791
6792   insn = emit_move_insn (operands[0], gen_rtx_MEM (Pmode, operands[3]));
6793
6794   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
6795                                                                   0), 0, 0),
6796                                         REG_NOTES (insn));
6797
6798   DONE;
6799 }")
6800
6801 (define_expand "sym2GOT"
6802   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
6803   ""
6804   "")
6805
6806 (define_expand "symGOT2reg"
6807   [(match_operand 0 "" "") (match_operand 1 "" "")]
6808   ""
6809   "
6810 {
6811   rtx gotsym, insn;
6812
6813   gotsym = gen_sym2GOT (operands[1]);
6814   PUT_MODE (gotsym, Pmode);
6815   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
6816
6817   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
6818
6819   DONE;
6820 }")
6821
6822 (define_expand "sym2GOTPLT"
6823   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTPLT))]
6824   ""
6825   "")
6826
6827 (define_expand "symGOTPLT2reg"
6828   [(match_operand 0 "" "") (match_operand 1 "" "")]
6829   ""
6830   "
6831 {
6832   emit_insn (gen_symGOT_load (operands[0], gen_sym2GOTPLT (operands[1])));
6833   DONE;
6834 }")
6835
6836 (define_expand "sym2GOTOFF"
6837   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
6838   ""
6839   "")
6840
6841 (define_expand "symGOTOFF2reg"
6842   [(match_operand 0 "" "") (match_operand 1 "" "")]
6843   ""
6844   "
6845 {
6846   rtx gotoffsym, insn;
6847   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6848
6849   gotoffsym = gen_sym2GOTOFF (operands[1]);
6850   PUT_MODE (gotoffsym, Pmode);
6851   emit_move_insn (t, gotoffsym);
6852   insn = emit_move_insn (operands[0],
6853                          gen_rtx_PLUS (Pmode, t,
6854                                        gen_rtx_REG (Pmode, PIC_REG)));
6855
6856   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
6857                                         REG_NOTES (insn));
6858
6859   DONE;
6860 }")
6861
6862 (define_expand "symPLT_label2reg"
6863   [(set (match_operand:SI 0 "" "")
6864         (const:SI (minus:SI
6865                    (const:SI
6866                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
6867                    (const:SI
6868                     (minus:SI
6869                      (const:SI (plus:SI
6870                                 (match_operand:SI 2 "" "")
6871                                 (const_int 2)))
6872                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
6873    ;; Even though the PIC register is not really used by the call
6874    ;; sequence in which this is expanded, the PLT code assumes the PIC
6875    ;; register is set, so we must not skip its initialization.  Since
6876    ;; we only use this expand as part of calling sequences, and never
6877    ;; to take the address of a function, this is the best point to
6878    ;; insert the (use).  Using the PLT to take the address of a
6879    ;; function would be wrong, not only because the PLT entry could
6880    ;; then be called from a function that doesn't initialize the PIC
6881    ;; register to the proper GOT, but also because pointers to the
6882    ;; same function might not compare equal, should they be set by
6883    ;; different shared libraries.
6884    (use (reg:SI PIC_REG))]
6885   "TARGET_SH1"
6886   "")
6887
6888 (define_expand "sym2PIC"
6889   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
6890   ""
6891   "")
6892
6893 ;; TLS code generation.
6894 ;; ??? this should be a define_insn_and_split
6895 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
6896 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
6897 ;; for details.
6898
6899 (define_insn "tls_global_dynamic"
6900   [(set (match_operand:SI 0 "register_operand" "=&z")
6901         (call (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
6902                                   UNSPEC_TLSGD))
6903               (const_int 0)))
6904    (use (reg:PSI FPSCR_REG))
6905    (use (reg:SI PIC_REG))
6906    (clobber (reg:SI PR_REG))
6907    (clobber (scratch:SI))]
6908   "TARGET_SH1"
6909   "*
6910 {
6911   return \"\\
6912 mov.l\\t1f,r4\\n\\
6913 \\tmova\\t2f,r0\\n\\
6914 \\tmov.l\\t2f,r1\\n\\
6915 \\tadd\\tr0,r1\\n\\
6916 \\tjsr\\t@r1\\n\\
6917 \\tadd\\tr12,r4\\n\\
6918 \\tbra\\t3f\\n\\
6919 \\tnop\\n\\
6920 \\t.align\\t2\\n\\
6921 1:\\t.long\\t%a1@TLSGD\\n\\
6922 2:\\t.long\\t__tls_get_addr@PLT\\n\\
6923 3:\";
6924 }"
6925   [(set_attr "type" "tls_load")
6926    (set_attr "length" "26")])
6927
6928 (define_insn "tls_local_dynamic"
6929   [(set (match_operand:SI 0 "register_operand" "=&z")
6930         (call (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
6931                                   UNSPEC_TLSLDM))
6932               (const_int 0)))
6933    (use (reg:PSI FPSCR_REG))
6934    (use (reg:SI PIC_REG))
6935    (clobber (reg:SI PR_REG))
6936    (clobber (scratch:SI))]
6937   "TARGET_SH1"
6938   "*
6939 {
6940   return \"\\
6941 mov.l\\t1f,r4\\n\\
6942 \\tmova\\t2f,r0\\n\\
6943 \\tmov.l\\t2f,r1\\n\\
6944 \\tadd\\tr0,r1\\n\\
6945 \\tjsr\\t@r1\\n\\
6946 \\tadd\\tr12,r4\\n\\
6947 \\tbra\\t3f\\n\\
6948 \\tnop\\n\\
6949 \\t.align\\t2\\n\\
6950 1:\\t.long\\t%a1@TLSLDM\\n\\
6951 2:\\t.long\\t__tls_get_addr@PLT\\n\\
6952 3:\";
6953 }"
6954   [(set_attr "type" "tls_load")
6955    (set_attr "length" "26")])
6956
6957 (define_expand "sym2DTPOFF"
6958   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
6959   ""
6960   "")
6961
6962 (define_expand "symDTPOFF2reg"
6963   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
6964   ""
6965   "
6966 {
6967   rtx dtpoffsym, insn;
6968   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6969
6970   dtpoffsym = gen_sym2DTPOFF (operands[1]);
6971   PUT_MODE (dtpoffsym, Pmode);
6972   emit_move_insn (t, dtpoffsym);
6973   insn = emit_move_insn (operands[0],
6974                          gen_rtx_PLUS (Pmode, t, operands[2]));
6975   DONE;
6976 }")
6977
6978 (define_expand "sym2GOTTPOFF"
6979   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
6980   ""
6981   "")
6982
6983 (define_insn "tls_initial_exec"
6984   [(set (match_operand:SI 0 "register_operand" "=&r")
6985         (unspec:SI [(match_operand:SI 1 "" "")]
6986                     UNSPEC_TLSIE))
6987    (use (reg:SI GBR_REG))
6988    (use (reg:SI PIC_REG))
6989    (clobber (reg:SI R0_REG))]
6990   ""
6991   "*
6992 {
6993   return \"\\
6994 mov.l\\t1f,r0\\n\\
6995 \\tstc\\tgbr,%0\\n\\
6996 \\tmov.l\\t@(r0,r12),r0\\n\\
6997 \\tbra\\t2f\\n\\
6998 \\tadd\\tr0,%0\\n\\
6999 \\t.align\\t2\\n\\
7000 1:\\t.long\\t%a1\\n\\
7001 2:\";
7002 }"
7003   [(set_attr "type" "tls_load")
7004    (set_attr "length" "16")])
7005
7006 (define_expand "sym2TPOFF"
7007   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
7008   ""
7009   "")
7010
7011 (define_expand "symTPOFF2reg"
7012   [(match_operand 0 "" "") (match_operand 1 "" "")]
7013   ""
7014   "
7015 {
7016   rtx tpoffsym, insn;
7017
7018   tpoffsym = gen_sym2TPOFF (operands[1]);
7019   PUT_MODE (tpoffsym, Pmode);
7020   insn = emit_move_insn (operands[0], tpoffsym);
7021   DONE;
7022 }")
7023
7024 (define_insn "load_gbr"
7025   [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
7026    (use (reg:SI GBR_REG))]
7027   ""
7028   "stc  gbr,%0"
7029   [(set_attr "type" "tls_load")])
7030
7031 ;; case instruction for switch statements.
7032
7033 ;; Operand 0 is index
7034 ;; operand 1 is the minimum bound
7035 ;; operand 2 is the maximum bound - minimum bound + 1
7036 ;; operand 3 is CODE_LABEL for the table;
7037 ;; operand 4 is the CODE_LABEL to go to if index out of range.
7038
7039 (define_expand "casesi"
7040   [(match_operand:SI 0 "arith_reg_operand" "")
7041    (match_operand:SI 1 "arith_reg_operand" "")
7042    (match_operand:SI 2 "arith_reg_operand" "")
7043    (match_operand 3 "" "") (match_operand 4 "" "")]
7044   ""
7045   "
7046 {
7047   rtx reg = gen_reg_rtx (SImode);
7048   rtx reg2 = gen_reg_rtx (SImode);
7049   if (TARGET_SHMEDIA)
7050     {
7051       rtx reg = gen_reg_rtx (DImode);
7052       rtx reg2 = gen_reg_rtx (DImode);
7053       rtx reg3 = gen_reg_rtx (DImode);
7054       rtx reg4 = gen_reg_rtx (DImode);
7055       rtx reg5 = gen_reg_rtx (DImode);
7056
7057       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
7058       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
7059       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
7060
7061       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
7062       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
7063       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
7064       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
7065       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
7066                                                (DImode, operands[3])));
7067       emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3]));
7068       emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4));
7069       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
7070       emit_barrier ();
7071       DONE;
7072     }
7073   operands[1] = copy_to_mode_reg (SImode, operands[1]);
7074   operands[2] = copy_to_mode_reg (SImode, operands[2]);
7075   /* If optimizing, casesi_worker depends on the mode of the instruction
7076      before label it 'uses' - operands[3].  */
7077   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
7078                            reg));
7079   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
7080   if (TARGET_SH2)
7081     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
7082   else
7083     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
7084   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
7085      operands[3], but to lab.  We will fix this up in
7086      machine_dependent_reorg.  */
7087   emit_barrier ();
7088   DONE;
7089 }")
7090
7091 (define_expand "casesi_0"
7092   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
7093    (set (match_dup 4) (minus:SI (match_dup 4)
7094                                 (match_operand:SI 1 "arith_operand" "")))
7095    (set (reg:SI T_REG)
7096         (gtu:SI (match_dup 4)
7097                 (match_operand:SI 2 "arith_reg_operand" "")))
7098    (set (pc)
7099         (if_then_else (ne (reg:SI T_REG)
7100                           (const_int 0))
7101                       (label_ref (match_operand 3 "" ""))
7102                       (pc)))]
7103   "TARGET_SH1"
7104   "")
7105
7106 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
7107 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
7108 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
7109
7110 (define_insn "casesi_worker_0"
7111   [(set (match_operand:SI 0 "register_operand" "=r,r")
7112         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
7113                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7114    (clobber (match_scratch:SI 3 "=X,1"))
7115    (clobber (match_scratch:SI 4 "=&z,z"))]
7116   "TARGET_SH1"
7117   "#")
7118
7119 (define_split
7120   [(set (match_operand:SI 0 "register_operand" "")
7121         (unspec:SI [(match_operand:SI 1 "register_operand" "")
7122                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7123    (clobber (match_scratch:SI 3 ""))
7124    (clobber (match_scratch:SI 4 ""))]
7125   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
7126   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
7127    (parallel [(set (match_dup 0)
7128               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
7129                           (label_ref (match_dup 2))] UNSPEC_CASESI))
7130               (clobber (match_dup 3))])
7131    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
7132   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
7133
7134 (define_split
7135   [(set (match_operand:SI 0 "register_operand" "")
7136         (unspec:SI [(match_operand:SI 1 "register_operand" "")
7137                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7138    (clobber (match_scratch:SI 3 ""))
7139    (clobber (match_scratch:SI 4 ""))]
7140   "TARGET_SH2 && reload_completed"
7141   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
7142    (parallel [(set (match_dup 0)
7143               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
7144                           (label_ref (match_dup 2))] UNSPEC_CASESI))
7145               (clobber (match_dup 3))])]
7146   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
7147
7148 (define_insn "casesi_worker_1"
7149   [(set (match_operand:SI 0 "register_operand" "=r,r")
7150         (unspec:SI [(reg:SI R0_REG)
7151                     (match_operand:SI 1 "register_operand" "0,r")
7152                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7153    (clobber (match_scratch:SI 3 "=X,1"))]
7154   "TARGET_SH1"
7155   "*
7156 {
7157   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
7158
7159   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
7160
7161   switch (GET_MODE (diff_vec))
7162     {
7163     case SImode:
7164       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
7165     case HImode:
7166       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
7167     case QImode:
7168       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7169         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
7170       return \"mov.b    @(r0,%1),%0\";
7171     default:
7172       gcc_unreachable ();
7173     }
7174 }"
7175   [(set_attr "length" "4")])
7176
7177 (define_insn "casesi_worker_2"
7178   [(set (match_operand:SI 0 "register_operand" "=r,r")
7179         (unspec:SI [(reg:SI R0_REG)
7180                     (match_operand:SI 1 "register_operand" "0,r")
7181                     (label_ref (match_operand 2 "" ""))
7182                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
7183    (clobber (match_operand:SI 4 "" "=X,1"))]
7184   "TARGET_SH2 && reload_completed && flag_pic"
7185   "*
7186 {
7187   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
7188   const char *load;
7189
7190   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
7191
7192   switch (GET_MODE (diff_vec))
7193     {
7194     case SImode:
7195       output_asm_insn (\"shll2    %1\", operands);
7196       load = \"mov.l    @(r0,%1),%0\"; break;
7197     case HImode:
7198       output_asm_insn (\"add    %1,%1\", operands);
7199       load = \"mov.w    @(r0,%1),%0\"; break;
7200     case QImode:
7201       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7202         load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
7203       else
7204         load = \"mov.b  @(r0,%1),%0\";
7205       break;
7206     default:
7207       gcc_unreachable ();
7208     }
7209   output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
7210   return load;
7211 }"
7212   [(set_attr "length" "8")])
7213
7214 (define_insn "casesi_shift_media"
7215   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7216         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
7217                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
7218                     UNSPEC_CASESI)))]
7219   "TARGET_SHMEDIA"
7220   "*
7221 {
7222   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
7223
7224   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
7225
7226   switch (GET_MODE (diff_vec))
7227     {
7228     case SImode:
7229       return \"shlli    %1, 2, %0\";
7230     case HImode:
7231       return \"shlli    %1, 1, %0\";
7232     case QImode:
7233       if (rtx_equal_p (operands[0], operands[1]))
7234         return \"\";
7235       return \"add      %1, r63, %0\";
7236     default:
7237       gcc_unreachable ();
7238     }
7239 }"
7240   [(set_attr "type" "arith_media")])
7241
7242 (define_insn "casesi_load_media"
7243   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7244         (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r")
7245                          (match_operand 2 "arith_reg_operand" "r")
7246                          (label_ref:DI (match_operand 3 "" ""))] 2)))]
7247   "TARGET_SHMEDIA"
7248   "*
7249 {
7250   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
7251
7252   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
7253
7254   switch (GET_MODE (diff_vec))
7255     {
7256     case SImode:
7257       return \"ldx.l    %1, %2, %0\";
7258     case HImode:
7259 #if 0
7260       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7261         return \"ldx.uw %1, %2, %0\";
7262 #endif
7263       return \"ldx.w    %1, %2, %0\";
7264     case QImode:
7265       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7266         return \"ldx.ub %1, %2, %0\";
7267       return \"ldx.b    %1, %2, %0\";
7268     default:
7269       gcc_unreachable ();
7270     }
7271 }"
7272   [(set_attr "type" "load_media")])
7273
7274 (define_expand "return"
7275   [(return)]
7276   "reload_completed && ! sh_need_epilogue ()"
7277   "
7278 {
7279   if (TARGET_SHMEDIA)
7280     {
7281       emit_jump_insn (gen_return_media ());
7282       DONE;
7283     }
7284
7285   if (TARGET_SHCOMPACT
7286       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
7287     {
7288       emit_jump_insn (gen_shcompact_return_tramp ());
7289       DONE;
7290     }
7291 }")
7292
7293 (define_insn "*return_i"
7294   [(return)]
7295   "TARGET_SH1 && ! (TARGET_SHCOMPACT
7296                     && (current_function_args_info.call_cookie
7297                         & CALL_COOKIE_RET_TRAMP (1)))
7298    && reload_completed"
7299   "%@   %#"
7300   [(set_attr "type" "return")
7301    (set_attr "needs_delay_slot" "yes")])
7302
7303 (define_expand "shcompact_return_tramp"
7304   [(return)]
7305   "TARGET_SHCOMPACT
7306    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7307   "
7308 {
7309   rtx reg = gen_rtx_REG (Pmode, R0_REG);
7310   rtx sym = function_symbol (\"__GCC_shcompact_return_trampoline\");
7311
7312   if (flag_pic)
7313     emit_insn (gen_symGOTPLT2reg (reg, sym));
7314   else
7315     emit_move_insn (reg, sym);
7316
7317   emit_jump_insn (gen_shcompact_return_tramp_i ());
7318   DONE;
7319 }")
7320
7321 (define_insn "shcompact_return_tramp_i"
7322   [(parallel [(return) (use (reg:SI R0_REG))])]
7323   "TARGET_SHCOMPACT
7324    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7325   "jmp  @r0%#"
7326   [(set_attr "type" "jump_ind")
7327    (set_attr "needs_delay_slot" "yes")])
7328
7329 (define_insn "return_media_i"
7330   [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])]
7331   "TARGET_SHMEDIA && reload_completed"
7332   "blink        %0, r63"
7333   [(set_attr "type" "jump_media")])
7334
7335 (define_insn "return_media_rte"
7336   [(return)]
7337   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
7338   "rte"
7339   [(set_attr "type" "jump_media")])
7340
7341 (define_expand "return_media"
7342   [(return)]
7343   "TARGET_SHMEDIA && reload_completed"
7344   "
7345 {
7346   int tr_regno = sh_media_register_for_return ();
7347   rtx tr;
7348
7349   if (current_function_interrupt)
7350     {
7351       emit_jump_insn (gen_return_media_rte ());
7352       DONE;
7353     }
7354   if (tr_regno < 0)
7355     {
7356       rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
7357
7358       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
7359       tr_regno = TR0_REG;
7360       tr = gen_rtx_REG (DImode, tr_regno);
7361       emit_move_insn (tr, r18);
7362     }
7363   else
7364     tr = gen_rtx_REG (DImode, tr_regno);
7365
7366   emit_jump_insn (gen_return_media_i (tr));
7367   DONE;
7368 }")
7369
7370 (define_insn "shcompact_preserve_incoming_args"
7371   [(set (match_operand:SI 0 "register_operand" "+r")
7372         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
7373   "TARGET_SHCOMPACT"
7374   ""
7375   [(set_attr "length" "0")])
7376
7377 (define_insn "shcompact_incoming_args"
7378   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
7379    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
7380    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
7381    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
7382    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
7383    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
7384    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
7385    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
7386    (set (mem:BLK (reg:SI MACL_REG))
7387         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
7388    (use (reg:SI R0_REG))
7389    (clobber (reg:SI R0_REG))
7390    (clobber (reg:SI MACL_REG))
7391    (clobber (reg:SI MACH_REG))
7392    (clobber (reg:SI PR_REG))]
7393   "TARGET_SHCOMPACT"
7394   "jsr  @r0%#"
7395   [(set_attr "needs_delay_slot" "yes")])
7396
7397 (define_insn "shmedia_save_restore_regs_compact"
7398   [(set (reg:SI SP_REG)
7399         (plus:SI (reg:SI SP_REG)
7400                  (match_operand:SI 0 "immediate_operand" "i")))
7401    (use (reg:SI R0_REG))
7402    (clobber (reg:SI PR_REG))]
7403   "TARGET_SHCOMPACT
7404    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
7405        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
7406   "jsr @r0%#"
7407   [(set_attr "needs_delay_slot" "yes")])
7408
7409 (define_expand "prologue"
7410   [(const_int 0)]
7411   ""
7412   "sh_expand_prologue (); DONE;")
7413
7414 (define_expand "epilogue"
7415   [(return)]
7416   ""
7417   "
7418 {
7419   sh_expand_epilogue (0);
7420   emit_jump_insn (gen_return ());
7421   DONE;
7422 }")
7423
7424 (define_expand "eh_return"
7425   [(use (match_operand 0 "register_operand" ""))]
7426   ""
7427 {
7428   rtx ra = operands[0];
7429
7430   if (TARGET_SHMEDIA64)
7431     emit_insn (gen_eh_set_ra_di (ra));
7432   else
7433     emit_insn (gen_eh_set_ra_si (ra));
7434
7435   DONE;
7436 })
7437
7438 ;; Clobber the return address on the stack.  We can't expand this
7439 ;; until we know where it will be put in the stack frame.
7440
7441 (define_insn "eh_set_ra_si"
7442   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
7443    (clobber (match_scratch:SI 1 "=&r"))]
7444   "! TARGET_SHMEDIA64"
7445   "#")
7446
7447 (define_insn "eh_set_ra_di"
7448   [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
7449    (clobber (match_scratch:DI 1 "=&r"))]
7450   "TARGET_SHMEDIA64"
7451   "#")
7452
7453 (define_split
7454   [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
7455    (clobber (match_scratch 1 ""))]
7456   "reload_completed"
7457   [(const_int 0)]
7458   "
7459 {
7460   sh_set_return_address (operands[0], operands[1]);
7461   DONE;
7462 }")
7463
7464 (define_insn "blockage"
7465   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7466   ""
7467   ""
7468   [(set_attr "length" "0")])
7469 \f
7470 ;; ------------------------------------------------------------------------
7471 ;; Scc instructions
7472 ;; ------------------------------------------------------------------------
7473
7474 (define_insn "movt"
7475   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7476         (eq:SI (reg:SI T_REG) (const_int 1)))]
7477   "TARGET_SH1"
7478   "movt %0"
7479   [(set_attr "type" "arith")])
7480
7481 (define_expand "seq"
7482   [(set (match_operand:SI 0 "arith_reg_operand" "")
7483         (match_dup 1))]
7484   ""
7485   "
7486 {
7487   if (TARGET_SHMEDIA)
7488     {
7489       if (GET_MODE (operands[0]) != DImode)
7490         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7491       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7492       if (sh_compare_op1 != const0_rtx)
7493         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7494                                     ? GET_MODE (sh_compare_op0)
7495                                     : GET_MODE (sh_compare_op1),
7496                                     sh_compare_op1);
7497
7498       switch (GET_MODE (sh_compare_op0))
7499         {
7500         case DImode:
7501           emit_insn (gen_cmpeqdi_media (operands[0],
7502                                         sh_compare_op0, sh_compare_op1));
7503           break;
7504
7505         case SFmode:
7506           if (! TARGET_SHMEDIA_FPU)
7507             FAIL;
7508           emit_insn (gen_cmpeqsf_media (operands[0],
7509                                         sh_compare_op0, sh_compare_op1));
7510           break;
7511
7512         case DFmode:
7513           if (! TARGET_SHMEDIA_FPU)
7514             FAIL;
7515           emit_insn (gen_cmpeqdf_media (operands[0],
7516                                         sh_compare_op0, sh_compare_op1));
7517           break;
7518
7519         default:
7520           FAIL;
7521         }
7522       DONE;
7523     }
7524   if (sh_expand_t_scc (EQ, operands[0]))
7525     DONE;
7526   if (! currently_expanding_to_rtl)
7527     FAIL;
7528   operands[1] = prepare_scc_operands (EQ);
7529 }")
7530
7531 (define_expand "slt"
7532   [(set (match_operand:SI 0 "arith_reg_operand" "")
7533         (match_dup 1))]
7534   ""
7535   "
7536 {
7537   if (TARGET_SHMEDIA)
7538     {
7539       if (GET_MODE (operands[0]) != DImode)
7540         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7541       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7542       if (sh_compare_op1 != const0_rtx)
7543         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7544                                     ? GET_MODE (sh_compare_op0)
7545                                     : GET_MODE (sh_compare_op1),
7546                                     sh_compare_op1);
7547
7548       switch (GET_MODE (sh_compare_op0))
7549         {
7550         case DImode:
7551           emit_insn (gen_cmpgtdi_media (operands[0],
7552                                         sh_compare_op1, sh_compare_op0));
7553           break;
7554
7555         case SFmode:
7556           if (! TARGET_SHMEDIA_FPU)
7557             FAIL;
7558           emit_insn (gen_cmpgtsf_media (operands[0],
7559                                         sh_compare_op1, sh_compare_op0));
7560           break;
7561
7562         case DFmode:
7563           if (! TARGET_SHMEDIA_FPU)
7564             FAIL;
7565           emit_insn (gen_cmpgtdf_media (operands[0],
7566                                         sh_compare_op1, sh_compare_op0));
7567           break;
7568
7569         default:
7570           FAIL;
7571         }
7572       DONE;
7573     }
7574   if (! currently_expanding_to_rtl)
7575     FAIL;
7576   operands[1] = prepare_scc_operands (LT);
7577 }")
7578
7579 (define_expand "sle"
7580   [(match_operand:SI 0 "arith_reg_operand" "")]
7581   ""
7582   "
7583 {
7584   rtx tmp = sh_compare_op0;
7585
7586   if (TARGET_SHMEDIA)
7587     {
7588       if (GET_MODE (operands[0]) != DImode)
7589         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7590       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7591       if (sh_compare_op1 != const0_rtx)
7592         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7593                                     ? GET_MODE (sh_compare_op0)
7594                                     : GET_MODE (sh_compare_op1),
7595                                     sh_compare_op1);
7596
7597       switch (GET_MODE (sh_compare_op0))
7598         {
7599         case DImode:
7600           {
7601             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7602
7603             emit_insn (gen_cmpgtdi_media (tmp,
7604                                           sh_compare_op0, sh_compare_op1));
7605             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7606             break;
7607           }
7608
7609         case SFmode:
7610           if (! TARGET_SHMEDIA_FPU)
7611             FAIL;
7612           emit_insn (gen_cmpgesf_media (operands[0],
7613                                         sh_compare_op1, sh_compare_op0));
7614           break;
7615
7616         case DFmode:
7617           if (! TARGET_SHMEDIA_FPU)
7618             FAIL;
7619           emit_insn (gen_cmpgedf_media (operands[0],
7620                                         sh_compare_op1, sh_compare_op0));
7621           break;
7622
7623         default:
7624           FAIL;
7625         }
7626       DONE;
7627     }
7628
7629   sh_compare_op0 = sh_compare_op1;
7630   sh_compare_op1 = tmp;
7631   emit_insn (gen_sge (operands[0]));
7632   DONE;
7633 }")
7634
7635 (define_expand "sgt"
7636   [(set (match_operand:SI 0 "arith_reg_operand" "")
7637         (match_dup 1))]
7638   ""
7639   "
7640 {
7641   if (TARGET_SHMEDIA)
7642     {
7643       if (GET_MODE (operands[0]) != DImode)
7644         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7645       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7646       if (sh_compare_op1 != const0_rtx)
7647         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7648                                     ? GET_MODE (sh_compare_op0)
7649                                     : GET_MODE (sh_compare_op1),
7650                                     sh_compare_op1);
7651
7652       switch (GET_MODE (sh_compare_op0))
7653         {
7654         case DImode:
7655           emit_insn (gen_cmpgtdi_media (operands[0],
7656                                         sh_compare_op0, sh_compare_op1));
7657           break;
7658
7659         case SFmode:
7660           if (! TARGET_SHMEDIA_FPU)
7661             FAIL;
7662           emit_insn (gen_cmpgtsf_media (operands[0],
7663                                         sh_compare_op0, sh_compare_op1));
7664           break;
7665
7666         case DFmode:
7667           if (! TARGET_SHMEDIA_FPU)
7668             FAIL;
7669           emit_insn (gen_cmpgtdf_media (operands[0],
7670                                         sh_compare_op0, sh_compare_op1));
7671           break;
7672
7673         default:
7674           FAIL;
7675         }
7676       DONE;
7677     }
7678   if (! currently_expanding_to_rtl)
7679     FAIL;
7680   operands[1] = prepare_scc_operands (GT);
7681 }")
7682
7683 (define_expand "sge"
7684   [(set (match_operand:SI 0 "arith_reg_operand" "")
7685         (match_dup 1))]
7686   ""
7687   "
7688 {
7689   if (TARGET_SHMEDIA)
7690     {
7691       if (GET_MODE (operands[0]) != DImode)
7692         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7693       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7694       if (sh_compare_op1 != const0_rtx)
7695         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7696                                     ? GET_MODE (sh_compare_op0)
7697                                     : GET_MODE (sh_compare_op1),
7698                                     sh_compare_op1);
7699
7700       switch (GET_MODE (sh_compare_op0))
7701         {
7702         case DImode:
7703           {
7704             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7705
7706             emit_insn (gen_cmpgtdi_media (tmp,
7707                                           sh_compare_op1, sh_compare_op0));
7708             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7709             break;
7710           }
7711
7712         case SFmode:
7713           if (! TARGET_SHMEDIA_FPU)
7714             FAIL;
7715           emit_insn (gen_cmpgesf_media (operands[0],
7716                                         sh_compare_op0, sh_compare_op1));
7717           break;
7718
7719         case DFmode:
7720           if (! TARGET_SHMEDIA_FPU)
7721             FAIL;
7722           emit_insn (gen_cmpgedf_media (operands[0],
7723                                         sh_compare_op0, sh_compare_op1));
7724           break;
7725
7726         default:
7727           FAIL;
7728         }
7729       DONE;
7730     }
7731
7732   if (! currently_expanding_to_rtl)
7733     FAIL;
7734   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7735     {
7736       if (TARGET_IEEE)
7737         {
7738           rtx lab = gen_label_rtx ();
7739           prepare_scc_operands (EQ);
7740           emit_jump_insn (gen_branch_true (lab));
7741           prepare_scc_operands (GT);
7742           emit_label (lab);
7743           emit_insn (gen_movt (operands[0]));
7744         }
7745       else
7746         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
7747       DONE;
7748     }
7749   operands[1] = prepare_scc_operands (GE);
7750 }")
7751
7752 (define_expand "sgtu"
7753   [(set (match_operand:SI 0 "arith_reg_operand" "")
7754         (match_dup 1))]
7755   ""
7756   "
7757 {
7758   if (TARGET_SHMEDIA)
7759     {
7760       if (GET_MODE (operands[0]) != DImode)
7761         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7762       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7763       if (sh_compare_op1 != const0_rtx)
7764         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7765                                     ? GET_MODE (sh_compare_op0)
7766                                     : GET_MODE (sh_compare_op1),
7767                                     sh_compare_op1);
7768
7769       emit_insn (gen_cmpgtudi_media (operands[0],
7770                                      sh_compare_op0, sh_compare_op1));
7771       DONE;
7772     }
7773   if (! currently_expanding_to_rtl)
7774     FAIL;
7775   operands[1] = prepare_scc_operands (GTU);
7776 }")
7777
7778 (define_expand "sltu"
7779   [(set (match_operand:SI 0 "arith_reg_operand" "")
7780         (match_dup 1))]
7781   ""
7782   "
7783 {
7784   if (TARGET_SHMEDIA)
7785     {
7786       if (GET_MODE (operands[0]) != DImode)
7787         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7788       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7789       if (sh_compare_op1 != const0_rtx)
7790         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7791                                     ? GET_MODE (sh_compare_op0)
7792                                     : GET_MODE (sh_compare_op1),
7793                                     sh_compare_op1);
7794
7795       emit_insn (gen_cmpgtudi_media (operands[0],
7796                                      sh_compare_op1, sh_compare_op0));
7797       DONE;
7798     }
7799   if (! currently_expanding_to_rtl)
7800     FAIL;
7801   operands[1] = prepare_scc_operands (LTU);
7802 }")
7803
7804 (define_expand "sleu"
7805   [(set (match_operand:SI 0 "arith_reg_operand" "")
7806         (match_dup 1))]
7807   ""
7808   "
7809 {
7810   if (TARGET_SHMEDIA)
7811     {
7812       rtx tmp;
7813
7814       if (GET_MODE (operands[0]) != DImode)
7815         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7816       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7817       if (sh_compare_op1 != const0_rtx)
7818         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7819                                     ? GET_MODE (sh_compare_op0)
7820                                     : GET_MODE (sh_compare_op1),
7821                                     sh_compare_op1);
7822
7823       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7824
7825       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
7826       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7827
7828       DONE;
7829     }
7830   if (! currently_expanding_to_rtl)
7831     FAIL;
7832   operands[1] = prepare_scc_operands (LEU);
7833 }")
7834
7835 (define_expand "sgeu"
7836   [(set (match_operand:SI 0 "arith_reg_operand" "")
7837         (match_dup 1))]
7838   ""
7839   "
7840 {
7841   if (TARGET_SHMEDIA)
7842     {
7843       rtx tmp;
7844
7845       if (GET_MODE (operands[0]) != DImode)
7846         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7847       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7848       if (sh_compare_op1 != const0_rtx)
7849         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7850                                     ? GET_MODE (sh_compare_op0)
7851                                     : GET_MODE (sh_compare_op1),
7852                                     sh_compare_op1);
7853
7854       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7855
7856       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
7857       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7858
7859       DONE;
7860     }
7861
7862   if (! currently_expanding_to_rtl)
7863     FAIL;
7864   operands[1] = prepare_scc_operands (GEU);
7865 }")
7866
7867 ;; sne moves the complement of the T reg to DEST like this:
7868 ;;      cmp/eq ...
7869 ;;      mov    #-1,temp
7870 ;;      negc   temp,dest
7871 ;;   This is better than xoring compare result with 1 because it does
7872 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
7873 ;;   loop.
7874
7875 (define_expand "sne"
7876   [(set (match_dup 2) (const_int -1))
7877    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
7878                    (neg:SI (plus:SI (match_dup 1)
7879                                     (match_dup 2))))
7880               (set (reg:SI T_REG)
7881                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
7882                           (const_int 0)))])]
7883   ""
7884   "
7885 {
7886   if (TARGET_SHMEDIA)
7887     {
7888       rtx tmp;
7889
7890       if (GET_MODE (operands[0]) != DImode)
7891         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7892
7893       if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode)
7894         FAIL;
7895
7896       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7897       if (sh_compare_op1 != const0_rtx)
7898         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7899                                     ? GET_MODE (sh_compare_op0)
7900                                     : GET_MODE (sh_compare_op1),
7901                                     sh_compare_op1);
7902
7903       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7904
7905       emit_insn (gen_seq (tmp));
7906       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7907
7908       DONE;
7909     }
7910
7911   if (sh_expand_t_scc (NE, operands[0]))
7912     DONE;
7913   if (! currently_expanding_to_rtl)
7914     FAIL;
7915   operands[1] = prepare_scc_operands (EQ);
7916   operands[2] = gen_reg_rtx (SImode);
7917 }")
7918
7919 (define_expand "sunordered"
7920   [(set (match_operand:DI 0 "arith_reg_operand" "")
7921         (unordered:DI (match_dup 1) (match_dup 2)))]
7922   "TARGET_SHMEDIA_FPU"
7923   "
7924 {
7925   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7926   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7927 }")
7928
7929 ;; Use the same trick for FP sle / sge
7930 (define_expand "movnegt"
7931   [(set (match_dup 2) (const_int -1))
7932    (parallel [(set (match_operand 0 "" "")
7933                    (neg:SI (plus:SI (match_dup 1)
7934                                     (match_dup 2))))
7935               (set (reg:SI T_REG)
7936                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
7937                           (const_int 0)))])]
7938   "TARGET_SH1"
7939   "operands[2] = gen_reg_rtx (SImode);")
7940
7941 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
7942 ;; This prevents a regression that occurred when we switched from xor to
7943 ;; mov/neg for sne.
7944
7945 (define_split
7946   [(set (match_operand:SI 0 "arith_reg_operand" "")
7947         (plus:SI (reg:SI T_REG)
7948                  (const_int -1)))]
7949   "TARGET_SH1"
7950   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
7951    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
7952   "")
7953
7954 ;; -------------------------------------------------------------------------
7955 ;; Instructions to cope with inline literal tables
7956 ;; -------------------------------------------------------------------------
7957
7958 ; 2 byte integer in line
7959
7960 (define_insn "consttable_2"
7961  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7962                     (match_operand 1 "" "")]
7963                    UNSPECV_CONST2)]
7964  ""
7965  "*
7966 {
7967   if (operands[1] != const0_rtx)
7968     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
7969   return \"\";
7970 }"
7971  [(set_attr "length" "2")
7972  (set_attr "in_delay_slot" "no")])
7973
7974 ; 4 byte integer in line
7975
7976 (define_insn "consttable_4"
7977  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7978                     (match_operand 1 "" "")]
7979                    UNSPECV_CONST4)]
7980  ""
7981  "*
7982 {
7983   if (operands[1] != const0_rtx)
7984     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
7985   return \"\";
7986 }"
7987  [(set_attr "length" "4")
7988   (set_attr "in_delay_slot" "no")])
7989
7990 ; 8 byte integer in line
7991
7992 (define_insn "consttable_8"
7993  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7994                     (match_operand 1 "" "")]
7995                    UNSPECV_CONST8)]
7996  ""
7997  "*
7998 {
7999   if (operands[1] != const0_rtx)
8000     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
8001   return \"\";
8002 }"
8003  [(set_attr "length" "8")
8004   (set_attr "in_delay_slot" "no")])
8005
8006 ; 4 byte floating point
8007
8008 (define_insn "consttable_sf"
8009  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
8010                     (match_operand 1 "" "")]
8011                    UNSPECV_CONST4)]
8012  ""
8013  "*
8014 {
8015   if (operands[1] != const0_rtx)
8016     {
8017       REAL_VALUE_TYPE d;
8018       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
8019       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
8020     }
8021   return \"\";
8022 }"
8023  [(set_attr "length" "4")
8024   (set_attr "in_delay_slot" "no")])
8025
8026 ; 8 byte floating point
8027
8028 (define_insn "consttable_df"
8029  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
8030                     (match_operand 1 "" "")]
8031                    UNSPECV_CONST8)]
8032  ""
8033  "*
8034 {
8035   if (operands[1] != const0_rtx)
8036     {
8037       REAL_VALUE_TYPE d;
8038       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
8039       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
8040     }
8041   return \"\";
8042 }"
8043  [(set_attr "length" "8")
8044   (set_attr "in_delay_slot" "no")])
8045
8046 ;; Alignment is needed for some constant tables; it may also be added for
8047 ;; Instructions at the start of loops, or after unconditional branches.
8048 ;; ??? We would get more accurate lengths if we did instruction
8049 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
8050 ;; here is too conservative.
8051
8052 ; align to a two byte boundary
8053
8054 (define_expand "align_2"
8055  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
8056  ""
8057  "")
8058
8059 ; align to a four byte boundary
8060 ;; align_4 and align_log are instructions for the starts of loops, or
8061 ;; after unconditional branches, which may take up extra room.
8062
8063 (define_expand "align_4"
8064  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
8065  ""
8066  "")
8067
8068 ; align to a cache line boundary
8069
8070 (define_insn "align_log"
8071  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
8072  ""
8073  ""
8074  [(set_attr "length" "0")
8075   (set_attr "in_delay_slot" "no")])
8076
8077 ; emitted at the end of the literal table, used to emit the
8078 ; 32bit branch labels if needed.
8079
8080 (define_insn "consttable_end"
8081   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
8082   ""
8083   "* return output_jump_label_table ();"
8084   [(set_attr "in_delay_slot" "no")])
8085
8086 ; emitted at the end of the window in the literal table.
8087
8088 (define_insn "consttable_window_end"
8089   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
8090   ""
8091   ""
8092   [(set_attr "length" "0")
8093    (set_attr "in_delay_slot" "no")])
8094
8095 ;; -------------------------------------------------------------------------
8096 ;; Misc
8097 ;; -------------------------------------------------------------------------
8098
8099 ;; String/block move insn.
8100
8101 (define_expand "movmemsi"
8102   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
8103                    (mem:BLK (match_operand:BLK 1 "" "")))
8104               (use (match_operand:SI 2 "nonmemory_operand" ""))
8105               (use (match_operand:SI 3 "immediate_operand" ""))
8106               (clobber (reg:SI PR_REG))
8107               (clobber (reg:SI R4_REG))
8108               (clobber (reg:SI R5_REG))
8109               (clobber (reg:SI R0_REG))])]
8110   "TARGET_SH1 && ! TARGET_SH5"
8111   "
8112 {
8113   if(expand_block_move (operands))
8114      DONE;
8115   else FAIL;
8116 }")
8117
8118 (define_insn "block_move_real"
8119   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8120                    (mem:BLK (reg:SI R5_REG)))
8121               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8122               (clobber (reg:SI PR_REG))
8123               (clobber (reg:SI R0_REG))])]
8124   "TARGET_SH1 && ! TARGET_HARD_SH4"
8125   "jsr  @%0%#"
8126   [(set_attr "type" "sfunc")
8127    (set_attr "needs_delay_slot" "yes")])
8128
8129 (define_insn "block_lump_real"
8130   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8131                    (mem:BLK (reg:SI R5_REG)))
8132               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8133               (use (reg:SI R6_REG))
8134               (clobber (reg:SI PR_REG))
8135               (clobber (reg:SI T_REG))
8136               (clobber (reg:SI R4_REG))
8137               (clobber (reg:SI R5_REG))
8138               (clobber (reg:SI R6_REG))
8139               (clobber (reg:SI R0_REG))])]
8140   "TARGET_SH1 && ! TARGET_HARD_SH4"
8141   "jsr  @%0%#"
8142   [(set_attr "type" "sfunc")
8143    (set_attr "needs_delay_slot" "yes")])
8144
8145 (define_insn "block_move_real_i4"
8146   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8147                    (mem:BLK (reg:SI R5_REG)))
8148               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8149               (clobber (reg:SI PR_REG))
8150               (clobber (reg:SI R0_REG))
8151               (clobber (reg:SI R1_REG))
8152               (clobber (reg:SI R2_REG))])]
8153   "TARGET_HARD_SH4"
8154   "jsr  @%0%#"
8155   [(set_attr "type" "sfunc")
8156    (set_attr "needs_delay_slot" "yes")])
8157
8158 (define_insn "block_lump_real_i4"
8159   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8160                    (mem:BLK (reg:SI R5_REG)))
8161               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8162               (use (reg:SI R6_REG))
8163               (clobber (reg:SI PR_REG))
8164               (clobber (reg:SI T_REG))
8165               (clobber (reg:SI R4_REG))
8166               (clobber (reg:SI R5_REG))
8167               (clobber (reg:SI R6_REG))
8168               (clobber (reg:SI R0_REG))
8169               (clobber (reg:SI R1_REG))
8170               (clobber (reg:SI R2_REG))
8171               (clobber (reg:SI R3_REG))])]
8172   "TARGET_HARD_SH4"
8173   "jsr  @%0%#"
8174   [(set_attr "type" "sfunc")
8175    (set_attr "needs_delay_slot" "yes")])
8176 \f
8177 ;; -------------------------------------------------------------------------
8178 ;; Floating point instructions.
8179 ;; -------------------------------------------------------------------------
8180
8181 ;; ??? All patterns should have a type attribute.
8182
8183 (define_expand "fpu_switch0"
8184   [(set (match_operand:SI 0 "" "") (match_dup 2))
8185    (set (match_dup 1) (mem:PSI (match_dup 0)))]
8186   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8187   "
8188 {
8189   operands[1] = get_fpscr_rtx ();
8190   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
8191   if (flag_pic)
8192     operands[2] = legitimize_pic_address (operands[2], SImode,
8193                                           no_new_pseudos ? operands[0] : 0);
8194 }")
8195
8196 (define_expand "fpu_switch1"
8197   [(set (match_operand:SI 0 "" "") (match_dup 2))
8198    (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4)))
8199    (set (match_dup 1) (mem:PSI (match_dup 3)))]
8200   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8201   "
8202 {
8203   operands[1] = get_fpscr_rtx ();
8204   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
8205   if (flag_pic)
8206     operands[2] = legitimize_pic_address (operands[2], SImode,
8207                                           no_new_pseudos ? operands[0] : 0);
8208   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
8209 }")
8210
8211 (define_expand "movpsi"
8212   [(set (match_operand:PSI 0 "register_operand" "")
8213         (match_operand:PSI 1 "general_movsrc_operand" ""))]
8214   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8215   "")
8216
8217 ;; The c / m alternative is a fake to guide reload to load directly into
8218 ;; fpscr, since reload doesn't know how to use post-increment.
8219 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
8220 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
8221 ;; predicate after reload.
8222 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
8223 ;; like a mac -> gpr move.
8224 (define_insn "fpu_switch"
8225   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
8226         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
8227   "TARGET_SH2E
8228    && (! reload_completed
8229        || true_regnum (operands[0]) != FPSCR_REG
8230        || GET_CODE (operands[1]) != MEM
8231        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
8232   "@
8233         ! precision stays the same
8234         lds.l   %1,fpscr
8235         mov.l   %1,%0
8236         #
8237         lds     %1,fpscr
8238         mov     %1,%0
8239         mov.l   %1,%0
8240         sts     fpscr,%0
8241         sts.l   fpscr,%0"
8242   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
8243    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
8244
8245 (define_split
8246   [(set (reg:PSI FPSCR_REG)
8247         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
8248   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
8249   [(set (match_dup 0) (match_dup 0))]
8250   "
8251 {
8252   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
8253                                         gen_rtx_MEM (PSImode,
8254                                                  gen_rtx_POST_INC (Pmode,
8255                                                           operands[0]))));
8256   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
8257 }")
8258
8259 (define_split
8260   [(set (reg:PSI FPSCR_REG)
8261         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
8262   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8263   [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))]
8264   "
8265 {
8266   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
8267                                         gen_rtx_MEM (PSImode,
8268                                                  gen_rtx_POST_INC (Pmode,
8269                                                           operands[0]))));
8270   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
8271 }")
8272
8273 ;; ??? This uses the fp unit, but has no type indicating that.
8274 ;; If we did that, this would either give a bogus latency or introduce
8275 ;; a bogus FIFO constraint.
8276 ;; Since this insn is currently only used for prologues/epilogues,
8277 ;; it is probably best to claim no function unit, which matches the
8278 ;; current setting.
8279 (define_insn "toggle_sz"
8280   [(set (reg:PSI FPSCR_REG)
8281         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
8282   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8283   "fschg"
8284   [(set_attr "type" "fp") (set_attr "fp_set" "unknown")])
8285
8286 ;; There's no way we can use it today, since optimize mode switching
8287 ;; doesn't enable us to know from which mode we're switching to the
8288 ;; mode it requests, to tell whether we can use a relative mode switch
8289 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
8290 ;; memory).
8291 (define_insn "toggle_pr"
8292   [(set (reg:PSI FPSCR_REG)
8293         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
8294   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
8295   "fpchg"
8296   [(set_attr "type" "fp")])
8297
8298 (define_expand "addsf3"
8299   [(set (match_operand:SF 0 "arith_reg_operand" "")
8300         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
8301                  (match_operand:SF 2 "arith_reg_operand" "")))]
8302   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8303   "
8304 {
8305   if (TARGET_SH2E)
8306     {
8307       expand_sf_binop (&gen_addsf3_i, operands);
8308       DONE;
8309     }
8310 }")
8311
8312 (define_insn "*addsf3_media"
8313   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8314         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8315                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8316   "TARGET_SHMEDIA_FPU"
8317   "fadd.s       %1, %2, %0"
8318   [(set_attr "type" "fparith_media")])
8319
8320 (define_insn_and_split "unary_sf_op"
8321   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8322         (vec_select:V2SF
8323          (vec_concat:V2SF
8324           (vec_select:SF
8325            (match_dup 0)
8326            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
8327           (match_operator:SF 2 "unary_float_operator"
8328             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
8329                             (parallel [(match_operand 4
8330                                         "const_int_operand" "n")]))]))
8331          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
8332   "TARGET_SHMEDIA_FPU"
8333   "#"
8334   "TARGET_SHMEDIA_FPU && reload_completed"
8335   [(set (match_dup 5) (match_dup 6))]
8336   "
8337 {
8338   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
8339   rtx op1 = gen_rtx_REG (SFmode,
8340                          (true_regnum (operands[1])
8341                           + (INTVAL (operands[4]) ^ endian)));
8342
8343   operands[7] = gen_rtx_REG (SFmode,
8344                              (true_regnum (operands[0])
8345                               + (INTVAL (operands[3]) ^ endian)));
8346   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
8347 }"
8348   [(set_attr "type" "fparith_media")])
8349
8350 (define_insn_and_split "binary_sf_op"
8351   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8352         (vec_select:V2SF
8353          (vec_concat:V2SF
8354           (vec_select:SF
8355            (match_dup 0)
8356            (parallel [(match_operand 7 "const_int_operand" "n")]))
8357           (match_operator:SF 3 "binary_float_operator"
8358             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
8359                             (parallel [(match_operand 5
8360                                         "const_int_operand" "n")]))
8361              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
8362                             (parallel [(match_operand 6
8363                                         "const_int_operand" "n")]))]))
8364          (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
8365   "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
8366   "#"
8367   "&& reload_completed"
8368   [(set (match_dup 8) (match_dup 9))]
8369   "
8370 {
8371   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
8372   rtx op1 = gen_rtx_REG (SFmode,
8373                          (true_regnum (operands[1])
8374                           + (INTVAL (operands[5]) ^ endian)));
8375   rtx op2 = gen_rtx_REG (SFmode,
8376                          (true_regnum (operands[2])
8377                           + (INTVAL (operands[6]) ^ endian)));
8378
8379   operands[8] = gen_rtx_REG (SFmode,
8380                              (true_regnum (operands[0])
8381                               + (INTVAL (operands[4]) ^ endian)));
8382   operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
8383 }"
8384   [(set_attr "type" "fparith_media")])
8385
8386 (define_insn "addsf3_i"
8387   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8388         (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
8389                  (match_operand:SF 2 "arith_reg_operand" "f")))
8390    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8391   "TARGET_SH2E"
8392   "fadd %2,%0"
8393   [(set_attr "type" "fp")
8394    (set_attr "fp_mode" "single")])
8395
8396 (define_expand "subsf3"
8397   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8398         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8399                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8400   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8401   "
8402 {
8403   if (TARGET_SH2E)
8404     {
8405       expand_sf_binop (&gen_subsf3_i, operands);
8406       DONE;
8407     }
8408 }")
8409
8410 (define_insn "*subsf3_media"
8411   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8412         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8413                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8414   "TARGET_SHMEDIA_FPU"
8415   "fsub.s       %1, %2, %0"
8416   [(set_attr "type" "fparith_media")])
8417
8418 (define_insn "subsf3_i"
8419   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8420         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
8421                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8422    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8423   "TARGET_SH2E"
8424   "fsub %2,%0"
8425   [(set_attr "type" "fp")
8426    (set_attr "fp_mode" "single")])
8427
8428 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
8429 ;; register in feeding fp instructions.  Thus, we cannot generate fmac for
8430 ;; mixed-precision SH4 targets.  To allow it to be still generated for the
8431 ;; SH3E, we use a separate insn for SH3E mulsf3.
8432
8433 (define_expand "mulsf3"
8434   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8435         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8436                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8437   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8438   "
8439 {
8440   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
8441     expand_sf_binop (&gen_mulsf3_i4, operands);
8442   else if (TARGET_SH2E)
8443     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
8444   if (! TARGET_SHMEDIA)
8445     DONE;
8446 }")
8447
8448 (define_insn "*mulsf3_media"
8449   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8450         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8451                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8452   "TARGET_SHMEDIA_FPU"
8453   "fmul.s       %1, %2, %0"
8454   [(set_attr "type" "fparith_media")])
8455
8456 (define_insn "mulsf3_i4"
8457   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8458         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8459                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8460    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8461   "TARGET_SH2E"
8462   "fmul %2,%0"
8463   [(set_attr "type" "fp")
8464    (set_attr "fp_mode" "single")])
8465
8466 (define_insn "mulsf3_ie"
8467   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8468         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8469                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8470   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8471   "fmul %2,%0"
8472   [(set_attr "type" "fp")])
8473
8474 (define_insn "*mac_media"
8475   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8476         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8477                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8478                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
8479   "TARGET_SHMEDIA_FPU"
8480   "fmac.s %1, %2, %0"
8481   [(set_attr "type" "fparith_media")])
8482
8483 (define_insn "*macsf3"
8484   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8485         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
8486                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8487                  (match_operand:SF 3 "arith_reg_operand" "0")))
8488    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
8489   "TARGET_SH2E && ! TARGET_SH4"
8490   "fmac fr0,%2,%0"
8491   [(set_attr "type" "fp")
8492    (set_attr "fp_mode" "single")])
8493
8494 (define_expand "divsf3"
8495   [(set (match_operand:SF 0 "arith_reg_operand" "")
8496         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
8497                 (match_operand:SF 2 "arith_reg_operand" "")))]
8498   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8499   "
8500 {
8501   if (TARGET_SH2E)
8502     {
8503       expand_sf_binop (&gen_divsf3_i, operands);
8504       DONE;
8505     }
8506 }")
8507
8508 (define_insn "*divsf3_media"
8509   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8510         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8511                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8512   "TARGET_SHMEDIA_FPU"
8513   "fdiv.s       %1, %2, %0"
8514   [(set_attr "type" "fdiv_media")])
8515
8516 (define_insn "divsf3_i"
8517   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8518         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
8519                  (match_operand:SF 2 "arith_reg_operand" "f")))
8520    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8521   "TARGET_SH2E"
8522   "fdiv %2,%0"
8523   [(set_attr "type" "fdiv")
8524    (set_attr "fp_mode" "single")])
8525
8526 (define_insn "floatdisf2"
8527   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8528         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8529   "TARGET_SHMEDIA_FPU"
8530   "float.qs %1, %0"
8531   [(set_attr "type" "fpconv_media")])
8532
8533 (define_expand "floatsisf2"
8534   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8535         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
8536   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8537   "
8538 {
8539   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
8540     {
8541       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8542       DONE;
8543     }
8544 }")
8545
8546 (define_insn "*floatsisf2_media"
8547   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8548         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8549   "TARGET_SHMEDIA_FPU"
8550   "float.ls     %1, %0"
8551   [(set_attr "type" "fpconv_media")])
8552
8553 (define_insn "floatsisf2_i4"
8554   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8555         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
8556    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8557   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8558   "float        %1,%0"
8559   [(set_attr "type" "fp")
8560    (set_attr "fp_mode" "single")])
8561
8562 (define_insn "*floatsisf2_ie"
8563   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8564         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
8565   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8566   "float        %1,%0"
8567   [(set_attr "type" "fp")])
8568
8569 (define_insn "fix_truncsfdi2"
8570   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8571         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8572   "TARGET_SHMEDIA_FPU"
8573   "ftrc.sq %1, %0"
8574   [(set_attr "type" "fpconv_media")])
8575
8576 (define_expand "fix_truncsfsi2"
8577   [(set (match_operand:SI 0 "fpul_operand" "=y")
8578         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8579   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8580   "
8581 {
8582   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
8583     {
8584       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8585       DONE;
8586     }
8587 }")
8588
8589 (define_insn "*fix_truncsfsi2_media"
8590   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8591         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8592   "TARGET_SHMEDIA_FPU"
8593   "ftrc.sl      %1, %0"
8594   [(set_attr "type" "fpconv_media")])
8595
8596 (define_insn "fix_truncsfsi2_i4"
8597   [(set (match_operand:SI 0 "fpul_operand" "=y")
8598         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8599    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8600   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8601   "ftrc %1,%0"
8602   [(set_attr "type" "ftrc_s")
8603    (set_attr "fp_mode" "single")])
8604
8605 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
8606 ;; fix_truncsfsi2_i4.
8607 ;; (define_insn "fix_truncsfsi2_i4_2"
8608 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8609 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8610 ;;   (use (reg:PSI FPSCR_REG))
8611 ;;   (clobber (reg:SI FPUL_REG))]
8612 ;;  "TARGET_SH4"
8613 ;;  "#"
8614 ;;  [(set_attr "length" "4")
8615 ;;   (set_attr "fp_mode" "single")])
8616
8617 ;;(define_split
8618 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8619 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8620 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
8621 ;;   (clobber (reg:SI FPUL_REG))]
8622 ;;  "TARGET_SH4"
8623 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8624 ;;            (use (match_dup 2))])
8625 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
8626
8627 (define_insn "*fixsfsi"
8628   [(set (match_operand:SI 0 "fpul_operand" "=y")
8629         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8630   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8631   "ftrc %1,%0"
8632   [(set_attr "type" "fp")])
8633
8634 (define_insn "cmpgtsf_t"
8635   [(set (reg:SI T_REG)
8636         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8637                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8638   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8639   "fcmp/gt      %1,%0"
8640   [(set_attr "type" "fp")
8641    (set_attr "fp_mode" "single")])
8642
8643 (define_insn "cmpeqsf_t"
8644   [(set (reg:SI T_REG)
8645         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8646                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8647   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8648   "fcmp/eq      %1,%0"
8649   [(set_attr "type" "fp")
8650    (set_attr "fp_mode" "single")])
8651
8652 (define_insn "ieee_ccmpeqsf_t"
8653   [(set (reg:SI T_REG)
8654         (ior:SI (reg:SI T_REG)
8655                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8656                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
8657   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8658   "* return output_ieee_ccmpeq (insn, operands);"
8659   [(set_attr "length" "4")])
8660
8661
8662 (define_insn "cmpgtsf_t_i4"
8663   [(set (reg:SI T_REG)
8664         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8665                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8666    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8667   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8668   "fcmp/gt      %1,%0"
8669   [(set_attr "type" "fp")
8670    (set_attr "fp_mode" "single")])
8671
8672 (define_insn "cmpeqsf_t_i4"
8673   [(set (reg:SI T_REG)
8674         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8675                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8676    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8677   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8678   "fcmp/eq      %1,%0"
8679   [(set_attr "type" "fp")
8680    (set_attr "fp_mode" "single")])
8681
8682 (define_insn "*ieee_ccmpeqsf_t_4"
8683   [(set (reg:SI T_REG)
8684         (ior:SI (reg:SI T_REG)
8685                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8686                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
8687    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8688   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8689   "* return output_ieee_ccmpeq (insn, operands);"
8690   [(set_attr "length" "4")
8691    (set_attr "fp_mode" "single")])
8692
8693 (define_insn "cmpeqsf_media"
8694   [(set (match_operand:DI 0 "register_operand" "=r")
8695         (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8696                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8697   "TARGET_SHMEDIA_FPU"
8698   "fcmpeq.s     %1, %2, %0"
8699   [(set_attr "type" "fcmp_media")])
8700
8701 (define_insn "cmpgtsf_media"
8702   [(set (match_operand:DI 0 "register_operand" "=r")
8703         (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8704                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8705   "TARGET_SHMEDIA_FPU"
8706   "fcmpgt.s     %1, %2, %0"
8707   [(set_attr "type" "fcmp_media")])
8708
8709 (define_insn "cmpgesf_media"
8710   [(set (match_operand:DI 0 "register_operand" "=r")
8711         (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8712                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8713   "TARGET_SHMEDIA_FPU"
8714   "fcmpge.s     %1, %2, %0"
8715   [(set_attr "type" "fcmp_media")])
8716
8717 (define_insn "cmpunsf_media"
8718   [(set (match_operand:DI 0 "register_operand" "=r")
8719         (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8720                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8721   "TARGET_SHMEDIA_FPU"
8722   "fcmpun.s     %1, %2, %0"
8723   [(set_attr "type" "fcmp_media")])
8724
8725 (define_expand "cmpsf"
8726   [(set (reg:SI T_REG)
8727         (compare (match_operand:SF 0 "arith_operand" "")
8728                  (match_operand:SF 1 "arith_operand" "")))]
8729   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8730   "
8731 {
8732   sh_compare_op0 = operands[0];
8733   sh_compare_op1 = operands[1];
8734   DONE;
8735 }")
8736
8737 (define_expand "negsf2"
8738   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8739         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8740   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8741   "
8742 {
8743   if (TARGET_SH2E)
8744     {
8745       expand_sf_unop (&gen_negsf2_i, operands);
8746       DONE;
8747     }
8748 }")
8749
8750 (define_insn "*negsf2_media"
8751   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8752         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8753   "TARGET_SHMEDIA_FPU"
8754   "fneg.s       %1, %0"
8755   [(set_attr "type" "fmove_media")])
8756
8757 (define_insn "negsf2_i"
8758   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8759         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8760    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8761   "TARGET_SH2E"
8762   "fneg %0"
8763   [(set_attr "type" "fmove")
8764    (set_attr "fp_mode" "single")])
8765
8766 (define_expand "sqrtsf2"
8767   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8768         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8769   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8770   "
8771 {
8772   if (TARGET_SH3E)
8773     {
8774       expand_sf_unop (&gen_sqrtsf2_i, operands);
8775       DONE;
8776     }
8777 }")
8778
8779 (define_insn "*sqrtsf2_media"
8780   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8781         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8782   "TARGET_SHMEDIA_FPU"
8783   "fsqrt.s      %1, %0"
8784   [(set_attr "type" "fdiv_media")])
8785
8786 (define_insn "sqrtsf2_i"
8787   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8788         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8789    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8790   "TARGET_SH3E"
8791   "fsqrt        %0"
8792   [(set_attr "type" "fdiv")
8793    (set_attr "fp_mode" "single")])
8794
8795 (define_insn "rsqrtsf2"
8796   [(set (match_operand:SF 0 "register_operand" "=f")
8797         (div:SF (match_operand:SF 1 "immediate_operand" "i")
8798                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
8799    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8800   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
8801    && operands[1] == CONST1_RTX (SFmode)"
8802   "fsrra        %0"
8803   [(set_attr "type" "fsrra")
8804    (set_attr "fp_mode" "single")])
8805
8806 (define_insn "fsca"
8807   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8808         (vec_concat:V2SF
8809          (unspec:SF [(mult:SF
8810                       (float:SF (match_operand:SI 1 "fpul_operand" "y"))
8811                       (match_operand:SF 2 "immediate_operand" "i"))
8812                     ] UNSPEC_FSINA)
8813          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
8814                     ] UNSPEC_FCOSA)))
8815    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8816   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
8817    && operands[2] == sh_fsca_int2sf ()"
8818   "fsca fpul,%d0"
8819   [(set_attr "type" "fsca")
8820    (set_attr "fp_mode" "single")])
8821
8822 (define_expand "sinsf2"
8823   [(set (match_operand:SF 0 "nonimmediate_operand" "")
8824         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
8825                    UNSPEC_FSINA))]
8826   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
8827   "
8828 {
8829   rtx scaled = gen_reg_rtx (SFmode);
8830   rtx truncated = gen_reg_rtx (SImode);
8831   rtx fsca = gen_reg_rtx (V2SFmode);
8832   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
8833
8834   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
8835   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
8836   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8837                           get_fpscr_rtx ()));
8838   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
8839   DONE;
8840 }")
8841
8842 (define_expand "cossf2"
8843   [(set (match_operand:SF 0 "nonimmediate_operand" "")
8844         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
8845                    UNSPEC_FCOSA))]
8846   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
8847   "
8848 {
8849   rtx scaled = gen_reg_rtx (SFmode);
8850   rtx truncated = gen_reg_rtx (SImode);
8851   rtx fsca = gen_reg_rtx (V2SFmode);
8852   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
8853
8854   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
8855   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
8856   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8857                           get_fpscr_rtx ()));
8858   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
8859   DONE;
8860 }")
8861
8862 (define_expand "sindf2"
8863   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8864         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
8865                    UNSPEC_FSINA))]
8866   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
8867   "
8868 {
8869   rtx scaled = gen_reg_rtx (DFmode);
8870   rtx truncated = gen_reg_rtx (SImode);
8871   rtx fsca = gen_reg_rtx (V2SFmode);
8872   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
8873   rtx sfresult = gen_reg_rtx (SFmode);
8874
8875   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
8876   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
8877   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8878                           get_fpscr_rtx ()));
8879   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
8880   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
8881   DONE;
8882 }")
8883
8884 (define_expand "cosdf2"
8885   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8886         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
8887                    UNSPEC_FCOSA))]
8888   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
8889   "
8890 {
8891   rtx scaled = gen_reg_rtx (DFmode);
8892   rtx truncated = gen_reg_rtx (SImode);
8893   rtx fsca = gen_reg_rtx (V2SFmode);
8894   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
8895   rtx sfresult = gen_reg_rtx (SFmode);
8896
8897   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
8898   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
8899   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8900                           get_fpscr_rtx ()));
8901   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
8902   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
8903   DONE;
8904 }")
8905
8906 (define_expand "abssf2"
8907   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8908         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8909   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8910   "
8911 {
8912   if (TARGET_SH2E)
8913     {
8914       expand_sf_unop (&gen_abssf2_i, operands);
8915       DONE;
8916     }
8917 }")
8918
8919 (define_insn "*abssf2_media"
8920   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8921         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8922   "TARGET_SHMEDIA_FPU"
8923   "fabs.s       %1, %0"
8924   [(set_attr "type" "fmove_media")])
8925
8926 (define_insn "abssf2_i"
8927   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8928         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8929    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8930   "TARGET_SH2E"
8931   "fabs %0"
8932   [(set_attr "type" "fmove")
8933    (set_attr "fp_mode" "single")])
8934
8935 (define_expand "adddf3"
8936   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8937         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8938                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8939   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
8940   "
8941 {
8942   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8943     {
8944       expand_df_binop (&gen_adddf3_i, operands);
8945       DONE;
8946     }
8947 }")
8948
8949 (define_insn "*adddf3_media"
8950   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8951         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8952                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8953   "TARGET_SHMEDIA_FPU"
8954   "fadd.d       %1, %2, %0"
8955   [(set_attr "type" "dfparith_media")])
8956
8957 (define_insn "adddf3_i"
8958   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8959         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8960                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8961    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8962   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8963   "fadd %2,%0"
8964   [(set_attr "type" "dfp_arith")
8965    (set_attr "fp_mode" "double")])
8966
8967 (define_expand "subdf3"
8968   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8969         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8970                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8971   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
8972   "
8973 {
8974   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8975     {
8976       expand_df_binop (&gen_subdf3_i, operands);
8977       DONE;
8978     }
8979 }")
8980
8981 (define_insn "*subdf3_media"
8982   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8983         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8984                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8985   "TARGET_SHMEDIA_FPU"
8986   "fsub.d       %1, %2, %0"
8987   [(set_attr "type" "dfparith_media")])
8988
8989 (define_insn "subdf3_i"
8990   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8991         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8992                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8993    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8994   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8995   "fsub %2,%0"
8996   [(set_attr "type" "dfp_arith")
8997    (set_attr "fp_mode" "double")])
8998
8999 (define_expand "muldf3"
9000   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
9001         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
9002                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
9003   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9004   "
9005 {
9006   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9007     {
9008       expand_df_binop (&gen_muldf3_i, operands);
9009       DONE;
9010     }
9011 }")
9012
9013 (define_insn "*muldf3_media"
9014   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9015         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
9016                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9017   "TARGET_SHMEDIA_FPU"
9018   "fmul.d       %1, %2, %0"
9019   [(set_attr "type" "dfmul_media")])
9020
9021 (define_insn "muldf3_i"
9022   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9023         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
9024                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
9025    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9026   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9027   "fmul %2,%0"
9028   [(set_attr "type" "dfp_arith")
9029    (set_attr "fp_mode" "double")])
9030
9031 (define_expand "divdf3"
9032   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
9033         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
9034                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
9035   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9036   "
9037 {
9038   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9039     {
9040       expand_df_binop (&gen_divdf3_i, operands);
9041       DONE;
9042     }
9043 }")
9044
9045 (define_insn "*divdf3_media"
9046   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9047         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
9048                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9049   "TARGET_SHMEDIA_FPU"
9050   "fdiv.d       %1, %2, %0"
9051   [(set_attr "type" "dfdiv_media")])
9052
9053 (define_insn "divdf3_i"
9054   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9055         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
9056                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
9057    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9058   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9059   "fdiv %2,%0"
9060   [(set_attr "type" "dfdiv")
9061    (set_attr "fp_mode" "double")])
9062
9063 (define_insn "floatdidf2"
9064   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9065         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
9066   "TARGET_SHMEDIA_FPU"
9067   "float.qd     %1, %0"
9068   [(set_attr "type" "dfpconv_media")])
9069
9070 (define_expand "floatsidf2"
9071   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
9072         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
9073   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9074   "
9075 {
9076   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9077     {
9078       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
9079                                       get_fpscr_rtx ()));
9080       DONE;
9081     }
9082 }")
9083
9084 (define_insn "*floatsidf2_media"
9085   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9086         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
9087   "TARGET_SHMEDIA_FPU"
9088   "float.ld     %1, %0"
9089   [(set_attr "type" "dfpconv_media")])
9090
9091 (define_insn "floatsidf2_i"
9092   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9093         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
9094    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9095   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9096   "float        %1,%0"
9097   [(set_attr "type" "dfp_conv")
9098    (set_attr "fp_mode" "double")])
9099
9100 (define_insn "fix_truncdfdi2"
9101   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
9102         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9103   "TARGET_SHMEDIA_FPU"
9104   "ftrc.dq      %1, %0"
9105   [(set_attr "type" "dfpconv_media")])
9106
9107 (define_expand "fix_truncdfsi2"
9108   [(set (match_operand:SI 0 "fpul_operand" "")
9109         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
9110   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9111   "
9112 {
9113   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9114     {
9115       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
9116                                           get_fpscr_rtx ()));
9117       DONE;
9118     }
9119 }")
9120
9121 (define_insn "*fix_truncdfsi2_media"
9122   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
9123         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9124   "TARGET_SHMEDIA_FPU"
9125   "ftrc.dl      %1, %0"
9126   [(set_attr "type" "dfpconv_media")])
9127
9128 (define_insn "fix_truncdfsi2_i"
9129   [(set (match_operand:SI 0 "fpul_operand" "=y")
9130         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
9131    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9132   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9133   "ftrc %1,%0"
9134   [(set_attr "type" "dfp_conv")
9135    (set_attr "dfp_comp" "no")
9136    (set_attr "fp_mode" "double")])
9137
9138 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
9139 ;; fix_truncdfsi2_i.
9140 ;; (define_insn "fix_truncdfsi2_i4"
9141 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9142 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
9143 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
9144 ;;    (clobber (reg:SI FPUL_REG))]
9145 ;;   "TARGET_SH4"
9146 ;;   "#"
9147 ;;   [(set_attr "length" "4")
9148 ;;    (set_attr "fp_mode" "double")])
9149 ;;
9150 ;; (define_split
9151 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9152 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
9153 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
9154 ;;    (clobber (reg:SI FPUL_REG))]
9155 ;;   "TARGET_SH4"
9156 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
9157 ;;            (use (match_dup 2))])
9158 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
9159
9160 (define_insn "cmpgtdf_t"
9161   [(set (reg:SI T_REG)
9162         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
9163                (match_operand:DF 1 "arith_reg_operand" "f")))
9164    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9165   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9166   "fcmp/gt      %1,%0"
9167   [(set_attr "type" "dfp_cmp")
9168    (set_attr "fp_mode" "double")])
9169
9170 (define_insn "cmpeqdf_t"
9171   [(set (reg:SI T_REG)
9172         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
9173                (match_operand:DF 1 "arith_reg_operand" "f")))
9174    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9175   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9176   "fcmp/eq      %1,%0"
9177   [(set_attr "type" "dfp_cmp")
9178    (set_attr "fp_mode" "double")])
9179
9180 (define_insn "*ieee_ccmpeqdf_t"
9181   [(set (reg:SI T_REG)
9182         (ior:SI (reg:SI T_REG)
9183                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
9184                        (match_operand:DF 1 "arith_reg_operand" "f"))))
9185    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9186   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9187   "* return output_ieee_ccmpeq (insn, operands);"
9188   [(set_attr "length" "4")
9189    (set_attr "fp_mode" "double")])
9190
9191 (define_insn "cmpeqdf_media"
9192   [(set (match_operand:DI 0 "register_operand" "=r")
9193         (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9194                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9195   "TARGET_SHMEDIA_FPU"
9196   "fcmpeq.d     %1,%2,%0"
9197   [(set_attr "type" "fcmp_media")])
9198
9199 (define_insn "cmpgtdf_media"
9200   [(set (match_operand:DI 0 "register_operand" "=r")
9201         (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9202                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9203   "TARGET_SHMEDIA_FPU"
9204   "fcmpgt.d     %1,%2,%0"
9205   [(set_attr "type" "fcmp_media")])
9206
9207 (define_insn "cmpgedf_media"
9208   [(set (match_operand:DI 0 "register_operand" "=r")
9209         (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9210                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9211   "TARGET_SHMEDIA_FPU"
9212   "fcmpge.d     %1,%2,%0"
9213   [(set_attr "type" "fcmp_media")])
9214
9215 (define_insn "cmpundf_media"
9216   [(set (match_operand:DI 0 "register_operand" "=r")
9217         (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9218                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9219   "TARGET_SHMEDIA_FPU"
9220   "fcmpun.d     %1,%2,%0"
9221   [(set_attr "type" "fcmp_media")])
9222
9223 (define_expand "cmpdf"
9224   [(set (reg:SI T_REG)
9225         (compare (match_operand:DF 0 "arith_operand" "")
9226                  (match_operand:DF 1 "arith_operand" "")))]
9227   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9228   "
9229 {
9230   sh_compare_op0 = operands[0];
9231   sh_compare_op1 = operands[1];
9232   DONE;
9233 }")
9234
9235 (define_expand "negdf2"
9236   [(set (match_operand:DF 0 "arith_reg_operand" "")
9237         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
9238   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9239   "
9240 {
9241   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9242     {
9243       expand_df_unop (&gen_negdf2_i, operands);
9244       DONE;
9245     }
9246 }")
9247
9248 (define_insn "*negdf2_media"
9249   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9250         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9251   "TARGET_SHMEDIA_FPU"
9252   "fneg.d       %1, %0"
9253   [(set_attr "type" "fmove_media")])
9254
9255 (define_insn "negdf2_i"
9256   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
9257         (neg:DF (match_operand:DF 1 "arith_reg_operand" "0")))
9258    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9259   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9260   "fneg %0"
9261   [(set_attr "type" "fmove")
9262    (set_attr "fp_mode" "double")])
9263
9264 (define_expand "sqrtdf2"
9265   [(set (match_operand:DF 0 "arith_reg_operand" "")
9266         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
9267   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9268   "
9269 {
9270   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9271     {
9272       expand_df_unop (&gen_sqrtdf2_i, operands);
9273       DONE;
9274     }
9275 }")
9276
9277 (define_insn "*sqrtdf2_media"
9278   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9279         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9280   "TARGET_SHMEDIA_FPU"
9281   "fsqrt.d      %1, %0"
9282   [(set_attr "type" "dfdiv_media")])
9283
9284 (define_insn "sqrtdf2_i"
9285   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
9286         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0")))
9287    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9288   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9289   "fsqrt        %0"
9290   [(set_attr "type" "dfdiv")
9291    (set_attr "fp_mode" "double")])
9292
9293 (define_expand "absdf2"
9294   [(set (match_operand:DF 0 "arith_reg_operand" "")
9295         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
9296   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9297   "
9298 {
9299   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9300     {
9301       expand_df_unop (&gen_absdf2_i, operands);
9302       DONE;
9303     }
9304 }")
9305
9306 (define_insn "*absdf2_media"
9307   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9308         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9309   "TARGET_SHMEDIA_FPU"
9310   "fabs.d       %1, %0"
9311   [(set_attr "type" "fmove_media")])
9312
9313 (define_insn "absdf2_i"
9314   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
9315         (abs:DF (match_operand:DF 1 "arith_reg_operand" "0")))
9316    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9317   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9318   "fabs %0"
9319   [(set_attr "type" "fmove")
9320    (set_attr "fp_mode" "double")])
9321
9322 (define_expand "extendsfdf2"
9323   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
9324         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
9325   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9326   "
9327 {
9328   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9329     {
9330       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
9331                                         get_fpscr_rtx ()));
9332       DONE;
9333     }
9334 }")
9335
9336 (define_insn "*extendsfdf2_media"
9337   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9338         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
9339   "TARGET_SHMEDIA_FPU"
9340   "fcnv.sd      %1, %0"
9341   [(set_attr "type" "dfpconv_media")])
9342
9343 (define_insn "extendsfdf2_i4"
9344   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9345         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
9346    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9347   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9348   "fcnvsd  %1,%0"
9349   [(set_attr "type" "fp")
9350    (set_attr "fp_mode" "double")])
9351
9352 (define_expand "truncdfsf2"
9353   [(set (match_operand:SF 0 "fpul_operand" "")
9354         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
9355   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9356   "
9357 {
9358   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9359     {
9360       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
9361                                        get_fpscr_rtx ()));
9362       DONE;
9363     }
9364 }")
9365
9366 (define_insn "*truncdfsf2_media"
9367   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9368         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9369   "TARGET_SHMEDIA_FPU"
9370   "fcnv.ds      %1, %0"
9371   [(set_attr "type" "dfpconv_media")])
9372
9373 (define_insn "truncdfsf2_i4"
9374   [(set (match_operand:SF 0 "fpul_operand" "=y")
9375         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
9376    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9377   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9378   "fcnvds  %1,%0"
9379   [(set_attr "type" "fp")
9380    (set_attr "fp_mode" "double")])
9381 \f
9382 ;; Bit field extract patterns.  These give better code for packed bitfields,
9383 ;; because they allow auto-increment addresses to be generated.
9384
9385 (define_expand "insv"
9386   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
9387                          (match_operand:SI 1 "immediate_operand" "")
9388                          (match_operand:SI 2 "immediate_operand" ""))
9389         (match_operand:SI 3 "general_operand" ""))]
9390   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
9391   "
9392 {
9393   rtx addr_target, orig_address, shift_reg, qi_val;
9394   HOST_WIDE_INT bitsize, size, v = 0;
9395   rtx x = operands[3];
9396
9397   /* ??? expmed doesn't care for non-register predicates.  */
9398   if (! memory_operand (operands[0], VOIDmode)
9399       || ! immediate_operand (operands[1], VOIDmode)
9400       || ! immediate_operand (operands[2], VOIDmode)
9401       || ! general_operand (x, VOIDmode))
9402     FAIL;
9403   /* If this isn't a 16 / 24 / 32 bit field, or if
9404      it doesn't start on a byte boundary, then fail.  */
9405   bitsize = INTVAL (operands[1]);
9406   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
9407       || (INTVAL (operands[2]) % 8) != 0)
9408     FAIL;
9409
9410   size = bitsize / 8;
9411   orig_address = XEXP (operands[0], 0);
9412   shift_reg = gen_reg_rtx (SImode);
9413   if (GET_CODE (x) == CONST_INT)
9414     {
9415       v = INTVAL (x);
9416       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
9417     }
9418   else
9419     {
9420       emit_insn (gen_movsi (shift_reg, operands[3]));
9421       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
9422     }
9423   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
9424
9425   operands[0] = replace_equiv_address (operands[0], addr_target);
9426   emit_insn (gen_movqi (operands[0], qi_val));
9427
9428   while (size -= 1)
9429     {
9430       if (GET_CODE (x) == CONST_INT)
9431         qi_val
9432           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
9433       else
9434         {
9435           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
9436           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
9437         }
9438       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
9439       emit_insn (gen_movqi (operands[0], qi_val));
9440     }
9441
9442   DONE;
9443 }")
9444
9445 (define_insn "movua"
9446   [(set (match_operand:SI 0 "register_operand" "=z")
9447         (sign_extract:SI (match_operand:SI 1 "unaligned_load_operand" "Sua>")
9448                          (const_int 32) (const_int 0)))]
9449   "TARGET_SH4A_ARCH"
9450   "movua.l      %1,%0"
9451   [(set_attr "type" "movua")])
9452
9453 ;; We shouldn't need this, but cse replaces increments with references
9454 ;; to other regs before flow has a chance to create post_inc
9455 ;; addressing modes, and only postreload's cse_move2add brings the
9456 ;; increments back to a usable form.
9457 (define_peephole2
9458   [(set (match_operand:SI 0 "register_operand" "")
9459         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
9460                          (const_int 32) (const_int 0)))
9461    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
9462   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
9463   [(set (match_operand:SI 0 "register_operand" "")
9464         (sign_extract:SI (mem:SI (post_inc:SI
9465                                   (match_operand:SI 1 "register_operand" "")))
9466                          (const_int 32) (const_int 0)))]
9467   "")
9468
9469 (define_expand "extv"
9470   [(set (match_operand:SI 0 "register_operand" "")
9471         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
9472                          (match_operand 2 "const_int_operand" "")
9473                          (match_operand 3 "const_int_operand" "")))]
9474   "TARGET_SH4A_ARCH"
9475 {
9476   if (TARGET_SH4A_ARCH
9477       && INTVAL (operands[2]) == 32
9478       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
9479       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
9480     {
9481       emit_insn (gen_movua (operands[0],
9482                             adjust_address (operands[1], SImode, 0)));
9483       DONE;
9484     }
9485
9486   FAIL;
9487 })
9488
9489 (define_expand "extzv"
9490   [(set (match_operand:SI 0 "register_operand" "")
9491         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
9492                          (match_operand 2 "const_int_operand" "")
9493                          (match_operand 3 "const_int_operand" "")))]
9494   "TARGET_SH4A_ARCH"
9495 {
9496   if (TARGET_SH4A_ARCH
9497       && INTVAL (operands[2]) == 32
9498       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
9499       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
9500     {
9501       emit_insn (gen_movua (operands[0],
9502                             adjust_address (operands[1], SImode, 0)));
9503       DONE;
9504     }
9505
9506   FAIL;
9507 })
9508
9509 \f
9510 ;; -------------------------------------------------------------------------
9511 ;; Peepholes
9512 ;; -------------------------------------------------------------------------
9513
9514 ;; This matches cases where a stack pointer increment at the start of the
9515 ;; epilogue combines with a stack slot read loading the return value.
9516
9517 (define_peephole
9518   [(set (match_operand:SI 0 "arith_reg_operand" "")
9519         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
9520    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
9521   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
9522   "mov.l        @%1+,%0")
9523
9524 ;; See the comment on the dt combiner pattern above.
9525
9526 (define_peephole
9527   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9528         (plus:SI (match_dup 0)
9529                  (const_int -1)))
9530    (set (reg:SI T_REG)
9531         (eq:SI (match_dup 0)
9532                (const_int 0)))]
9533   "TARGET_SH2"
9534   "dt   %0")
9535
9536 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
9537 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
9538 ;; reload when the constant is too large for a reg+offset address.
9539
9540 ;; ??? We would get much better code if this was done in reload.  This would
9541 ;; require modifying find_reloads_address to recognize that if the constant
9542 ;; is out-of-range for an immediate add, then we get better code by reloading
9543 ;; the constant into a register than by reloading the sum into a register,
9544 ;; since the former is one instruction shorter if the address does not need
9545 ;; to be offsettable.  Unfortunately this does not work, because there is
9546 ;; only one register, r0, that can be used as an index register.  This register
9547 ;; is also the function return value register.  So, if we try to force reload
9548 ;; to use double-reg addresses, then we end up with some instructions that
9549 ;; need to use r0 twice.  The only way to fix this is to change the calling
9550 ;; convention so that r0 is not used to return values.
9551
9552 (define_peephole
9553   [(set (match_operand:SI 0 "register_operand" "=r")
9554         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9555    (set (mem:SI (match_dup 0))
9556         (match_operand:SI 2 "general_movsrc_operand" ""))]
9557   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9558   "mov.l        %2,@(%0,%1)")
9559
9560 (define_peephole
9561   [(set (match_operand:SI 0 "register_operand" "=r")
9562         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9563    (set (match_operand:SI 2 "general_movdst_operand" "")
9564         (mem:SI (match_dup 0)))]
9565   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9566   "mov.l        @(%0,%1),%2")
9567
9568 (define_peephole
9569   [(set (match_operand:SI 0 "register_operand" "=r")
9570         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9571    (set (mem:HI (match_dup 0))
9572         (match_operand:HI 2 "general_movsrc_operand" ""))]
9573   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9574   "mov.w        %2,@(%0,%1)")
9575
9576 (define_peephole
9577   [(set (match_operand:SI 0 "register_operand" "=r")
9578         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9579    (set (match_operand:HI 2 "general_movdst_operand" "")
9580         (mem:HI (match_dup 0)))]
9581   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9582   "mov.w        @(%0,%1),%2")
9583
9584 (define_peephole
9585   [(set (match_operand:SI 0 "register_operand" "=r")
9586         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9587    (set (mem:QI (match_dup 0))
9588         (match_operand:QI 2 "general_movsrc_operand" ""))]
9589   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9590   "mov.b        %2,@(%0,%1)")
9591
9592 (define_peephole
9593   [(set (match_operand:SI 0 "register_operand" "=r")
9594         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9595    (set (match_operand:QI 2 "general_movdst_operand" "")
9596         (mem:QI (match_dup 0)))]
9597   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9598   "mov.b        @(%0,%1),%2")
9599
9600 (define_peephole
9601   [(set (match_operand:SI 0 "register_operand" "=r")
9602         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9603    (set (mem:SF (match_dup 0))
9604         (match_operand:SF 2 "general_movsrc_operand" ""))]
9605   "TARGET_SH1 && REGNO (operands[0]) == 0
9606    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9607        || (GET_CODE (operands[2]) == SUBREG
9608            && REGNO (SUBREG_REG (operands[2])) < 16))
9609    && reg_unused_after (operands[0], insn)"
9610   "mov.l        %2,@(%0,%1)")
9611
9612 (define_peephole
9613   [(set (match_operand:SI 0 "register_operand" "=r")
9614         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9615    (set (match_operand:SF 2 "general_movdst_operand" "")
9616
9617         (mem:SF (match_dup 0)))]
9618   "TARGET_SH1 && REGNO (operands[0]) == 0
9619    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9620        || (GET_CODE (operands[2]) == SUBREG
9621            && REGNO (SUBREG_REG (operands[2])) < 16))
9622    && reg_unused_after (operands[0], insn)"
9623   "mov.l        @(%0,%1),%2")
9624
9625 (define_peephole
9626   [(set (match_operand:SI 0 "register_operand" "=r")
9627         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9628    (set (mem:SF (match_dup 0))
9629         (match_operand:SF 2 "general_movsrc_operand" ""))]
9630   "TARGET_SH2E && REGNO (operands[0]) == 0
9631    && ((GET_CODE (operands[2]) == REG
9632         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9633        || (GET_CODE (operands[2]) == SUBREG
9634            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9635    && reg_unused_after (operands[0], insn)"
9636   "fmov{.s|}    %2,@(%0,%1)")
9637
9638 (define_peephole
9639   [(set (match_operand:SI 0 "register_operand" "=r")
9640         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9641    (set (match_operand:SF 2 "general_movdst_operand" "")
9642
9643         (mem:SF (match_dup 0)))]
9644   "TARGET_SH2E && REGNO (operands[0]) == 0
9645    && ((GET_CODE (operands[2]) == REG
9646         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9647        || (GET_CODE (operands[2]) == SUBREG
9648            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9649    && reg_unused_after (operands[0], insn)"
9650   "fmov{.s|}    @(%0,%1),%2")
9651
9652 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
9653 (define_insn "sp_switch_1"
9654   [(const_int 1)]
9655   "TARGET_SH1"
9656   "*
9657 {
9658   rtx xoperands[1];
9659
9660   xoperands[0] = sp_switch;
9661   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
9662   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
9663   return \"mov r0,r15\";
9664 }"
9665   [(set_attr "length" "10")])
9666
9667 ;; Switch back to the original stack for interrupt functions with the
9668 ;; sp_switch attribute.  */
9669 (define_insn "sp_switch_2"
9670   [(const_int 2)]
9671   "TARGET_SH1"
9672   "mov.l @r15+,r15\;mov.l @r15+,r0"
9673   [(set_attr "length" "4")])
9674
9675 ;; Integer vector moves
9676
9677 (define_expand "movv8qi"
9678   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
9679         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
9680   "TARGET_SHMEDIA"
9681   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
9682
9683 (define_insn "movv8qi_i"
9684   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
9685         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9686   "TARGET_SHMEDIA
9687    && (register_operand (operands[0], V8QImode)
9688        || sh_register_operand (operands[1], V8QImode))"
9689   "@
9690         add     %1, r63, %0
9691         movi    %1, %0
9692         #
9693         ld%M1.q %m1, %0
9694         st%M0.q %m0, %N1"
9695   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9696    (set_attr "length" "4,4,16,4,4")])
9697
9698 (define_split
9699   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
9700         (subreg:V8QI (const_int 0) 0))]
9701   "TARGET_SHMEDIA"
9702   [(set (match_dup 0)
9703         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
9704                             (const_int 0) (const_int 0) (const_int 0)
9705                             (const_int 0) (const_int 0)]))])
9706
9707 (define_split
9708   [(set (match_operand 0 "arith_reg_dest" "")
9709         (match_operand 1 "sh_rep_vec" ""))]
9710   "TARGET_SHMEDIA && reload_completed
9711    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9712    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
9713    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
9714    && (XVECEXP (operands[1], 0, 0) != const0_rtx
9715        || XVECEXP (operands[1], 0, 1) != const0_rtx)
9716    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
9717        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
9718   [(set (match_dup 0) (match_dup 1))
9719    (match_dup 2)]
9720   "
9721 {
9722   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
9723   rtx elt1 = XVECEXP (operands[1], 0, 1);
9724
9725   if (unit_size > 2)
9726     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
9727   else
9728     {
9729       if (unit_size < 2)
9730         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
9731       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
9732     }
9733   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
9734   operands[1] = XVECEXP (operands[1], 0, 0);
9735   if (unit_size < 2)
9736     {
9737       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
9738         operands[1]
9739           = GEN_INT (TARGET_LITTLE_ENDIAN
9740                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
9741                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
9742       else
9743         {
9744           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
9745           operands[1]
9746             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
9747         }
9748     }
9749 }")
9750
9751 (define_split
9752   [(set (match_operand 0 "arith_reg_dest" "")
9753         (match_operand 1 "sh_const_vec" ""))]
9754   "TARGET_SHMEDIA && reload_completed
9755    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9756    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
9757    && operands[1] != CONST0_RTX (GET_MODE (operands[1]))"
9758   [(set (match_dup 0) (match_dup 1))]
9759   "
9760 {
9761   rtx v = operands[1];
9762   enum machine_mode new_mode
9763     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
9764
9765   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
9766   operands[1]
9767     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
9768 }")
9769
9770 (define_expand "movv2hi"
9771   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
9772         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
9773   "TARGET_SHMEDIA"
9774   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
9775
9776 (define_insn "movv2hi_i"
9777   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9778         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9779   "TARGET_SHMEDIA
9780    && (register_operand (operands[0], V2HImode)
9781        || sh_register_operand (operands[1], V2HImode))"
9782   "@
9783         addz.l  %1, r63, %0
9784         movi    %1, %0
9785         #
9786         ld%M1.l %m1, %0
9787         st%M0.l %m0, %N1"
9788   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9789    (set_attr "length" "4,4,16,4,4")])
9790
9791 (define_expand "movv4hi"
9792   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
9793         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
9794   "TARGET_SHMEDIA"
9795   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
9796
9797 (define_insn "movv4hi_i"
9798   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9799         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9800   "TARGET_SHMEDIA
9801    && (register_operand (operands[0], V4HImode)
9802        || sh_register_operand (operands[1], V4HImode))"
9803   "@
9804         add     %1, r63, %0
9805         movi    %1, %0
9806         #
9807         ld%M1.q %m1, %0
9808         st%M0.q %m0, %N1"
9809   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9810    (set_attr "length" "4,4,16,4,4")])
9811
9812 (define_expand "movv2si"
9813   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
9814         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
9815   "TARGET_SHMEDIA"
9816   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
9817
9818 (define_insn "movv2si_i"
9819   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
9820         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9821   "TARGET_SHMEDIA
9822    && (register_operand (operands[0], V2SImode)
9823        || sh_register_operand (operands[1], V2SImode))"
9824   "@
9825         add     %1, r63, %0
9826         #
9827         #
9828         ld%M1.q %m1, %0
9829         st%M0.q %m0, %N1"
9830   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9831    (set_attr "length" "4,4,16,4,4")])
9832
9833 ;; Multimedia Intrinsics
9834
9835 (define_insn "absv2si2"
9836   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9837         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
9838   "TARGET_SHMEDIA"
9839   "mabs.l       %1, %0"
9840   [(set_attr "type" "mcmp_media")])
9841
9842 (define_insn "absv4hi2"
9843   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9844         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
9845   "TARGET_SHMEDIA"
9846   "mabs.w       %1, %0"
9847   [(set_attr "type" "mcmp_media")])
9848
9849 (define_insn "addv2si3"
9850   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9851         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9852                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9853   "TARGET_SHMEDIA"
9854   "madd.l       %1, %2, %0"
9855   [(set_attr "type" "arith_media")])
9856
9857 (define_insn "addv4hi3"
9858   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9859         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9860                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9861   "TARGET_SHMEDIA"
9862   "madd.w       %1, %2, %0"
9863   [(set_attr "type" "arith_media")])
9864
9865 (define_insn "ssaddv2si3"
9866   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9867         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9868                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9869   "TARGET_SHMEDIA"
9870   "madds.l      %1, %2, %0"
9871   [(set_attr "type" "mcmp_media")])
9872
9873 (define_insn "usaddv8qi3"
9874   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9875         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
9876                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
9877   "TARGET_SHMEDIA"
9878   "madds.ub     %1, %2, %0"
9879   [(set_attr "type" "mcmp_media")])
9880
9881 (define_insn "ssaddv4hi3"
9882   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9883         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9884                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9885   "TARGET_SHMEDIA"
9886   "madds.w      %1, %2, %0"
9887   [(set_attr "type" "mcmp_media")])
9888
9889 (define_insn "negcmpeqv8qi"
9890   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9891         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
9892                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
9893   "TARGET_SHMEDIA"
9894   "mcmpeq.b     %N1, %N2, %0"
9895   [(set_attr "type" "mcmp_media")])
9896
9897 (define_insn "negcmpeqv2si"
9898   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9899         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
9900                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
9901   "TARGET_SHMEDIA"
9902   "mcmpeq.l     %N1, %N2, %0"
9903   [(set_attr "type" "mcmp_media")])
9904
9905 (define_insn "negcmpeqv4hi"
9906   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9907         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
9908                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9909   "TARGET_SHMEDIA"
9910   "mcmpeq.w     %N1, %N2, %0"
9911   [(set_attr "type" "mcmp_media")])
9912
9913 (define_insn "negcmpgtuv8qi"
9914   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9915         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
9916                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
9917   "TARGET_SHMEDIA"
9918   "mcmpgt.ub    %N1, %N2, %0"
9919   [(set_attr "type" "mcmp_media")])
9920
9921 (define_insn "negcmpgtv2si"
9922   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9923         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
9924                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
9925   "TARGET_SHMEDIA"
9926   "mcmpgt.l     %N1, %N2, %0"
9927   [(set_attr "type" "mcmp_media")])
9928
9929 (define_insn "negcmpgtv4hi"
9930   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9931         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
9932                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9933   "TARGET_SHMEDIA"
9934   "mcmpgt.w     %N1, %N2, %0"
9935   [(set_attr "type" "mcmp_media")])
9936
9937 (define_insn "mcmv"
9938   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9939         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9940                         (match_operand:DI 2 "arith_reg_operand" "r"))
9941                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
9942                         (not:DI (match_dup 2)))))]
9943   "TARGET_SHMEDIA"
9944   "mcmv %N1, %2, %0"
9945   [(set_attr "type" "arith_media")])
9946
9947 (define_insn "mcnvs_lw"
9948   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9949         (vec_concat:V4HI
9950          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
9951          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
9952   "TARGET_SHMEDIA"
9953   "mcnvs.lw     %N1, %N2, %0"
9954   [(set_attr "type" "mcmp_media")])
9955
9956 (define_insn "mcnvs_wb"
9957   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9958         (vec_concat:V8QI
9959          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
9960          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9961   "TARGET_SHMEDIA"
9962   "mcnvs.wb     %N1, %N2, %0"
9963   [(set_attr "type" "mcmp_media")])
9964
9965 (define_insn "mcnvs_wub"
9966   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9967         (vec_concat:V8QI
9968          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
9969          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9970   "TARGET_SHMEDIA"
9971   "mcnvs.wub    %N1, %N2, %0"
9972   [(set_attr "type" "mcmp_media")])
9973
9974 (define_insn "mextr_rl"
9975   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9976         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9977                              (match_operand:HI 3 "mextr_bit_offset" "i"))
9978                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
9979                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9980   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9981   "*
9982 {
9983   static char templ[16];
9984
9985   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
9986            (int) INTVAL (operands[3]) >> 3);
9987   return templ;
9988 }"
9989   [(set_attr "type" "arith_media")])
9990
9991 (define_insn "*mextr_lr"
9992   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9993         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9994                            (match_operand:HI 3 "mextr_bit_offset" "i"))
9995                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
9996                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9997   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9998   "*
9999 {
10000   static char templ[16];
10001
10002   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
10003            (int) INTVAL (operands[4]) >> 3);
10004   return templ;
10005 }"
10006   [(set_attr "type" "arith_media")])
10007
10008 ; mextrN can be modelled with vec_select / vec_concat, but the selection
10009 ; vector then varies depending on endianness.
10010 (define_expand "mextr1"
10011   [(match_operand:DI 0 "arith_reg_dest" "")
10012    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10013    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10014   "TARGET_SHMEDIA"
10015   "
10016 {
10017   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10018                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
10019   DONE;
10020 }")
10021
10022 (define_expand "mextr2"
10023   [(match_operand:DI 0 "arith_reg_dest" "")
10024    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10025    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10026   "TARGET_SHMEDIA"
10027   "
10028 {
10029   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10030                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
10031   DONE;
10032 }")
10033
10034 (define_expand "mextr3"
10035   [(match_operand:DI 0 "arith_reg_dest" "")
10036    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10037    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10038   "TARGET_SHMEDIA"
10039   "
10040 {
10041   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10042                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
10043   DONE;
10044 }")
10045
10046 (define_expand "mextr4"
10047   [(match_operand:DI 0 "arith_reg_dest" "")
10048    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10049    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10050   "TARGET_SHMEDIA"
10051   "
10052 {
10053   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10054                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
10055   DONE;
10056 }")
10057
10058 (define_expand "mextr5"
10059   [(match_operand:DI 0 "arith_reg_dest" "")
10060    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10061    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10062   "TARGET_SHMEDIA"
10063   "
10064 {
10065   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10066                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
10067   DONE;
10068 }")
10069
10070 (define_expand "mextr6"
10071   [(match_operand:DI 0 "arith_reg_dest" "")
10072    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10073    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10074   "TARGET_SHMEDIA"
10075   "
10076 {
10077   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10078                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
10079   DONE;
10080 }")
10081
10082 (define_expand "mextr7"
10083   [(match_operand:DI 0 "arith_reg_dest" "")
10084    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10085    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10086   "TARGET_SHMEDIA"
10087   "
10088 {
10089   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10090                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
10091   DONE;
10092 }")
10093
10094 (define_expand "mmacfx_wl"
10095   [(match_operand:V2SI 0 "arith_reg_dest" "")
10096    (match_operand:V2HI 1 "extend_reg_operand" "")
10097    (match_operand:V2HI 2 "extend_reg_operand" "")
10098    (match_operand:V2SI 3 "arith_reg_operand" "")]
10099   "TARGET_SHMEDIA"
10100   "
10101 {
10102   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
10103                               operands[1], operands[2]));
10104   DONE;
10105 }")
10106
10107 (define_insn "mmacfx_wl_i"
10108   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10109         (ss_plus:V2SI
10110          (match_operand:V2SI 1 "arith_reg_operand" "0")
10111          (ss_truncate:V2SI
10112           (ashift:V2DI
10113            (sign_extend:V2DI
10114             (mult:V2SI
10115              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
10116              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
10117            (const_int 1)))))]
10118   "TARGET_SHMEDIA"
10119   "mmacfx.wl    %2, %3, %0"
10120   [(set_attr "type" "mac_media")])
10121
10122 (define_expand "mmacnfx_wl"
10123   [(match_operand:V2SI 0 "arith_reg_dest" "")
10124    (match_operand:V2HI 1 "extend_reg_operand" "")
10125    (match_operand:V2HI 2 "extend_reg_operand" "")
10126    (match_operand:V2SI 3 "arith_reg_operand" "")]
10127   "TARGET_SHMEDIA"
10128   "
10129 {
10130   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
10131                                operands[1], operands[2]));
10132   DONE;
10133 }")
10134
10135 (define_insn "mmacnfx_wl_i"
10136   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10137         (ss_minus:V2SI
10138          (match_operand:V2SI 1 "arith_reg_operand" "0")
10139          (ss_truncate:V2SI
10140           (ashift:V2DI
10141            (sign_extend:V2DI
10142             (mult:V2SI
10143              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
10144              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
10145            (const_int 1)))))]
10146   "TARGET_SHMEDIA"
10147   "mmacnfx.wl   %2, %3, %0"
10148   [(set_attr "type" "mac_media")])
10149
10150 (define_insn "mulv2si3"
10151   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10152         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10153                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10154   "TARGET_SHMEDIA"
10155   "mmul.l       %1, %2, %0"
10156   [(set_attr "type" "d2mpy_media")])
10157
10158 (define_insn "mulv4hi3"
10159   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10160         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10161                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10162   "TARGET_SHMEDIA"
10163   "mmul.w       %1, %2, %0"
10164   [(set_attr "type" "dmpy_media")])
10165
10166 (define_insn "mmulfx_l"
10167   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10168         (ss_truncate:V2SI
10169          (ashiftrt:V2DI
10170           (mult:V2DI
10171            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
10172            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
10173           (const_int 31))))]
10174   "TARGET_SHMEDIA"
10175   "mmulfx.l     %1, %2, %0"
10176   [(set_attr "type" "d2mpy_media")])
10177
10178 (define_insn "mmulfx_w"
10179   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10180         (ss_truncate:V4HI
10181          (ashiftrt:V4SI
10182           (mult:V4SI
10183            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10184            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10185           (const_int 15))))]
10186   "TARGET_SHMEDIA"
10187   "mmulfx.w     %1, %2, %0"
10188   [(set_attr "type" "dmpy_media")])
10189
10190 (define_insn "mmulfxrp_w"
10191   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10192         (ss_truncate:V4HI
10193          (ashiftrt:V4SI
10194           (plus:V4SI
10195            (mult:V4SI
10196             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10197             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10198            (const_int 16384))
10199           (const_int 15))))]
10200   "TARGET_SHMEDIA"
10201   "mmulfxrp.w   %1, %2, %0"
10202   [(set_attr "type" "dmpy_media")])
10203
10204 (define_expand "mmulhi_wl"
10205   [(match_operand:V2SI 0 "arith_reg_dest" "")
10206    (match_operand:V4HI 1 "arith_reg_operand" "")
10207    (match_operand:V4HI 2 "arith_reg_operand" "")]
10208   "TARGET_SHMEDIA"
10209   "
10210 {
10211   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
10212              (operands[0], operands[1], operands[2]));
10213   DONE;
10214 }")
10215
10216 (define_expand "mmullo_wl"
10217   [(match_operand:V2SI 0 "arith_reg_dest" "")
10218    (match_operand:V4HI 1 "arith_reg_operand" "")
10219    (match_operand:V4HI 2 "arith_reg_operand" "")]
10220   "TARGET_SHMEDIA"
10221   "
10222 {
10223   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
10224              (operands[0], operands[1], operands[2]));
10225   DONE;
10226 }")
10227
10228 (define_insn "mmul23_wl"
10229   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10230         (vec_select:V2SI
10231          (mult:V4SI
10232           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10233           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10234          (parallel [(const_int 2) (const_int 3)])))]
10235   "TARGET_SHMEDIA"
10236   "* return (TARGET_LITTLE_ENDIAN
10237              ? \"mmulhi.wl      %1, %2, %0\"
10238              : \"mmullo.wl      %1, %2, %0\");"
10239   [(set_attr "type" "dmpy_media")])
10240
10241 (define_insn "mmul01_wl"
10242   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10243         (vec_select:V2SI
10244          (mult:V4SI
10245           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10246           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10247          (parallel [(const_int 0) (const_int 1)])))]
10248   "TARGET_SHMEDIA"
10249   "* return (TARGET_LITTLE_ENDIAN
10250              ? \"mmullo.wl      %1, %2, %0\"
10251              : \"mmulhi.wl      %1, %2, %0\");"
10252   [(set_attr "type" "dmpy_media")])
10253
10254 (define_expand "mmulsum_wq"
10255   [(match_operand:DI 0 "arith_reg_dest" "")
10256    (match_operand:V4HI 1 "arith_reg_operand" "")
10257    (match_operand:V4HI 2 "arith_reg_operand" "")
10258    (match_operand:DI 3 "arith_reg_operand" "")]
10259   "TARGET_SHMEDIA"
10260   "
10261 {
10262   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
10263                                operands[1], operands[2]));
10264   DONE;
10265 }")
10266
10267 (define_insn "mmulsum_wq_i"
10268   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10269         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
10270          (plus:DI
10271           (plus:DI
10272            (vec_select:DI
10273             (mult:V4DI
10274              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
10275              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
10276             (parallel [(const_int 0)]))
10277            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
10278                                      (sign_extend:V4DI (match_dup 3)))
10279                           (parallel [(const_int 1)])))
10280           (plus:DI
10281            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
10282                                      (sign_extend:V4DI (match_dup 3)))
10283                           (parallel [(const_int 2)]))
10284            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
10285                                      (sign_extend:V4DI (match_dup 3)))
10286                           (parallel [(const_int 3)]))))))]
10287   "TARGET_SHMEDIA"
10288   "mmulsum.wq   %2, %3, %0"
10289   [(set_attr "type" "mac_media")])
10290
10291 (define_expand "mperm_w"
10292   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
10293    (match_operand:V4HI 1 "arith_reg_operand" "r")
10294    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
10295   "TARGET_SHMEDIA"
10296   "
10297 {
10298   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
10299              (operands[0], operands[1], operands[2]));
10300   DONE;
10301 }")
10302
10303 ; This use of vec_select isn't exactly correct according to rtl.texi
10304 ; (because not constant), but it seems a straightforward extension.
10305 (define_insn "mperm_w_little"
10306   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10307         (vec_select:V4HI
10308          (match_operand:V4HI 1 "arith_reg_operand" "r")
10309          (parallel
10310           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
10311                             (const_int 2) (const_int 0))
10312            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
10313            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
10314            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
10315   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
10316   "mperm.w      %1, %N2, %0"
10317   [(set_attr "type" "arith_media")])
10318
10319 (define_insn "mperm_w_big"
10320   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10321         (vec_select:V4HI
10322          (match_operand:V4HI 1 "arith_reg_operand" "r")
10323          (parallel
10324           [(zero_extract:QI (not:QI (match_operand:QI 2
10325                                      "extend_reg_or_0_operand" "rZ"))
10326                             (const_int 2) (const_int 0))
10327            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
10328            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
10329            (zero_extract:QI (not:QI (match_dup 2))
10330                             (const_int 2) (const_int 6))])))]
10331   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
10332   "mperm.w      %1, %N2, %0"
10333   [(set_attr "type" "arith_media")])
10334
10335 (define_insn "mperm_w0"
10336   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10337         (vec_duplicate:V4HI (truncate:HI (match_operand 1
10338                                           "trunc_hi_operand" "r"))))]
10339   "TARGET_SHMEDIA"
10340   "mperm.w      %1, r63, %0"
10341   [(set_attr "type" "arith_media")])
10342
10343 (define_expand "msad_ubq"
10344   [(match_operand:DI 0 "arith_reg_dest" "")
10345    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
10346    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
10347    (match_operand:DI 3 "arith_reg_operand" "")]
10348   "TARGET_SHMEDIA"
10349   "
10350 {
10351   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
10352                              operands[1], operands[2]));
10353   DONE;
10354 }")
10355
10356 (define_insn "msad_ubq_i"
10357   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10358         (plus:DI
10359          (plus:DI
10360           (plus:DI
10361            (plus:DI
10362             (match_operand:DI 1 "arith_reg_operand" "0")
10363             (abs:DI (vec_select:DI
10364                      (minus:V8DI
10365                       (zero_extend:V8DI
10366                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
10367                       (zero_extend:V8DI
10368                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
10369                      (parallel [(const_int 0)]))))
10370            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10371                                               (zero_extend:V8DI (match_dup 3)))
10372                                   (parallel [(const_int 1)]))))
10373           (plus:DI
10374            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10375                                               (zero_extend:V8DI (match_dup 3)))
10376                                   (parallel [(const_int 2)])))
10377            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10378                                               (zero_extend:V8DI (match_dup 3)))
10379                                   (parallel [(const_int 3)])))))
10380          (plus:DI
10381           (plus:DI
10382            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10383                                               (zero_extend:V8DI (match_dup 3)))
10384                                   (parallel [(const_int 4)])))
10385            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10386                                               (zero_extend:V8DI (match_dup 3)))
10387                                   (parallel [(const_int 5)]))))
10388           (plus:DI
10389            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10390                                               (zero_extend:V8DI (match_dup 3)))
10391                                   (parallel [(const_int 6)])))
10392            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10393                                               (zero_extend:V8DI (match_dup 3)))
10394                                   (parallel [(const_int 7)])))))))]
10395   "TARGET_SHMEDIA"
10396   "msad.ubq     %N2, %N3, %0"
10397   [(set_attr "type" "mac_media")])
10398
10399 (define_insn "mshalds_l"
10400   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10401         (ss_truncate:V2SI
10402          (ashift:V2DI
10403           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
10404           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
10405                   (const_int 31)))))]
10406   "TARGET_SHMEDIA"
10407   "mshalds.l    %1, %2, %0"
10408   [(set_attr "type" "mcmp_media")])
10409
10410 (define_insn "mshalds_w"
10411   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10412         (ss_truncate:V4HI
10413          (ashift:V4SI
10414           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10415           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
10416                   (const_int 15)))))]
10417   "TARGET_SHMEDIA"
10418   "mshalds.w    %1, %2, %0"
10419   [(set_attr "type" "mcmp_media")])
10420
10421 (define_insn "ashrv2si3"
10422   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10423         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10424                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10425   "TARGET_SHMEDIA"
10426   "mshard.l     %1, %2, %0"
10427   [(set_attr "type" "arith_media")])
10428
10429 (define_insn "ashrv4hi3"
10430   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10431         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10432                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10433   "TARGET_SHMEDIA"
10434   "mshard.w     %1, %2, %0"
10435   [(set_attr "type" "arith_media")])
10436
10437 (define_insn "mshards_q"
10438   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
10439         (ss_truncate:HI
10440          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
10441                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
10442   "TARGET_SHMEDIA"
10443   "mshards.q    %1, %N2, %0"
10444   [(set_attr "type" "mcmp_media")])
10445
10446 (define_expand "mshfhi_b"
10447   [(match_operand:V8QI 0 "arith_reg_dest" "")
10448    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10449    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
10450   "TARGET_SHMEDIA"
10451   "
10452 {
10453   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
10454              (operands[0], operands[1], operands[2]));
10455   DONE;
10456 }")
10457
10458 (define_expand "mshflo_b"
10459   [(match_operand:V8QI 0 "arith_reg_dest" "")
10460    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10461    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
10462   "TARGET_SHMEDIA"
10463   "
10464 {
10465   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
10466              (operands[0], operands[1], operands[2]));
10467   DONE;
10468 }")
10469
10470 (define_insn "mshf4_b"
10471   [(set
10472     (match_operand:V8QI 0 "arith_reg_dest" "=r")
10473     (vec_select:V8QI
10474      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10475                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
10476      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
10477                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
10478   "TARGET_SHMEDIA"
10479   "* return (TARGET_LITTLE_ENDIAN
10480              ? \"mshfhi.b       %N1, %N2, %0\"
10481              : \"mshflo.b       %N1, %N2, %0\");"
10482   [(set_attr "type" "arith_media")])
10483
10484 (define_insn "mshf0_b"
10485   [(set
10486     (match_operand:V8QI 0 "arith_reg_dest" "=r")
10487     (vec_select:V8QI
10488      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10489                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
10490      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
10491                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
10492   "TARGET_SHMEDIA"
10493   "* return (TARGET_LITTLE_ENDIAN
10494              ? \"mshflo.b       %N1, %N2, %0\"
10495              : \"mshfhi.b       %N1, %N2, %0\");"
10496   [(set_attr "type" "arith_media")])
10497
10498 (define_expand "mshfhi_l"
10499   [(match_operand:V2SI 0 "arith_reg_dest" "")
10500    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10501    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
10502   "TARGET_SHMEDIA"
10503   "
10504 {
10505   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
10506              (operands[0], operands[1], operands[2]));
10507   DONE;
10508 }")
10509
10510 (define_expand "mshflo_l"
10511   [(match_operand:V2SI 0 "arith_reg_dest" "")
10512    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10513    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
10514   "TARGET_SHMEDIA"
10515   "
10516 {
10517   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
10518              (operands[0], operands[1], operands[2]));
10519   DONE;
10520 }")
10521
10522 (define_insn "mshf4_l"
10523   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10524         (vec_select:V2SI
10525          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10526                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
10527          (parallel [(const_int 1) (const_int 3)])))]
10528   "TARGET_SHMEDIA"
10529   "* return (TARGET_LITTLE_ENDIAN
10530              ? \"mshfhi.l       %N1, %N2, %0\"
10531              : \"mshflo.l       %N1, %N2, %0\");"
10532   [(set_attr "type" "arith_media")])
10533
10534 (define_insn "mshf0_l"
10535   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10536         (vec_select:V2SI
10537          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10538                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
10539          (parallel [(const_int 0) (const_int 2)])))]
10540   "TARGET_SHMEDIA"
10541   "* return (TARGET_LITTLE_ENDIAN
10542              ? \"mshflo.l       %N1, %N2, %0\"
10543              : \"mshfhi.l       %N1, %N2, %0\");"
10544   [(set_attr "type" "arith_media")])
10545
10546 (define_expand "mshfhi_w"
10547   [(match_operand:V4HI 0 "arith_reg_dest" "")
10548    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10549    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
10550   "TARGET_SHMEDIA"
10551   "
10552 {
10553   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
10554              (operands[0], operands[1], operands[2]));
10555   DONE;
10556 }")
10557
10558 (define_expand "mshflo_w"
10559   [(match_operand:V4HI 0 "arith_reg_dest" "")
10560    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10561    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
10562   "TARGET_SHMEDIA"
10563   "
10564 {
10565   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
10566              (operands[0], operands[1], operands[2]));
10567   DONE;
10568 }")
10569
10570 (define_insn "mshf4_w"
10571   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10572         (vec_select:V4HI
10573          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10574                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
10575          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
10576   "TARGET_SHMEDIA"
10577   "* return (TARGET_LITTLE_ENDIAN
10578              ? \"mshfhi.w       %N1, %N2, %0\"
10579              : \"mshflo.w       %N1, %N2, %0\");"
10580   [(set_attr "type" "arith_media")])
10581
10582 (define_insn "mshf0_w"
10583   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10584         (vec_select:V4HI
10585          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10586                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
10587          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
10588   "TARGET_SHMEDIA"
10589   "* return (TARGET_LITTLE_ENDIAN
10590              ? \"mshflo.w       %N1, %N2, %0\"
10591              : \"mshfhi.w       %N1, %N2, %0\");"
10592   [(set_attr "type" "arith_media")])
10593
10594 (define_insn "mshflo_w_x"
10595   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10596         (vec_select:V4HI
10597          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
10598                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
10599          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
10600   "TARGET_SHMEDIA"
10601   "mshflo.w     %N1, %N2, %0"
10602   [(set_attr "type" "arith_media")])
10603
10604 /* These are useful to expand ANDs and as combiner patterns.  */
10605 (define_insn_and_split "mshfhi_l_di"
10606   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
10607         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
10608                              (const_int 32))
10609                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
10610                         (const_int -4294967296))))]
10611   "TARGET_SHMEDIA"
10612   "@
10613         mshfhi.l        %N1, %N2, %0
10614         #"
10615   "TARGET_SHMEDIA && reload_completed
10616    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10617   [(set (match_dup 3) (match_dup 4))
10618    (set (match_dup 5) (match_dup 6))]
10619   "
10620 {
10621   operands[3] = gen_lowpart (SImode, operands[0]);
10622   operands[4] = gen_highpart (SImode, operands[1]);
10623   operands[5] = gen_highpart (SImode, operands[0]);
10624   operands[6] = gen_highpart (SImode, operands[2]);
10625 }"
10626   [(set_attr "type" "arith_media")])
10627
10628 (define_insn "*mshfhi_l_di_rev"
10629   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10630         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10631                         (const_int -4294967296))
10632                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10633                              (const_int 32))))]
10634   "TARGET_SHMEDIA"
10635   "mshfhi.l     %N2, %N1, %0"
10636   [(set_attr "type" "arith_media")])
10637
10638 (define_split
10639   [(set (match_operand:DI 0 "arith_reg_dest" "")
10640         (ior:DI (zero_extend:DI (match_operand:SI 1
10641                                               "extend_reg_or_0_operand" ""))
10642                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
10643                         (const_int -4294967296))))
10644    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
10645   "TARGET_SHMEDIA"
10646   [(const_int 0)]
10647   "
10648 {
10649   emit_insn (gen_ashldi3_media (operands[3],
10650                                 simplify_gen_subreg (DImode, operands[1],
10651                                                      SImode, 0),
10652                                 GEN_INT (32)));
10653   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
10654   DONE;
10655 }")
10656
10657 (define_insn "mshflo_l_di"
10658   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10659         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10660                         (const_int 4294967295))
10661                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10662                            (const_int 32))))]
10663
10664   "TARGET_SHMEDIA"
10665   "mshflo.l     %N1, %N2, %0"
10666   [(set_attr "type" "arith_media")])
10667
10668 (define_insn "*mshflo_l_di_rev"
10669   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10670         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10671                            (const_int 32))
10672                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10673                         (const_int 4294967295))))]
10674
10675   "TARGET_SHMEDIA"
10676   "mshflo.l     %N2, %N1, %0"
10677   [(set_attr "type" "arith_media")])
10678
10679 ;; Combiner pattern for trampoline initialization.
10680 (define_insn_and_split "*double_shori"
10681   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10682         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
10683                            (const_int 32))
10684                 (match_operand:DI 2 "const_int_operand" "n")))]
10685   "TARGET_SHMEDIA
10686    && INTVAL (operands[2]) == trunc_int_for_mode (INTVAL (operands[2]), SImode)"
10687   "#"
10688   "rtx_equal_p (operands[0], operands[1])"
10689   [(const_int 0)]
10690   "
10691 {
10692   HOST_WIDE_INT v = INTVAL (operands[2]);
10693
10694   emit_insn (gen_shori_media (operands[0], operands[0],
10695              gen_int_mode (INTVAL (operands[2]) >> 16, HImode)));
10696   emit_insn (gen_shori_media (operands[0], operands[0],
10697                               gen_int_mode (v, HImode)));
10698   DONE;
10699 }")
10700
10701
10702 (define_insn "*mshflo_l_di_x"
10703   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10704         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
10705                                  "rZ"))
10706                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10707                            (const_int 32))))]
10708
10709   "TARGET_SHMEDIA"
10710   "mshflo.l     %N1, %N2, %0"
10711   [(set_attr "type" "arith_media")])
10712
10713 (define_insn_and_split "concat_v2sf"
10714   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
10715 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
10716         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
10717                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
10718
10719   "TARGET_SHMEDIA"
10720   "@
10721         mshflo.l        %N1, %N2, %0
10722         #
10723         #"
10724   "TARGET_SHMEDIA && reload_completed
10725    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10726   [(set (match_dup 3) (match_dup 1))
10727    (set (match_dup 4) (match_dup 2))]
10728   "
10729 {
10730   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
10731   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
10732 }"
10733   [(set_attr "type" "arith_media")])
10734
10735 (define_insn "*mshflo_l_di_x_rev"
10736   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10737         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10738                            (const_int 32))
10739                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
10740
10741   "TARGET_SHMEDIA"
10742   "mshflo.l     %N2, %N1, %0"
10743   [(set_attr "type" "arith_media")])
10744
10745 (define_insn "ashlv2si3"
10746   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10747         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10748                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10749   "TARGET_SHMEDIA"
10750   "mshlld.l     %1, %2, %0"
10751   [(set_attr "type" "arith_media")])
10752
10753 (define_insn "ashlv4hi3"
10754   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10755         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10756                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10757   "TARGET_SHMEDIA"
10758   "mshlld.w     %1, %2, %0"
10759   [(set_attr "type" "arith_media")])
10760
10761 (define_insn "lshrv2si3"
10762   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10763         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10764                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10765   "TARGET_SHMEDIA"
10766   "mshlrd.l     %1, %2, %0"
10767   [(set_attr "type" "arith_media")])
10768
10769 (define_insn "lshrv4hi3"
10770   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10771         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10772                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10773   "TARGET_SHMEDIA"
10774   "mshlrd.w     %1, %2, %0"
10775   [(set_attr "type" "arith_media")])
10776
10777 (define_insn "subv2si3"
10778   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10779         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10780                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10781   "TARGET_SHMEDIA"
10782   "msub.l       %N1, %2, %0"
10783   [(set_attr "type" "arith_media")])
10784
10785 (define_insn "subv4hi3"
10786   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10787         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10788                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10789   "TARGET_SHMEDIA"
10790   "msub.w       %N1, %2, %0"
10791   [(set_attr "type" "arith_media")])
10792
10793 (define_insn "sssubv2si3"
10794   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10795         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10796                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10797   "TARGET_SHMEDIA"
10798   "msubs.l      %N1, %2, %0"
10799   [(set_attr "type" "mcmp_media")])
10800
10801 (define_insn "ussubv8qi3"
10802   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10803         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10804                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
10805   "TARGET_SHMEDIA"
10806   "msubs.ub     %1, %2, %0"
10807   [(set_attr "type" "mcmp_media")])
10808
10809 (define_insn "sssubv4hi3"
10810   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10811         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10812                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10813   "TARGET_SHMEDIA"
10814   "msubs.w      %N1, %2, %0"
10815   [(set_attr "type" "mcmp_media")])
10816
10817 ;; Floating Point Intrinsics
10818
10819 (define_insn "fcosa_s"
10820   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10821         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10822                    UNSPEC_FCOSA))]
10823   "TARGET_SHMEDIA"
10824   "fcosa.s      %1, %0"
10825   [(set_attr "type" "atrans_media")])
10826
10827 (define_insn "fsina_s"
10828   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10829         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10830                    UNSPEC_FSINA))]
10831   "TARGET_SHMEDIA"
10832   "fsina.s      %1, %0"
10833   [(set_attr "type" "atrans_media")])
10834
10835 (define_insn "fipr"
10836   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10837         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
10838                                                     "fp_arith_reg_operand" "f")
10839                                                    (match_operand:V4SF 2
10840                                                     "fp_arith_reg_operand" "f"))
10841                                          (parallel [(const_int 0)]))
10842                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10843                                          (parallel [(const_int 1)])))
10844                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10845                                          (parallel [(const_int 2)]))
10846                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10847                                          (parallel [(const_int 3)])))))]
10848   "TARGET_SHMEDIA"
10849   "fipr.s       %1, %2, %0"
10850   [(set_attr "type" "fparith_media")])
10851
10852 (define_insn "fsrra_s"
10853   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10854         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
10855                    UNSPEC_FSRRA))]
10856   "TARGET_SHMEDIA"
10857   "fsrra.s      %1, %0"
10858   [(set_attr "type" "atrans_media")])
10859
10860 (define_insn "ftrv"
10861   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
10862         (plus:V4SF
10863          (plus:V4SF
10864           (mult:V4SF
10865            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
10866                             (parallel [(const_int 0) (const_int 5)
10867                                        (const_int 10) (const_int 15)]))
10868            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
10869           (mult:V4SF
10870            (vec_select:V4SF (match_dup 1)
10871                             (parallel [(const_int 4) (const_int 9)
10872                                        (const_int 14) (const_int 3)]))
10873            (vec_select:V4SF (match_dup 2)
10874                             (parallel [(const_int 1) (const_int 2)
10875                                        (const_int 3) (const_int 0)]))))
10876          (plus:V4SF
10877           (mult:V4SF
10878            (vec_select:V4SF (match_dup 1)
10879                             (parallel [(const_int 8) (const_int 13)
10880                                        (const_int 2) (const_int 7)]))
10881            (vec_select:V4SF (match_dup 2)
10882                             (parallel [(const_int 2) (const_int 3)
10883                                        (const_int 0) (const_int 1)])))
10884           (mult:V4SF
10885            (vec_select:V4SF (match_dup 1)
10886                             (parallel [(const_int 12) (const_int 1)
10887                                        (const_int 6) (const_int 11)]))
10888            (vec_select:V4SF (match_dup 2)
10889                             (parallel [(const_int 3) (const_int 0)
10890                                        (const_int 1) (const_int 2)]))))))]
10891   "TARGET_SHMEDIA"
10892   "ftrv.s %1, %2, %0"
10893   [(set_attr "type" "fparith_media")])
10894
10895 (define_insn "nsb"
10896   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
10897         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10898                    UNSPEC_NSB))]
10899   "TARGET_SHMEDIA"
10900   "nsb  %1, %0"
10901   [(set_attr "type" "arith_media")])
10902
10903 (define_insn "nsbsi"
10904   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
10905         (zero_extend:SI
10906          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10907                     UNSPEC_NSB)))]
10908   "TARGET_SHMEDIA"
10909   "nsb  %1, %0"
10910   [(set_attr "type" "arith_media")])
10911
10912 (define_insn "nsbdi"
10913   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10914         (zero_extend:DI
10915          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10916                     UNSPEC_NSB)))]
10917   "TARGET_SHMEDIA"
10918   "nsb  %1, %0"
10919   [(set_attr "type" "arith_media")])
10920
10921 (define_expand "ffsdi2"
10922   [(set (match_operand:DI 0 "arith_reg_dest" "")
10923         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
10924   "TARGET_SHMEDIA"
10925   "
10926 {
10927   rtx scratch = gen_reg_rtx (DImode);
10928   rtx last;
10929
10930   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
10931   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
10932   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
10933   emit_insn (gen_nsbdi (scratch, scratch));
10934   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
10935   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
10936   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
10937   REG_NOTES (last)
10938     = gen_rtx_EXPR_LIST (REG_EQUAL,
10939                          gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
10940   DONE;
10941 }")
10942
10943 (define_expand "ffssi2"
10944   [(set (match_operand:SI 0 "arith_reg_dest" "")
10945         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
10946   "TARGET_SHMEDIA"
10947   "
10948 {
10949   rtx scratch = gen_reg_rtx (SImode);
10950   rtx discratch = gen_reg_rtx (DImode);
10951   rtx last;
10952
10953   emit_insn (gen_adddi3 (discratch,
10954                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
10955                          constm1_rtx));
10956   emit_insn (gen_andcdi3 (discratch,
10957                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
10958                           discratch));
10959   emit_insn (gen_nsbsi (scratch, discratch));
10960   last = emit_insn (gen_subsi3 (operands[0],
10961                                 force_reg (SImode, GEN_INT (63)), scratch));
10962   REG_NOTES (last)
10963     = gen_rtx_EXPR_LIST (REG_EQUAL,
10964                          gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
10965   DONE;
10966 }")
10967
10968 (define_insn "byterev"
10969   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10970         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10971                          (parallel [(const_int 7) (const_int 6) (const_int 5)
10972                                     (const_int 4) (const_int 3) (const_int 2)
10973                                     (const_int 1) (const_int 0)])))]
10974   "TARGET_SHMEDIA"
10975   "byterev      %1, %0"
10976   [(set_attr "type" "arith_media")])
10977
10978 (define_insn "prefetch_media"
10979   [(prefetch (match_operand:QI 0 "address_operand" "p")
10980              (match_operand:SI 1 "const_int_operand" "n")
10981              (match_operand:SI 2 "const_int_operand" "n"))]
10982   "TARGET_SHMEDIA"
10983   "*
10984 {
10985   operands[0] = gen_rtx_MEM (QImode, operands[0]);
10986   output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
10987   return \"\";
10988 }"
10989   [(set_attr "type" "other")])
10990
10991 (define_insn "prefetch_i4"
10992   [(prefetch (match_operand:SI 0 "register_operand" "r")
10993              (match_operand:SI 1 "const_int_operand" "n")
10994              (match_operand:SI 2 "const_int_operand" "n"))]
10995   "TARGET_HARD_SH4"
10996   "*
10997 {
10998   return \"pref @%0\";
10999 }"
11000   [(set_attr "type" "other")])
11001
11002 (define_expand "prefetch"
11003   [(prefetch (match_operand:QI 0 "address_operand" "p")
11004              (match_operand:SI 1 "const_int_operand" "n")
11005              (match_operand:SI 2 "const_int_operand" "n"))]
11006   "TARGET_SHMEDIA || TARGET_HARD_SH4"
11007   "
11008 {
11009   if (TARGET_HARD_SH4 && ! register_operand (operands[0], SImode))
11010     {
11011       rtx reg = gen_reg_rtx (SImode);
11012       emit_move_insn (reg, operands[0]);
11013       operands[0] = reg;
11014     }
11015
11016   emit_insn ((TARGET_SHMEDIA ? gen_prefetch_media : gen_prefetch_i4)
11017              (operands[0], operands[1], operands[2]));
11018   DONE;
11019 }")