OSDN Git Service

* sh.md (cbranch define_delay) Use cond_delay_slot for
[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 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                 (if_then_else (eq_attr "braf_branch_p" "yes")
411                               (const_int 6)
412                               (const_int 10))
413                 (eq_attr "braf_branch_p" "yes")
414                 (const_int 10)
415 ;; ??? using pc is not computed transitively.
416                 (ne (match_dup 0) (match_dup 0))
417                 (const_int 12)
418                 (ne (symbol_ref ("flag_pic")) (const_int 0))
419                 (const_int 22)
420                 ] (const_int 14))
421          (eq_attr "type" "pt_media")
422          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
423                        (const_int 20) (const_int 12))
424          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
425                          (const_int 4)
426                          (const_int 2))))
427
428 ;; DFA descriptions for the pipelines
429
430 (include "sh1.md")
431 (include "shmedia.md")
432 (include "sh4.md")
433
434 ;; Definitions for filling delay slots
435
436 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
437
438 ;; ??? This should be (nil) instead of (const_int 0)
439 (define_attr "hit_stack" "yes,no"
440         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
441                    (const_int 0))
442                (const_string "no")]
443               (const_string "yes")))
444
445 (define_attr "interrupt_function" "no,yes"
446   (const (symbol_ref "current_function_interrupt")))
447
448 (define_attr "in_delay_slot" "yes,no"
449   (cond [(eq_attr "type" "cbranch") (const_string "no")
450          (eq_attr "type" "pcload,pcload_si") (const_string "no")
451          (eq_attr "needs_delay_slot" "yes") (const_string "no")
452          (eq_attr "length" "2") (const_string "yes")
453          ] (const_string "no")))
454
455 (define_attr "cond_delay_slot" "yes,no"
456   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
457          ] (const_string "no")))
458
459 (define_attr "is_sfunc" ""
460   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
461
462 (define_attr "is_mac_media" ""
463   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
464
465 (define_attr "branch_zero" "yes,no"
466   (cond [(eq_attr "type" "!cbranch") (const_string "no")
467          (ne (symbol_ref "(next_active_insn (insn)\
468                            == (prev_active_insn\
469                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
470                           && get_attr_length (next_active_insn (insn)) == 2")
471              (const_int 0))
472          (const_string "yes")]
473         (const_string "no")))
474
475 ;; SH4 Double-precision computation with double-precision result -
476 ;; the two halves are ready at different times.
477 (define_attr "dfp_comp" "yes,no"
478   (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")]
479         (const_string "no")))
480
481 ;; Insns for which the latency of a preceding fp insn is decreased by one.
482 (define_attr "late_fp_use" "yes,no" (const_string "no"))
483 ;; And feeding insns for which this relevant.
484 (define_attr "any_fp_comp" "yes,no"
485   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
486          (const_string "yes")]
487         (const_string "no")))
488
489 (define_attr "any_int_load" "yes,no"
490   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
491          (const_string "yes")]
492         (const_string "no")))
493
494 (define_delay
495   (eq_attr "needs_delay_slot" "yes")
496   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
497
498 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
499 ;; and thus we can't put a pop instruction in its delay slot.
500 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
501 ;; instruction can go in the delay slot.
502
503 ;; Since a normal return (rts) implicitly uses the PR register,
504 ;; we can't allow PR register loads in an rts delay slot.
505
506 (define_delay
507   (eq_attr "type" "return")
508   [(and (eq_attr "in_delay_slot" "yes")
509         (ior (and (eq_attr "interrupt_function" "no")
510                   (eq_attr "type" "!pload,prset"))
511              (and (eq_attr "interrupt_function" "yes")
512                   (ior
513                    (ne (symbol_ref "TARGET_SH3") (const_int 0))
514                    (eq_attr "hit_stack" "no"))))) (nil) (nil)])
515
516 ;; Since a call implicitly uses the PR register, we can't allow
517 ;; a PR register store in a jsr delay slot.
518
519 (define_delay
520   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
521   [(and (eq_attr "in_delay_slot" "yes")
522         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
523
524 ;; Say that we have annulled true branches, since this gives smaller and
525 ;; faster code when branches are predicted as not taken.
526
527 ;; ??? The non-annulled condition should really be "in_delay_slot",
528 ;; but insns that can be filled in non-annulled get priority over insns
529 ;; that can only be filled in anulled.
530
531 (define_delay
532   (and (eq_attr "type" "cbranch")
533        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
534   ;; SH2e has a hardware bug that pretty much prohibits the use of
535   ;; annuled delay slots.
536   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
537                                         (not (eq_attr "cpu" "sh2e"))) (nil)])
538 \f
539 ;; -------------------------------------------------------------------------
540 ;; SImode signed integer comparisons
541 ;; -------------------------------------------------------------------------
542
543 (define_insn ""
544   [(set (reg:SI T_REG)
545         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
546                        (match_operand:SI 1 "arith_operand" "K08,r"))
547                (const_int 0)))]
548   "TARGET_SH1"
549   "tst  %1,%0"
550   [(set_attr "type" "mt_group")])
551
552 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
553 ;; That would still allow reload to create cmpi instructions, but would
554 ;; perhaps allow forcing the constant into a register when that is better.
555 ;; Probably should use r0 for mem/imm compares, but force constant into a
556 ;; register for pseudo/imm compares.
557
558 (define_insn "cmpeqsi_t"
559   [(set (reg:SI T_REG)
560         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
561                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
562   "TARGET_SH1"
563   "@
564         tst     %0,%0
565         cmp/eq  %1,%0
566         cmp/eq  %1,%0"
567    [(set_attr "type" "mt_group")])
568
569 (define_insn "cmpgtsi_t"
570   [(set (reg:SI T_REG)
571         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
572                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
573   "TARGET_SH1"
574   "@
575         cmp/gt  %1,%0
576         cmp/pl  %0"
577    [(set_attr "type" "mt_group")])
578
579 (define_insn "cmpgesi_t"
580   [(set (reg:SI T_REG)
581         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
582                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
583   "TARGET_SH1"
584   "@
585         cmp/ge  %1,%0
586         cmp/pz  %0"
587    [(set_attr "type" "mt_group")])
588
589 ;; -------------------------------------------------------------------------
590 ;; SImode unsigned integer comparisons
591 ;; -------------------------------------------------------------------------
592
593 (define_insn "cmpgeusi_t"
594   [(set (reg:SI T_REG)
595         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
596                 (match_operand:SI 1 "arith_reg_operand" "r")))]
597   "TARGET_SH1"
598   "cmp/hs       %1,%0"
599    [(set_attr "type" "mt_group")])
600
601 (define_insn "cmpgtusi_t"
602   [(set (reg:SI T_REG)
603         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
604                 (match_operand:SI 1 "arith_reg_operand" "r")))]
605   "TARGET_SH1"
606   "cmp/hi       %1,%0"
607    [(set_attr "type" "mt_group")])
608
609 ;; We save the compare operands in the cmpxx patterns and use them when
610 ;; we generate the branch.
611
612 (define_expand "cmpsi"
613   [(set (reg:SI T_REG)
614         (compare (match_operand:SI 0 "cmpsi_operand" "")
615                  (match_operand:SI 1 "arith_operand" "")))]
616   "TARGET_SH1"
617   "
618 {
619   if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
620       && GET_CODE (operands[1]) != CONST_INT)
621     operands[0] = copy_to_mode_reg (SImode, operands[0]);
622   sh_compare_op0 = operands[0];
623   sh_compare_op1 = operands[1];
624   DONE;
625 }")
626 \f
627 ;; -------------------------------------------------------------------------
628 ;; DImode signed integer comparisons
629 ;; -------------------------------------------------------------------------
630
631 ;; ??? Could get better scheduling by splitting the initial test from the
632 ;; rest of the insn after reload.  However, the gain would hardly justify
633 ;; the sh.md size increase necessary to do that.
634
635 (define_insn ""
636   [(set (reg:SI T_REG)
637         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
638                        (match_operand:DI 1 "arith_operand" "r"))
639                (const_int 0)))]
640   "TARGET_SH1"
641   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
642                                  insn, operands);"
643   [(set_attr "length" "6")
644    (set_attr "type" "arith3b")])
645
646 (define_insn "cmpeqdi_t"
647   [(set (reg:SI T_REG)
648         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
649                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
650   "TARGET_SH1"
651   "@
652         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
653         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
654   [(set_attr "length" "6")
655    (set_attr "type" "arith3b")])
656
657 (define_split
658   [(set (reg:SI T_REG)
659         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
660                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
661 ;; If we applied this split when not optimizing, it would only be
662 ;; applied during the machine-dependent reorg, when no new basic blocks
663 ;; may be created.
664   "TARGET_SH1 && reload_completed && optimize"
665   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
666    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
667                            (label_ref (match_dup 6))
668                            (pc)))
669    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
670    (match_dup 6)]
671   "
672 {
673   operands[2]
674     = gen_rtx_REG (SImode,
675                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
676   operands[3]
677     = (operands[1] == const0_rtx
678        ? const0_rtx
679        : gen_rtx_REG (SImode,
680                       true_regnum (operands[1])
681                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
682   operands[4] = gen_lowpart (SImode, operands[0]);
683   operands[5] = gen_lowpart (SImode, operands[1]);
684   operands[6] = gen_label_rtx ();
685 }")
686
687 (define_insn "cmpgtdi_t"
688   [(set (reg:SI T_REG)
689         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
690                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
691   "TARGET_SH2"
692   "@
693         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
694         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
695   [(set_attr "length" "8")
696    (set_attr "type" "arith3")])
697
698 (define_insn "cmpgedi_t"
699   [(set (reg:SI T_REG)
700         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
701                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
702   "TARGET_SH2"
703   "@
704         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
705         cmp/pz\\t%S0"
706   [(set_attr "length" "8,2")
707    (set_attr "type" "arith3,mt_group")])
708 \f
709 ;; -------------------------------------------------------------------------
710 ;; DImode unsigned integer comparisons
711 ;; -------------------------------------------------------------------------
712
713 (define_insn "cmpgeudi_t"
714   [(set (reg:SI T_REG)
715         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
716                 (match_operand:DI 1 "arith_reg_operand" "r")))]
717   "TARGET_SH2"
718   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
719   [(set_attr "length" "8")
720    (set_attr "type" "arith3")])
721
722 (define_insn "cmpgtudi_t"
723   [(set (reg:SI T_REG)
724         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
725                 (match_operand:DI 1 "arith_reg_operand" "r")))]
726   "TARGET_SH2"
727   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
728   [(set_attr "length" "8")
729    (set_attr "type" "arith3")])
730
731 (define_insn "cmpeqdi_media"
732   [(set (match_operand:DI 0 "register_operand" "=r")
733         (eq:DI (match_operand:DI 1 "register_operand" "%r")
734                (match_operand:DI 2 "arith_reg_or_0_operand" "Nr")))]
735   "TARGET_SHMEDIA"
736   "cmpeq        %1, %N2, %0"
737   [(set_attr "type" "cmp_media")])
738
739 (define_insn "cmpgtdi_media"
740   [(set (match_operand:DI 0 "register_operand" "=r")
741         (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
742                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
743   "TARGET_SHMEDIA"
744   "cmpgt        %N1, %N2, %0"
745   [(set_attr "type" "cmp_media")])
746
747 (define_insn "cmpgtudi_media"
748   [(set (match_operand:DI 0 "register_operand" "=r")
749         (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
750                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
751   "TARGET_SHMEDIA"
752   "cmpgtu       %N1, %N2, %0"
753   [(set_attr "type" "cmp_media")])
754
755 ;; We save the compare operands in the cmpxx patterns and use them when
756 ;; we generate the branch.
757
758 (define_expand "cmpdi"
759   [(set (reg:SI T_REG)
760         (compare (match_operand:DI 0 "arith_operand" "")
761                  (match_operand:DI 1 "arith_operand" "")))]
762   "TARGET_SH2 || TARGET_SHMEDIA"
763   "
764 {
765   sh_compare_op0 = operands[0];
766   sh_compare_op1 = operands[1];
767   DONE;
768 }")
769 ;; -------------------------------------------------------------------------
770 ;; Conditional move instructions
771 ;; -------------------------------------------------------------------------
772
773 ;; The insn names may seem reversed, but note that cmveq performs the move
774 ;; if op1 == 0, and cmvne does it if op1 != 0.
775
776 (define_insn "movdicc_false"
777   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
778         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
779                              (const_int 0))
780          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
781          (match_operand:DI 3 "arith_reg_operand" "0")))]
782   "TARGET_SHMEDIA"
783   "cmveq        %1, %N2, %0"
784   [(set_attr "type" "arith_media")])
785
786 (define_insn "movdicc_true"
787   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
788         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
789                              (const_int 0))
790          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
791          (match_operand:DI 3 "arith_reg_operand" "0")))]
792   "TARGET_SHMEDIA"
793   "cmvne        %1, %N2, %0"
794   [(set_attr "type" "arith_media")])
795
796 (define_expand "movdicc"
797   [(set (match_operand:DI 0 "register_operand" "")
798         (if_then_else:DI (match_operand 1 "comparison_operator" "")
799                          (match_operand:DI 2 "register_operand" "")
800                          (match_operand:DI 3 "register_operand" "")))]
801   "TARGET_SHMEDIA"
802   "
803 {
804   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
805       && GET_MODE (sh_compare_op0) == DImode
806       && sh_compare_op1 == const0_rtx)
807     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
808                                   sh_compare_op0, sh_compare_op1);
809   else
810     {
811       rtx tmp;
812
813       if (no_new_pseudos)
814         FAIL;
815
816       tmp = gen_reg_rtx (DImode);
817
818       switch (GET_CODE (operands[1]))
819         {
820         case EQ:
821           emit_insn (gen_seq (tmp));
822           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
823           break;
824
825         case NE:
826           emit_insn (gen_seq (tmp));
827           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
828           break;
829
830         case GT:
831           emit_insn (gen_sgt (tmp));
832           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
833           break;
834
835         case LT:
836           emit_insn (gen_slt (tmp));
837           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
838           break;
839
840         case GE:
841           emit_insn (gen_slt (tmp));
842           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
843           break;
844
845         case LE:
846           emit_insn (gen_sgt (tmp));
847           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
848           break;
849
850         case GTU:
851           emit_insn (gen_sgtu (tmp));
852           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
853           break;
854
855         case LTU:
856           emit_insn (gen_sltu (tmp));
857           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
858           break;
859
860         case GEU:
861           emit_insn (gen_sltu (tmp));
862           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
863           break;
864
865         case LEU:
866           emit_insn (gen_sgtu (tmp));
867           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
868           break;
869
870         case UNORDERED:
871           emit_insn (gen_sunordered (tmp));
872           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
873           break;
874
875         case ORDERED:
876           emit_insn (gen_sunordered (tmp));
877           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
878           break;
879
880         case UNEQ:
881         case UNGE:
882         case UNGT:
883         case UNLE:
884         case UNLT:
885         case LTGT:
886           FAIL;
887
888         default:
889           abort ();
890         }
891     }
892 }")
893 \f
894 ;; -------------------------------------------------------------------------
895 ;; Addition instructions
896 ;; -------------------------------------------------------------------------
897
898 (define_expand "adddi3"
899   [(set (match_operand:DI 0 "arith_reg_operand" "")
900         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
901                  (match_operand:DI 2 "arith_operand" "")))]
902   ""
903   "
904 {
905   if (TARGET_SH1)
906     {
907       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
908         FAIL;
909       operands[2] = force_reg (DImode, operands[2]);
910       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
911       DONE;
912     }
913 }")
914
915 (define_insn "*adddi3_media"
916   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
917         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
918                  (match_operand:DI 2 "arith_operand" "r,I10")))]
919   "TARGET_SHMEDIA"
920   "@
921         add     %1, %2, %0
922         addi    %1, %2, %0"
923   [(set_attr "type" "arith_media")])
924
925 (define_insn "adddi3z_media"
926   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
927         (zero_extend:DI
928          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
929                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
930   "TARGET_SHMEDIA"
931   "addz.l       %1, %N2, %0"
932   [(set_attr "type" "arith_media")])
933
934 (define_insn "adddi3_compact"
935   [(set (match_operand:DI 0 "arith_reg_operand" "=&r")
936         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
937                  (match_operand:DI 2 "arith_reg_operand" "r")))
938    (clobber (reg:SI T_REG))]
939   "TARGET_SH1"
940   "#"
941   [(set_attr "length" "6")])
942
943 (define_split
944   [(set (match_operand:DI 0 "arith_reg_operand" "")
945         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
946                  (match_operand:DI 2 "arith_reg_operand" "")))
947    (clobber (reg:SI T_REG))]
948   "TARGET_SH1 && reload_completed"
949   [(const_int 0)]
950   "
951 {
952   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
953   high0 = gen_rtx_REG (SImode,
954                        true_regnum (operands[0])
955                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
956   high2 = gen_rtx_REG (SImode,
957                        true_regnum (operands[2])
958                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
959   emit_insn (gen_clrt ());
960   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
961   emit_insn (gen_addc1 (high0, high0, high2));
962   DONE;
963 }")
964
965 (define_insn "addc"
966   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
967         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
968                           (match_operand:SI 2 "arith_reg_operand" "r"))
969                  (reg:SI T_REG)))
970    (set (reg:SI T_REG)
971         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
972   "TARGET_SH1"
973   "addc %2,%0"
974   [(set_attr "type" "arith")])
975
976 (define_insn "addc1"
977   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
978         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
979                           (match_operand:SI 2 "arith_reg_operand" "r"))
980                  (reg:SI T_REG)))
981    (clobber (reg:SI T_REG))]
982   "TARGET_SH1"
983   "addc %2,%0"
984   [(set_attr "type" "arith")])
985
986 (define_expand "addsi3"
987   [(set (match_operand:SI 0 "arith_reg_operand" "")
988         (plus:SI (match_operand:SI 1 "arith_operand" "")
989                  (match_operand:SI 2 "arith_operand" "")))]
990   ""
991   "
992 {
993   if (TARGET_SHMEDIA)
994     operands[1] = force_reg (SImode, operands[1]);
995 }")
996
997 (define_insn "addsi3_media"
998   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
999         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1000                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1001   "TARGET_SHMEDIA"
1002   "@
1003         add.l   %1, %2, %0
1004         addi.l  %1, %2, %0"
1005   [(set_attr "type" "arith_media")])
1006
1007 (define_insn "*addsi3_compact"
1008   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1009         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1010                  (match_operand:SI 2 "arith_operand" "rI08")))]
1011   "TARGET_SH1"
1012   "add  %2,%0"
1013   [(set_attr "type" "arith")])
1014
1015 ;; -------------------------------------------------------------------------
1016 ;; Subtraction instructions
1017 ;; -------------------------------------------------------------------------
1018
1019 (define_expand "subdi3"
1020   [(set (match_operand:DI 0 "arith_reg_operand" "")
1021         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1022                   (match_operand:DI 2 "arith_reg_operand" "")))]
1023   ""
1024   "
1025 {
1026   if (TARGET_SH1)
1027     {
1028       operands[1] = force_reg (DImode, operands[1]);
1029       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1030       DONE;
1031     }
1032 }")
1033
1034 (define_insn "*subdi3_media"
1035   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1036         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1037                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1038   "TARGET_SHMEDIA"
1039   "sub  %N1, %2, %0"
1040   [(set_attr "type" "arith_media")])
1041
1042 (define_insn "subdi3_compact"
1043   [(set (match_operand:DI 0 "arith_reg_operand" "=&r")
1044         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1045                  (match_operand:DI 2 "arith_reg_operand" "r")))
1046    (clobber (reg:SI T_REG))]
1047   "TARGET_SH1"
1048   "#"
1049   [(set_attr "length" "6")])
1050
1051 (define_split
1052   [(set (match_operand:DI 0 "arith_reg_operand" "")
1053         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1054                   (match_operand:DI 2 "arith_reg_operand" "")))
1055    (clobber (reg:SI T_REG))]
1056   "TARGET_SH1 && reload_completed"
1057   [(const_int 0)]
1058   "
1059 {
1060   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1061   high0 = gen_rtx_REG (SImode,
1062                        true_regnum (operands[0])
1063                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1064   high2 = gen_rtx_REG (SImode,
1065                        true_regnum (operands[2])
1066                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1067   emit_insn (gen_clrt ());
1068   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1069   emit_insn (gen_subc1 (high0, high0, high2));
1070   DONE;
1071 }")
1072
1073 (define_insn "subc"
1074   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1075         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1076                             (match_operand:SI 2 "arith_reg_operand" "r"))
1077                   (reg:SI T_REG)))
1078    (set (reg:SI T_REG)
1079         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1080                           (reg:SI T_REG))
1081                 (match_dup 1)))]
1082   "TARGET_SH1"
1083   "subc %2,%0"
1084   [(set_attr "type" "arith")])
1085
1086 (define_insn "subc1"
1087   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1088         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1089                             (match_operand:SI 2 "arith_reg_operand" "r"))
1090                   (reg:SI T_REG)))
1091    (clobber (reg:SI T_REG))]
1092   "TARGET_SH1"
1093   "subc %2,%0"
1094   [(set_attr "type" "arith")])
1095
1096 (define_insn "*subsi3_internal"
1097   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1098         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1099                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1100   "TARGET_SH1"
1101   "sub  %2,%0"
1102   [(set_attr "type" "arith")])
1103
1104 (define_insn "*subsi3_media"
1105   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1106         (minus:SI (match_operand:SI 1 "extend_reg_or_0_operand" "rN")
1107                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1108   "TARGET_SHMEDIA"
1109   "sub.l        %N1, %2, %0"
1110   [(set_attr "type" "arith_media")])
1111
1112 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1113 ;; will sometimes save one instruction.  Otherwise we might get
1114 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1115 ;; are the same.
1116
1117 (define_expand "subsi3"
1118   [(set (match_operand:SI 0 "arith_reg_operand" "")
1119         (minus:SI (match_operand:SI 1 "arith_operand" "")
1120                   (match_operand:SI 2 "arith_reg_operand" "")))]
1121   ""
1122   "
1123 {
1124   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1125     {
1126       emit_insn (gen_negsi2 (operands[0], operands[2]));
1127       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1128       DONE;
1129     }
1130   if (TARGET_SHMEDIA)
1131     {
1132       if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1133         FAIL;
1134       if (operands[1] != const0_rtx)
1135         operands[1] = force_reg (SImode, operands[1]);
1136     }
1137 }")
1138 \f
1139 ;; -------------------------------------------------------------------------
1140 ;; Division instructions
1141 ;; -------------------------------------------------------------------------
1142
1143 ;; We take advantage of the library routines which don't clobber as many
1144 ;; registers as a normal function call would.
1145
1146 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1147 ;; also has an effect on the register that holds the address of the sfunc.
1148 ;; To make this work, we have an extra dummy insn that shows the use
1149 ;; of this register for reorg.
1150
1151 (define_insn "use_sfunc_addr"
1152   [(set (reg:SI PR_REG)
1153         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1154   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1155   ""
1156   [(set_attr "length" "0")])
1157
1158 (define_insn "udivsi3_sh2a"
1159   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1160         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1161                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1162   "TARGET_SH2A"
1163   "divu %2,%1"
1164   [(set_attr "type" "arith")])
1165
1166 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1167 ;; hard register 0.  If we used hard register 0, then the next instruction
1168 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1169 ;; gets allocated to a stack slot that needs its address reloaded, then
1170 ;; there is nothing to prevent reload from using r0 to reload the address.
1171 ;; This reload would clobber the value in r0 we are trying to store.
1172 ;; If we let reload allocate r0, then this problem can never happen.
1173
1174 (define_insn "udivsi3_i1"
1175   [(set (match_operand:SI 0 "register_operand" "=z")
1176         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1177    (clobber (reg:SI T_REG))
1178    (clobber (reg:SI PR_REG))
1179    (clobber (reg:SI R4_REG))
1180    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1181   "TARGET_SH1 && ! TARGET_SH4"
1182   "jsr  @%1%#"
1183   [(set_attr "type" "sfunc")
1184    (set_attr "needs_delay_slot" "yes")])
1185
1186 ; Since shmedia-nofpu code could be linked against shcompact code, and
1187 ; the udivsi3 libcall has the same name, we must consider all registers
1188 ; clobbered that are in the union of the registers clobbered by the
1189 ; shmedia and the shcompact implementation.  Note, if the shcompact
1190 ; implementation actually used shcompact code, we'd need to clobber
1191 ; also r23 and fr23.
1192 (define_insn "udivsi3_i1_media"
1193   [(set (match_operand:SI 0 "register_operand" "=z")
1194         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1195    (clobber (reg:SI T_MEDIA_REG))
1196    (clobber (reg:SI PR_MEDIA_REG))
1197    (clobber (reg:SI R20_REG))
1198    (clobber (reg:SI R21_REG))
1199    (clobber (reg:SI R22_REG))
1200    (clobber (reg:DI TR0_REG))
1201    (clobber (reg:DI TR1_REG))
1202    (clobber (reg:DI TR2_REG))
1203    (use (match_operand:DI 1 "target_operand" "b"))]
1204   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1205   "blink        %1, r18"
1206   [(set_attr "type" "sfunc")
1207    (set_attr "needs_delay_slot" "yes")])
1208
1209 (define_expand "udivsi3_i4_media"
1210   [(set (match_dup 3)
1211         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1212    (set (match_dup 4)
1213         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1214    (set (match_dup 5) (float:DF (match_dup 3)))
1215    (set (match_dup 6) (float:DF (match_dup 4)))
1216    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1217    (set (match_dup 8) (fix:DI (match_dup 7)))
1218    (set (match_operand:SI 0 "register_operand" "")
1219         (truncate:SI (match_dup 8)))]
1220   "TARGET_SHMEDIA_FPU"
1221   "
1222 {
1223   operands[3] = gen_reg_rtx (DImode);
1224   operands[4] = gen_reg_rtx (DImode);
1225   operands[5] = gen_reg_rtx (DFmode);
1226   operands[6] = gen_reg_rtx (DFmode);
1227   operands[7] = gen_reg_rtx (DFmode);
1228   operands[8] = gen_reg_rtx (DImode);
1229 }")
1230
1231 (define_insn "udivsi3_i4"
1232   [(set (match_operand:SI 0 "register_operand" "=y")
1233         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1234    (clobber (reg:SI T_REG))
1235    (clobber (reg:SI PR_REG))
1236    (clobber (reg:DF DR0_REG))
1237    (clobber (reg:DF DR2_REG))
1238    (clobber (reg:DF DR4_REG))
1239    (clobber (reg:SI R0_REG))
1240    (clobber (reg:SI R1_REG))
1241    (clobber (reg:SI R4_REG))
1242    (clobber (reg:SI R5_REG))
1243    (use (reg:PSI FPSCR_REG))
1244    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1245   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1246   "jsr  @%1%#"
1247   [(set_attr "type" "sfunc")
1248    (set_attr "fp_mode" "double")
1249    (set_attr "needs_delay_slot" "yes")])
1250
1251 (define_insn "udivsi3_i4_single"
1252   [(set (match_operand:SI 0 "register_operand" "=y")
1253         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1254    (clobber (reg:SI T_REG))
1255    (clobber (reg:SI PR_REG))
1256    (clobber (reg:DF DR0_REG))
1257    (clobber (reg:DF DR2_REG))
1258    (clobber (reg:DF DR4_REG))
1259    (clobber (reg:SI R0_REG))
1260    (clobber (reg:SI R1_REG))
1261    (clobber (reg:SI R4_REG))
1262    (clobber (reg:SI R5_REG))
1263    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1264   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1265   "jsr  @%1%#"
1266   [(set_attr "type" "sfunc")
1267    (set_attr "needs_delay_slot" "yes")])
1268
1269 (define_expand "udivsi3"
1270   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1271    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1272    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1273    (parallel [(set (match_operand:SI 0 "register_operand" "")
1274                    (udiv:SI (reg:SI R4_REG)
1275                             (reg:SI R5_REG)))
1276               (clobber (reg:SI T_REG))
1277               (clobber (reg:SI PR_REG))
1278               (clobber (reg:SI R4_REG))
1279               (use (match_dup 3))])]
1280   ""
1281   "
1282 {
1283   rtx first, last;
1284
1285   operands[3] = gen_reg_rtx (Pmode);
1286   /* Emit the move of the address to a pseudo outside of the libcall.  */
1287   if (TARGET_HARD_SH4 && TARGET_SH2E)
1288     {
1289       emit_move_insn (operands[3], function_symbol (\"__udivsi3_i4\"));
1290       if (TARGET_FPU_SINGLE)
1291         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1292       else
1293         last = gen_udivsi3_i4 (operands[0], operands[3]);
1294     }
1295   else if (TARGET_SHMEDIA_FPU)
1296     {
1297       operands[1] = force_reg (SImode, operands[1]);
1298       operands[2] = force_reg (SImode, operands[2]);
1299       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1300       DONE;
1301     }
1302   else if (TARGET_SH2A)
1303     {
1304       operands[1] = force_reg (SImode, operands[1]);
1305       operands[2] = force_reg (SImode, operands[2]);
1306       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1307       DONE;
1308     }
1309   else if (TARGET_SH5)
1310     {
1311       emit_move_insn (operands[3],
1312                       function_symbol (TARGET_FPU_ANY
1313                                        ? \"__udivsi3_i4\"
1314                                        : \"__udivsi3\"));
1315
1316       if (TARGET_SHMEDIA)
1317         last = gen_udivsi3_i1_media (operands[0],
1318                                      Pmode == DImode
1319                                      ? operands[3]
1320                                      : gen_rtx_SUBREG (DImode, operands[3],
1321                                                        0));
1322       else if (TARGET_FPU_ANY)
1323         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1324       else
1325         last = gen_udivsi3_i1 (operands[0], operands[3]);
1326     }
1327   else
1328     {
1329       emit_move_insn (operands[3], function_symbol (\"__udivsi3\"));
1330       last = gen_udivsi3_i1 (operands[0], operands[3]);
1331     }
1332   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1333   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1334   last = emit_insn (last);
1335   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1336      invariant code motion can move it.  */
1337   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1338   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1339   DONE;
1340 }")
1341
1342 (define_insn "divsi3_sh2a"
1343   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1344         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1345                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1346   "TARGET_SH2A"
1347   "divs %2,%1"
1348   [(set_attr "type" "arith")])
1349
1350 (define_insn "divsi3_i1"
1351   [(set (match_operand:SI 0 "register_operand" "=z")
1352         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1353    (clobber (reg:SI T_REG))
1354    (clobber (reg:SI PR_REG))
1355    (clobber (reg:SI R1_REG))
1356    (clobber (reg:SI R2_REG))
1357    (clobber (reg:SI R3_REG))
1358    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1359   "TARGET_SH1 && ! TARGET_SH4"
1360   "jsr  @%1%#"
1361   [(set_attr "type" "sfunc")
1362    (set_attr "needs_delay_slot" "yes")])
1363
1364 ; Since shmedia-nofpu code could be linked against shcompact code, and
1365 ; the sdivsi3 libcall has the same name, we must consider all registers
1366 ; clobbered that are in the union of the registers clobbered by the
1367 ; shmedia and the shcompact implementation.  Note, if the shcompact
1368 ; implementation actually used shcompact code, we'd need to clobber
1369 ; also r22, r23 and fr23.
1370 (define_insn "divsi3_i1_media"
1371   [(set (match_operand:SI 0 "register_operand" "=z")
1372         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1373    (clobber (reg:SI T_MEDIA_REG))
1374    (clobber (reg:SI PR_MEDIA_REG))
1375    (clobber (reg:SI R1_REG))
1376    (clobber (reg:SI R2_REG))
1377    (clobber (reg:SI R3_REG))
1378    (clobber (reg:SI R20_REG))
1379    (clobber (reg:SI R21_REG))
1380    (clobber (reg:DI TR0_REG))
1381    (clobber (reg:DI TR1_REG))
1382    (clobber (reg:DI TR2_REG))
1383    (use (match_operand:DI 1 "target_operand" "b"))]
1384   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1385   "blink        %1, r18"
1386   [(set_attr "type" "sfunc")])
1387
1388 (define_expand "divsi3_i4_media"
1389   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
1390    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
1391    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
1392    (set (match_operand:SI 0 "register_operand" "=r")
1393         (fix:SI (match_dup 5)))]
1394   "TARGET_SHMEDIA_FPU"
1395   "
1396 {
1397   operands[3] = gen_reg_rtx (DFmode);
1398   operands[4] = gen_reg_rtx (DFmode);
1399   operands[5] = gen_reg_rtx (DFmode);
1400 }")
1401
1402 (define_insn "divsi3_i4"
1403   [(set (match_operand:SI 0 "register_operand" "=y")
1404         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1405    (clobber (reg:SI PR_REG))
1406    (clobber (reg:DF DR0_REG))
1407    (clobber (reg:DF DR2_REG))
1408    (use (reg:PSI FPSCR_REG))
1409    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1410   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1411   "jsr  @%1%#"
1412   [(set_attr "type" "sfunc")
1413    (set_attr "fp_mode" "double")
1414    (set_attr "needs_delay_slot" "yes")])
1415
1416 (define_insn "divsi3_i4_single"
1417   [(set (match_operand:SI 0 "register_operand" "=y")
1418         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1419    (clobber (reg:SI PR_REG))
1420    (clobber (reg:DF DR0_REG))
1421    (clobber (reg:DF DR2_REG))
1422    (clobber (reg:SI R2_REG))
1423    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1424   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1425   "jsr  @%1%#"
1426   [(set_attr "type" "sfunc")
1427    (set_attr "needs_delay_slot" "yes")])
1428
1429 (define_expand "divsi3"
1430   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
1431    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1432    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1433    (parallel [(set (match_operand:SI 0 "register_operand" "")
1434                    (div:SI (reg:SI R4_REG)
1435                            (reg:SI R5_REG)))
1436               (clobber (reg:SI T_REG))
1437               (clobber (reg:SI PR_REG))
1438               (clobber (reg:SI R1_REG))
1439               (clobber (reg:SI R2_REG))
1440               (clobber (reg:SI R3_REG))
1441               (use (match_dup 3))])]
1442   ""
1443   "
1444 {
1445   rtx first, last;
1446
1447   operands[3] = gen_reg_rtx (Pmode);
1448   /* Emit the move of the address to a pseudo outside of the libcall.  */
1449   if (TARGET_HARD_SH4 && TARGET_SH2E)
1450     {
1451       emit_move_insn (operands[3], function_symbol (\"__sdivsi3_i4\"));
1452       if (TARGET_FPU_SINGLE)
1453         last = gen_divsi3_i4_single (operands[0], operands[3]);
1454       else
1455         last = gen_divsi3_i4 (operands[0], operands[3]);
1456     }
1457   else if (TARGET_SH2A)
1458     {
1459       operands[1] = force_reg (SImode, operands[1]);
1460       operands[2] = force_reg (SImode, operands[2]);
1461       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
1462       DONE;
1463     }
1464   else if (TARGET_SHMEDIA_FPU)
1465     {
1466       operands[1] = force_reg (SImode, operands[1]);
1467       operands[2] = force_reg (SImode, operands[2]);
1468       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
1469       DONE;
1470     }
1471   else if (TARGET_SH5)
1472     {
1473       emit_move_insn (operands[3],
1474                       function_symbol (TARGET_FPU_ANY
1475                                        ? \"__sdivsi3_i4\"
1476                                        : \"__sdivsi3\"));
1477
1478       if (TARGET_SHMEDIA)
1479         last = gen_divsi3_i1_media (operands[0],
1480                                     Pmode == DImode
1481                                     ? operands[3]
1482                                     : gen_rtx_SUBREG (DImode, operands[3],
1483                                                       0));
1484       else if (TARGET_FPU_ANY)
1485         last = gen_divsi3_i4_single (operands[0], operands[3]);
1486       else
1487         last = gen_divsi3_i1 (operands[0], operands[3]);
1488     }
1489   else
1490     {
1491       emit_move_insn (operands[3], function_symbol (\"__sdivsi3\"));
1492       last = gen_divsi3_i1 (operands[0], operands[3]);
1493     }
1494   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1495   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1496   last = emit_insn (last);
1497   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1498      invariant code motion can move it.  */
1499   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1500   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1501   DONE;
1502 }")
1503 \f
1504 ;; -------------------------------------------------------------------------
1505 ;; Multiplication instructions
1506 ;; -------------------------------------------------------------------------
1507
1508 (define_insn "umulhisi3_i"
1509   [(set (reg:SI MACL_REG)
1510         (mult:SI (zero_extend:SI
1511                   (match_operand:HI 0 "arith_reg_operand" "r"))
1512                  (zero_extend:SI
1513                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1514   "TARGET_SH1"
1515   "mulu.w       %1,%0"
1516   [(set_attr "type" "smpy")])
1517
1518 (define_insn "mulhisi3_i"
1519   [(set (reg:SI MACL_REG)
1520         (mult:SI (sign_extend:SI
1521                   (match_operand:HI 0 "arith_reg_operand" "r"))
1522                  (sign_extend:SI
1523                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1524   "TARGET_SH1"
1525   "muls.w       %1,%0"
1526   [(set_attr "type" "smpy")])
1527
1528 (define_expand "mulhisi3"
1529   [(set (reg:SI MACL_REG)
1530         (mult:SI (sign_extend:SI
1531                   (match_operand:HI 1 "arith_reg_operand" ""))
1532                  (sign_extend:SI
1533                   (match_operand:HI 2 "arith_reg_operand" ""))))
1534    (set (match_operand:SI 0 "arith_reg_operand" "")
1535         (reg:SI MACL_REG))]
1536   "TARGET_SH1"
1537   "
1538 {
1539   rtx first, last;
1540
1541   first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
1542   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1543   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1544      invariant code motion can move it.  */
1545   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1546   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1547   /* expand_binop can't find a suitable code in umul_widen_optab to
1548      make a REG_EQUAL note from, so make one here.
1549      See also smulsi3_highpart.
1550      ??? Alternatively, we could put this at the calling site of expand_binop,
1551      i.e. expand_expr.  */
1552   REG_NOTES (last)
1553     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1554                          REG_NOTES (last));
1555   DONE;
1556 }")
1557
1558 (define_expand "umulhisi3"
1559   [(set (reg:SI MACL_REG)
1560         (mult:SI (zero_extend:SI
1561                   (match_operand:HI 1 "arith_reg_operand" ""))
1562                  (zero_extend:SI
1563                   (match_operand:HI 2 "arith_reg_operand" ""))))
1564    (set (match_operand:SI 0 "arith_reg_operand" "")
1565         (reg:SI MACL_REG))]
1566   "TARGET_SH1"
1567   "
1568 {
1569   rtx first, last;
1570
1571   first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
1572   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1573   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1574      invariant code motion can move it.  */
1575   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1576   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1577   /* expand_binop can't find a suitable code in umul_widen_optab to
1578      make a REG_EQUAL note from, so make one here.
1579      See also smulsi3_highpart.
1580      ??? Alternatively, we could put this at the calling site of expand_binop,
1581      i.e. expand_expr.  */
1582   REG_NOTES (last)
1583     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1584                          REG_NOTES (last));
1585   DONE;
1586 }")
1587
1588 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
1589 ;; a call to a routine which clobbers known registers.
1590
1591 (define_insn ""
1592   [(set (match_operand:SI 1 "register_operand" "=z")
1593         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1594    (clobber (reg:SI MACL_REG))
1595    (clobber (reg:SI T_REG))
1596    (clobber (reg:SI PR_REG))
1597    (clobber (reg:SI R3_REG))
1598    (clobber (reg:SI R2_REG))
1599    (clobber (reg:SI R1_REG))
1600    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
1601   "TARGET_SH1"
1602   "jsr  @%0%#"
1603   [(set_attr "type" "sfunc")
1604    (set_attr "needs_delay_slot" "yes")])
1605
1606 (define_expand "mulsi3_call"
1607   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1608    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1609    (parallel[(set (match_operand:SI 0 "register_operand" "")
1610                   (mult:SI (reg:SI R4_REG)
1611                            (reg:SI R5_REG)))
1612              (clobber (reg:SI MACL_REG))
1613              (clobber (reg:SI T_REG))
1614              (clobber (reg:SI PR_REG))
1615              (clobber (reg:SI R3_REG))
1616              (clobber (reg:SI R2_REG))
1617              (clobber (reg:SI R1_REG))
1618              (use (match_operand:SI 3 "register_operand" ""))])]
1619   "TARGET_SH1"
1620   "")
1621
1622 (define_insn "mul_r"
1623   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1624         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
1625                  (match_operand:SI 2 "arith_reg_operand" "z")))]
1626   "TARGET_SH2A"
1627   "mulr %2,%0"
1628   [(set_attr "type" "dmpy")])
1629
1630 (define_insn "mul_l"
1631   [(set (reg:SI MACL_REG)
1632         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
1633                  (match_operand:SI 1 "arith_reg_operand" "r")))]
1634   "TARGET_SH2"
1635   "mul.l        %1,%0"
1636   [(set_attr "type" "dmpy")])
1637
1638 (define_expand "mulsi3"
1639   [(set (reg:SI MACL_REG)
1640         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
1641                   (match_operand:SI 2 "arith_reg_operand" "")))
1642    (set (match_operand:SI 0 "arith_reg_operand" "")
1643         (reg:SI MACL_REG))]
1644   "TARGET_SH1"
1645   "
1646 {
1647   rtx first, last;
1648
1649   if (!TARGET_SH2)
1650     {
1651       /* The address must be set outside the libcall,
1652          since it goes into a pseudo.  */
1653       rtx sym = function_symbol (\"__mulsi3\");
1654       rtx addr = force_reg (SImode, sym);
1655       rtx insns = gen_mulsi3_call (operands[0], operands[1],
1656                                    operands[2], addr);
1657       first = insns;
1658       last = emit_insn (insns);
1659     }
1660   else
1661     {
1662       rtx macl = gen_rtx_REG (SImode, MACL_REG);
1663
1664       first = emit_insn (gen_mul_l (operands[1], operands[2]));
1665       /* consec_sets_giv can only recognize the first insn that sets a
1666          giv as the giv insn.  So we must tag this also with a REG_EQUAL
1667          note.  */
1668       last = emit_insn (gen_movsi_i ((operands[0]), macl));
1669     }
1670   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1671      invariant code motion can move it.  */
1672   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1673   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1674   DONE;
1675 }")
1676
1677 (define_insn "mulsidi3_i"
1678   [(set (reg:SI MACH_REG)
1679         (truncate:SI
1680          (lshiftrt:DI
1681           (mult:DI
1682            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1683            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1684           (const_int 32))))
1685    (set (reg:SI MACL_REG)
1686         (mult:SI (match_dup 0)
1687                  (match_dup 1)))]
1688   "TARGET_SH2"
1689   "dmuls.l      %1,%0"
1690   [(set_attr "type" "dmpy")])
1691
1692 (define_expand "mulsidi3"
1693   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1694         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1695                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1696   "TARGET_SH2 || TARGET_SHMEDIA"
1697   "
1698 {
1699   if (TARGET_SH2)
1700     {
1701        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
1702                                         operands[2]));
1703        DONE;
1704     }
1705 }")
1706
1707 (define_insn "mulsidi3_media"
1708   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1709         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
1710                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
1711   "TARGET_SHMEDIA"
1712   "muls.l       %1, %2, %0"
1713   [(set_attr "type" "dmpy_media")])
1714
1715 (define_insn "mulsidi3_compact"
1716   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1717         (mult:DI
1718          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1719          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1720    (clobber (reg:SI MACH_REG))
1721    (clobber (reg:SI MACL_REG))]
1722   "TARGET_SH2"
1723   "#")
1724
1725 (define_split
1726   [(set (match_operand:DI 0 "arith_reg_operand" "")
1727         (mult:DI
1728          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1729          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1730    (clobber (reg:SI MACH_REG))
1731    (clobber (reg:SI MACL_REG))]
1732   "TARGET_SH2"
1733   [(const_int 0)]
1734   "
1735 {
1736   rtx low_dst = gen_lowpart (SImode, operands[0]);
1737   rtx high_dst = gen_highpart (SImode, operands[0]);
1738
1739   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
1740
1741   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1742   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1743   /* We need something to tag the possible REG_EQUAL notes on to.  */
1744   emit_move_insn (operands[0], operands[0]);
1745   DONE;
1746 }")
1747
1748 (define_insn "umulsidi3_i"
1749   [(set (reg:SI MACH_REG)
1750         (truncate:SI
1751          (lshiftrt:DI
1752           (mult:DI
1753            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1754            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1755           (const_int 32))))
1756    (set (reg:SI MACL_REG)
1757         (mult:SI (match_dup 0)
1758                  (match_dup 1)))]
1759   "TARGET_SH2"
1760   "dmulu.l      %1,%0"
1761   [(set_attr "type" "dmpy")])
1762
1763 (define_expand "umulsidi3"
1764   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1765         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1766                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1767   "TARGET_SH2 || TARGET_SHMEDIA"
1768   "
1769 {
1770   if (TARGET_SH2)
1771     {
1772        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
1773                                          operands[2]));
1774        DONE;
1775     }
1776 }")
1777
1778 (define_insn "umulsidi3_media"
1779   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1780         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
1781                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
1782   "TARGET_SHMEDIA"
1783   "mulu.l       %1, %2, %0"
1784   [(set_attr "type" "dmpy_media")])
1785
1786 (define_insn "umulsidi3_compact"
1787   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1788         (mult:DI
1789          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1790          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1791    (clobber (reg:SI MACH_REG))
1792    (clobber (reg:SI MACL_REG))]
1793   "TARGET_SH2"
1794   "#")
1795
1796 (define_split
1797   [(set (match_operand:DI 0 "arith_reg_operand" "")
1798         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1799                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1800    (clobber (reg:SI MACH_REG))
1801    (clobber (reg:SI MACL_REG))]
1802   "TARGET_SH2"
1803   [(const_int 0)]
1804   "
1805 {
1806   rtx low_dst = gen_lowpart (SImode, operands[0]);
1807   rtx high_dst = gen_highpart (SImode, operands[0]);
1808
1809   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
1810
1811   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1812   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1813   /* We need something to tag the possible REG_EQUAL notes on to.  */
1814   emit_move_insn (operands[0], operands[0]);
1815   DONE;
1816 }")
1817
1818 (define_insn "smulsi3_highpart_i"
1819   [(set (reg:SI MACH_REG)
1820         (truncate:SI
1821          (lshiftrt:DI
1822           (mult:DI
1823            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1824            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1825           (const_int 32))))
1826    (clobber (reg:SI MACL_REG))]
1827   "TARGET_SH2"
1828   "dmuls.l      %1,%0"
1829   [(set_attr "type" "dmpy")])
1830
1831 (define_expand "smulsi3_highpart"
1832   [(parallel
1833     [(set (reg:SI MACH_REG)
1834           (truncate:SI
1835            (lshiftrt:DI
1836             (mult:DI
1837              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1838              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1839             (const_int 32))))
1840     (clobber (reg:SI MACL_REG))])
1841    (set (match_operand:SI 0 "arith_reg_operand" "")
1842         (reg:SI MACH_REG))]
1843   "TARGET_SH2"
1844   "
1845 {
1846   rtx first, last;
1847
1848   first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
1849   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1850   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1851      invariant code motion can move it.  */
1852   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1853   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1854   /* expand_binop can't find a suitable code in mul_highpart_optab to
1855      make a REG_EQUAL note from, so make one here.
1856      See also {,u}mulhisi.
1857      ??? Alternatively, we could put this at the calling site of expand_binop,
1858      i.e. expand_mult_highpart.  */
1859   REG_NOTES (last)
1860     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1861                          REG_NOTES (last));
1862   DONE;
1863 }")
1864
1865 (define_insn "umulsi3_highpart_i"
1866   [(set (reg:SI MACH_REG)
1867         (truncate:SI
1868          (lshiftrt:DI
1869           (mult:DI
1870            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1871            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1872           (const_int 32))))
1873    (clobber (reg:SI MACL_REG))]
1874   "TARGET_SH2"
1875   "dmulu.l      %1,%0"
1876   [(set_attr "type" "dmpy")])
1877
1878 (define_expand "umulsi3_highpart"
1879   [(parallel
1880     [(set (reg:SI MACH_REG)
1881           (truncate:SI
1882            (lshiftrt:DI
1883             (mult:DI
1884              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1885              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1886             (const_int 32))))
1887     (clobber (reg:SI MACL_REG))])
1888    (set (match_operand:SI 0 "arith_reg_operand" "")
1889         (reg:SI MACH_REG))]
1890   "TARGET_SH2"
1891   "
1892 {
1893   rtx first, last;
1894
1895   first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
1896   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1897   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1898      invariant code motion can move it.  */
1899   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1900   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1901   DONE;
1902 }")
1903 \f
1904 ;; -------------------------------------------------------------------------
1905 ;; Logical operations
1906 ;; -------------------------------------------------------------------------
1907
1908 (define_insn "*andsi3_compact"
1909   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1910         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1911                 (match_operand:SI 2 "logical_operand" "r,K08")))]
1912   "TARGET_SH1"
1913   "and  %2,%0"
1914   [(set_attr "type" "arith")])
1915
1916 ;; If the constant is 255, then emit an extu.b instruction instead of an
1917 ;; and, since that will give better code.
1918
1919 (define_expand "andsi3"
1920   [(set (match_operand:SI 0 "arith_reg_operand" "")
1921         (and:SI (match_operand:SI 1 "arith_reg_operand" "")
1922                 (match_operand:SI 2 "logical_operand" "")))]
1923   "TARGET_SH1"
1924   "
1925 {
1926   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
1927     {
1928       emit_insn (gen_zero_extendqisi2 (operands[0],
1929                                        gen_lowpart (QImode, operands[1])));
1930       DONE;
1931     }
1932 }")
1933
1934 (define_insn_and_split "anddi3"
1935   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r,r")
1936         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
1937                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
1938   "TARGET_SHMEDIA"
1939   "@
1940         and     %1, %2, %0
1941         andi    %1, %2, %0
1942         #"
1943   "reload_completed
1944    && ! logical_operand (operands[2], DImode)"
1945   [(const_int 0)]
1946   "
1947 {
1948   if (INTVAL (operands[2]) == (unsigned) 0xffffffff)
1949     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
1950   else
1951     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
1952   DONE;
1953 }"
1954   [(set_attr "type" "arith_media")])
1955
1956 (define_insn "andcdi3"
1957   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1958         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
1959                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
1960   "TARGET_SHMEDIA"
1961   "andc %1,%2,%0"
1962   [(set_attr "type" "arith_media")])
1963
1964 (define_insn "iorsi3"
1965   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1966         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1967                 (match_operand:SI 2 "logical_operand" "r,K08")))]
1968   "TARGET_SH1"
1969   "or   %2,%0"
1970   [(set_attr "type" "arith")])
1971
1972 (define_insn "iordi3"
1973   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1974         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1975                 (match_operand:DI 2 "logical_operand" "r,I10")))]
1976   "TARGET_SHMEDIA"
1977   "@
1978         or      %1, %2, %0
1979         ori     %1, %2, %0"
1980   [(set_attr "type" "arith_media")])
1981
1982 (define_insn "xorsi3"
1983   [(set (match_operand:SI 0 "arith_reg_operand" "=z,r")
1984         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1985                 (match_operand:SI 2 "logical_operand" "K08,r")))]
1986   "TARGET_SH1"
1987   "xor  %2,%0"
1988   [(set_attr "type" "arith")])
1989
1990 (define_insn "xordi3"
1991   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1992         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1993                 (match_operand:DI 2 "shmedia_6bit_operand" "r,I06")))]
1994   "TARGET_SHMEDIA"
1995   "@
1996         xor     %1, %2, %0
1997         xori    %1, %2, %0"
1998   [(set_attr "type" "arith_media")])
1999
2000 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
2001 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
2002 (define_split
2003   [(set (match_operand:DI 0 "arith_reg_operand" "")
2004         (sign_extend:DI (match_operator 4 "binary_logical_operator"
2005                           [(match_operand 1 "any_register_operand" "")
2006                            (match_operand 2 "any_register_operand" "")])))]
2007   "TARGET_SHMEDIA"
2008   [(set (match_dup 5) (match_dup 4))
2009    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
2010 "
2011 {
2012   enum machine_mode inmode = GET_MODE (operands[1]);
2013   int offset = 0;
2014
2015   if (GET_CODE (operands[0]) == SUBREG)
2016     {
2017       offset = SUBREG_BYTE (operands[0]);
2018       operands[0] = SUBREG_REG (operands[0]);
2019     }
2020   if (GET_CODE (operands[0]) != REG)
2021     abort ();
2022   if (! TARGET_LITTLE_ENDIAN)
2023     offset += 8 - GET_MODE_SIZE (inmode);
2024   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
2025 }")
2026 \f
2027 ;; -------------------------------------------------------------------------
2028 ;; Shifts and rotates
2029 ;; -------------------------------------------------------------------------
2030
2031 (define_expand "rotldi3"
2032   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2033         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
2034                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
2035   "TARGET_SHMEDIA"
2036   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
2037
2038 (define_insn "rotldi3_mextr"
2039   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2040         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
2041                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
2042   "TARGET_SHMEDIA"
2043   "*
2044 {
2045   static char templ[16];
2046
2047   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
2048            8 - (int) (INTVAL (operands[2]) >> 3));
2049   return templ;
2050 }"
2051   [(set_attr "type" "arith_media")])
2052
2053 (define_expand "rotrdi3"
2054   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2055         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
2056                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
2057   "TARGET_SHMEDIA"
2058   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
2059
2060 (define_insn "rotrdi3_mextr"
2061   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2062         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
2063                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
2064   "TARGET_SHMEDIA"
2065   "*
2066 {
2067   static char templ[16];
2068
2069   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
2070   return templ;
2071 }"
2072   [(set_attr "type" "arith_media")])
2073
2074 (define_insn "rotlsi3_1"
2075   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2076         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
2077                    (const_int 1)))
2078    (set (reg:SI T_REG)
2079         (lshiftrt:SI (match_dup 1) (const_int 31)))]
2080   "TARGET_SH1"
2081   "rotl %0"
2082   [(set_attr "type" "arith")])
2083
2084 (define_insn "rotlsi3_31"
2085   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2086         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
2087                    (const_int 31)))
2088    (clobber (reg:SI T_REG))]
2089   "TARGET_SH1"
2090   "rotr %0"
2091   [(set_attr "type" "arith")])
2092
2093 (define_insn "rotlsi3_16"
2094   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2095         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
2096                    (const_int 16)))]
2097   "TARGET_SH1"
2098   "swap.w       %1,%0"
2099   [(set_attr "type" "arith")])
2100
2101 (define_expand "rotlsi3"
2102   [(set (match_operand:SI 0 "arith_reg_operand" "")
2103         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
2104                    (match_operand:SI 2 "immediate_operand" "")))]
2105   "TARGET_SH1"
2106   "
2107 {
2108   static const char rot_tab[] = {
2109     000, 000, 000, 000, 000, 000, 010, 001,
2110     001, 001, 011, 013, 003, 003, 003, 003,
2111     003, 003, 003, 003, 003, 013, 012, 002,
2112     002, 002, 010, 000, 000, 000, 000, 000,
2113   };
2114
2115   int count, choice;
2116
2117   if (GET_CODE (operands[2]) != CONST_INT)
2118     FAIL;
2119   count = INTVAL (operands[2]);
2120   choice = rot_tab[count];
2121   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
2122     FAIL;
2123   choice &= 7;
2124   switch (choice)
2125     {
2126     case 0:
2127       emit_move_insn (operands[0], operands[1]);
2128       count -= (count & 16) * 2;
2129       break;
2130     case 3:
2131      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
2132      count -= 16;
2133      break;
2134     case 1:
2135     case 2:
2136       {
2137         rtx parts[2];
2138         parts[0] = gen_reg_rtx (SImode);
2139         parts[1] = gen_reg_rtx (SImode);
2140         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
2141         emit_move_insn (parts[choice-1], operands[1]);
2142         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
2143         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
2144         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
2145         count = (count & ~16) - 8;
2146       }
2147     }
2148
2149   for (; count > 0; count--)
2150     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
2151   for (; count < 0; count++)
2152     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
2153
2154   DONE;
2155 }")
2156
2157 (define_insn "*rotlhi3_8"
2158   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2159         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
2160                    (const_int 8)))]
2161   "TARGET_SH1"
2162   "swap.b       %1,%0"
2163   [(set_attr "type" "arith")])
2164
2165 (define_expand "rotlhi3"
2166   [(set (match_operand:HI 0 "arith_reg_operand" "")
2167         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
2168                    (match_operand:HI 2 "immediate_operand" "")))]
2169   "TARGET_SH1"
2170   "
2171 {
2172   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
2173     FAIL;
2174 }")
2175
2176 ;;
2177 ;; shift left
2178
2179 (define_insn "ashlsi3_sh2a"
2180   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2181         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
2182                    (match_operand:SI 2 "arith_reg_operand" "r")))]
2183   "TARGET_SH2A"
2184   "shad %2,%0"
2185   [(set_attr "type" "arith")
2186    (set_attr "length" "4")])
2187
2188 ;; This pattern is used by init_expmed for computing the costs of shift
2189 ;; insns.
2190
2191 (define_insn_and_split "ashlsi3_std"
2192   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r,r,r")
2193         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
2194                    (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
2195    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
2196   "TARGET_SH3
2197    || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
2198        && CONST_OK_FOR_P27 (INTVAL (operands[2])))"
2199   "@
2200    shld %2,%0
2201    add  %0,%0
2202    shll%O2      %0
2203    #"
2204   "TARGET_SH3
2205    && reload_completed
2206    && GET_CODE (operands[2]) == CONST_INT
2207    && ! CONST_OK_FOR_P27 (INTVAL (operands[2]))"
2208   [(set (match_dup 3) (match_dup 2))
2209    (parallel
2210     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
2211      (clobber (match_dup 4))])]
2212   "operands[4] = gen_rtx_SCRATCH (SImode);"
2213   [(set_attr "length" "*,*,*,4")
2214    (set_attr "type" "dyn_shift,arith,arith,arith")])
2215
2216 (define_insn "ashlhi3_k"
2217   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
2218         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
2219                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
2220   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))"
2221   "@
2222         add     %0,%0
2223         shll%O2 %0"
2224   [(set_attr "type" "arith")])
2225
2226 (define_insn "ashlsi3_n"
2227   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2228         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
2229                    (match_operand:SI 2 "const_int_operand" "n")))
2230    (clobber (reg:SI T_REG))]
2231   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2232   "#"
2233   [(set (attr "length")
2234         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2235                (const_string "2")
2236                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2237                (const_string "4")
2238                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2239                (const_string "6")]
2240               (const_string "8")))
2241    (set_attr "type" "arith")])
2242
2243 (define_split
2244   [(set (match_operand:SI 0 "arith_reg_operand" "")
2245         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2246                    (match_operand:SI 2 "const_int_operand" "")))
2247    (clobber (reg:SI T_REG))]
2248   "TARGET_SH1 && reload_completed"
2249   [(use (reg:SI R0_REG))]
2250   "
2251 {
2252   gen_shifty_op (ASHIFT, operands);
2253   DONE;
2254 }")
2255
2256 (define_insn "ashlsi3_media"
2257   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2258         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2259                    (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2260   "TARGET_SHMEDIA"
2261   "@
2262         shlld.l %1, %2, %0
2263         shlli.l %1, %2, %0"
2264   [(set_attr "type" "arith_media")])
2265
2266 (define_expand "ashlsi3"
2267   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2268                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2269                               (match_operand:SI 2 "nonmemory_operand" "")))
2270               (clobber (reg:SI T_REG))])]
2271   ""
2272   "
2273 {
2274   if (TARGET_SHMEDIA)
2275     {
2276       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
2277       DONE;
2278     }
2279   if (GET_CODE (operands[2]) == CONST_INT
2280       && sh_dynamicalize_shift_p (operands[2]))
2281     operands[2] = force_reg (SImode, operands[2]);
2282   if (TARGET_SH3)
2283     {
2284       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
2285       DONE;
2286     }
2287   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2288     FAIL;
2289 }")
2290
2291 (define_insn "ashlhi3"
2292   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2293         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
2294                    (match_operand:HI 2 "const_int_operand" "n")))
2295    (clobber (reg:SI T_REG))]
2296   "TARGET_SH1"
2297   "#"
2298   [(set (attr "length")
2299         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2300                (const_string "2")
2301                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2302                (const_string "4")]
2303               (const_string "6")))
2304    (set_attr "type" "arith")])
2305
2306 (define_split
2307   [(set (match_operand:HI 0 "arith_reg_operand" "")
2308         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
2309                    (match_operand:HI 2 "const_int_operand" "")))
2310    (clobber (reg:SI T_REG))]
2311   "TARGET_SH1 && reload_completed"
2312   [(use (reg:SI R0_REG))]
2313   "
2314 {
2315   gen_shifty_hi_op (ASHIFT, operands);
2316   DONE;
2317 }")
2318
2319 ;
2320 ; arithmetic shift right
2321 ;
2322
2323 (define_insn "ashrsi3_sh2a"
2324   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2325         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2326                    (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2327   "TARGET_SH2A"
2328   "shad %2,%0"
2329   [(set_attr "type" "dyn_shift")
2330    (set_attr "length" "4")])
2331
2332 (define_insn "ashrsi3_k"
2333   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2334         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2335                      (match_operand:SI 2 "const_int_operand" "M")))
2336    (clobber (reg:SI T_REG))]
2337   "TARGET_SH1 && INTVAL (operands[2]) == 1"
2338   "shar %0"
2339   [(set_attr "type" "arith")])
2340
2341 ;; We can't do HImode right shifts correctly unless we start out with an
2342 ;; explicit zero / sign extension; doing that would result in worse overall
2343 ;; code, so just let the machine independent code widen the mode.
2344 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
2345
2346
2347 ;; ??? This should be a define expand.
2348
2349 (define_insn "ashrsi2_16"
2350   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2351         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
2352                      (const_int 16)))]
2353   "TARGET_SH1"
2354   "#"
2355   [(set_attr "length" "4")])
2356
2357 (define_split
2358   [(set (match_operand:SI 0 "arith_reg_operand" "")
2359         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2360                      (const_int 16)))]
2361   "TARGET_SH1"
2362   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
2363    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2364   "operands[2] = gen_lowpart (HImode, operands[0]);")
2365
2366 ;; ??? This should be a define expand.
2367
2368 (define_insn "ashrsi2_31"
2369   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2370         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2371                      (const_int 31)))
2372    (clobber (reg:SI T_REG))]
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 31)))
2381    (clobber (reg:SI T_REG))]
2382   "TARGET_SH1"
2383   [(const_int 0)]
2384   "
2385 {
2386   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
2387   emit_insn (gen_subc1 (operands[0], operands[0], operands[0]));
2388   DONE;
2389 }")
2390
2391 (define_insn "ashlsi_c"
2392   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2393         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
2394    (set (reg:SI T_REG)
2395         (lt:SI (match_dup 1) (const_int 0)))]
2396   "TARGET_SH1"
2397   "shll %0"
2398   [(set_attr "type" "arith")])
2399
2400 (define_insn "ashrsi3_d"
2401   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2402         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2403                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2404   "TARGET_SH3"
2405   "shad %2,%0"
2406   [(set_attr "type" "dyn_shift")])
2407
2408 (define_insn "ashrsi3_n"
2409   [(set (reg:SI R4_REG)
2410         (ashiftrt:SI (reg:SI R4_REG)
2411                      (match_operand:SI 0 "const_int_operand" "i")))
2412    (clobber (reg:SI T_REG))
2413    (clobber (reg:SI PR_REG))
2414    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2415   "TARGET_SH1"
2416   "jsr  @%1%#"
2417   [(set_attr "type" "sfunc")
2418    (set_attr "needs_delay_slot" "yes")])
2419
2420 (define_insn "ashrsi3_media"
2421   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2422         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2423                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2424   "TARGET_SHMEDIA"
2425   "@
2426         shard.l %1, %2, %0
2427         shari.l %1, %2, %0"
2428   [(set_attr "type" "arith_media")])
2429
2430 (define_expand "ashrsi3"
2431   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2432                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2433                                 (match_operand:SI 2 "nonmemory_operand" "")))
2434               (clobber (reg:SI T_REG))])]
2435   ""
2436   "
2437 {
2438   if (TARGET_SHMEDIA)
2439     {
2440       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
2441       DONE;
2442     }
2443   if (expand_ashiftrt (operands))
2444     DONE;
2445   else
2446     FAIL;
2447 }")
2448
2449 ;; logical shift right
2450
2451 (define_insn "lshrsi3_sh2a"
2452   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2453         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2454                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2455   "TARGET_SH2A"
2456   "shld %2,%0"
2457   [(set_attr "type" "dyn_shift")
2458    (set_attr "length" "4")])
2459
2460 (define_insn "lshrsi3_d"
2461   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2462         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2463                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2464   "TARGET_SH3"
2465   "shld %2,%0"
2466   [(set_attr "type" "dyn_shift")])
2467
2468 ;;  Only the single bit shift clobbers the T bit.
2469
2470 (define_insn "lshrsi3_m"
2471   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2472         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2473                      (match_operand:SI 2 "const_int_operand" "M")))
2474    (clobber (reg:SI T_REG))]
2475   "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
2476   "shlr %0"
2477   [(set_attr "type" "arith")])
2478
2479 (define_insn "lshrsi3_k"
2480   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2481         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2482                      (match_operand:SI 2 "const_int_operand" "P27")))]
2483   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))
2484    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
2485   "shlr%O2      %0"
2486   [(set_attr "type" "arith")])
2487
2488 (define_insn "lshrsi3_n"
2489   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2490         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2491                      (match_operand:SI 2 "const_int_operand" "n")))
2492    (clobber (reg:SI T_REG))]
2493   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2494   "#"
2495   [(set (attr "length")
2496         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2497                (const_string "2")
2498                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2499                (const_string "4")
2500                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2501                (const_string "6")]
2502               (const_string "8")))
2503    (set_attr "type" "arith")])
2504
2505 (define_split
2506   [(set (match_operand:SI 0 "arith_reg_operand" "")
2507         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2508                      (match_operand:SI 2 "const_int_operand" "")))
2509    (clobber (reg:SI T_REG))]
2510   "TARGET_SH1 && reload_completed"
2511   [(use (reg:SI R0_REG))]
2512   "
2513 {
2514   gen_shifty_op (LSHIFTRT, operands);
2515   DONE;
2516 }")
2517
2518 (define_insn "lshrsi3_media"
2519   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2520         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2521                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2522   "TARGET_SHMEDIA"
2523   "@
2524         shlrd.l %1, %2, %0
2525         shlri.l %1, %2, %0"
2526   [(set_attr "type" "arith_media")])
2527
2528 (define_expand "lshrsi3"
2529   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2530                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2531                                 (match_operand:SI 2 "nonmemory_operand" "")))
2532               (clobber (reg:SI T_REG))])]
2533   ""
2534   "
2535 {
2536   if (TARGET_SHMEDIA)
2537     {
2538       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
2539       DONE;
2540     }
2541   if (GET_CODE (operands[2]) == CONST_INT
2542       && sh_dynamicalize_shift_p (operands[2]))
2543     operands[2] = force_reg (SImode, operands[2]);
2544   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
2545     {
2546       rtx count = copy_to_mode_reg (SImode, operands[2]);
2547       emit_insn (gen_negsi2 (count, count));
2548       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
2549       DONE;
2550     }
2551   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2552     FAIL;
2553 }")
2554
2555 ;; ??? This should be a define expand.
2556
2557 (define_insn "ashldi3_k"
2558   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2559         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
2560                    (const_int 1)))
2561    (clobber (reg:SI T_REG))]
2562   "TARGET_SH1"
2563   "shll %R0\;rotcl      %S0"
2564   [(set_attr "length" "4")
2565    (set_attr "type" "arith")])
2566
2567 (define_insn "ashldi3_media"
2568   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2569         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2570                    (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2571   "TARGET_SHMEDIA"
2572   "@
2573         shlld   %1, %2, %0
2574         shlli   %1, %2, %0"
2575   [(set_attr "type" "arith_media")])
2576
2577 (define_expand "ashldi3"
2578   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2579                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
2580                               (match_operand:DI 2 "immediate_operand" "")))
2581               (clobber (reg:SI T_REG))])]
2582   ""
2583   "
2584 {
2585   if (TARGET_SHMEDIA)
2586     {
2587       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
2588       DONE;
2589     }
2590   if (GET_CODE (operands[2]) != CONST_INT
2591       || INTVAL (operands[2]) != 1)
2592     FAIL;
2593 }")
2594
2595 ;; ??? This should be a define expand.
2596
2597 (define_insn "lshrdi3_k"
2598   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2599         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2600                      (const_int 1)))
2601    (clobber (reg:SI T_REG))]
2602   "TARGET_SH1"
2603   "shlr %S0\;rotcr      %R0"
2604   [(set_attr "length" "4")
2605    (set_attr "type" "arith")])
2606
2607 (define_insn "lshrdi3_media"
2608   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2609         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2610                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2611   "TARGET_SHMEDIA"
2612   "@
2613         shlrd   %1, %2, %0
2614         shlri   %1, %2, %0"
2615   [(set_attr "type" "arith_media")])
2616
2617 (define_expand "lshrdi3"
2618   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2619                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2620                                (match_operand:DI 2 "immediate_operand" "")))
2621              (clobber (reg:SI T_REG))])]
2622   ""
2623   "
2624 {
2625   if (TARGET_SHMEDIA)
2626     {
2627       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
2628       DONE;
2629     }
2630   if (GET_CODE (operands[2]) != CONST_INT
2631       || INTVAL (operands[2]) != 1)
2632     FAIL;
2633 }")
2634
2635 ;; ??? This should be a define expand.
2636
2637 (define_insn "ashrdi3_k"
2638   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2639         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2640                      (const_int 1)))
2641    (clobber (reg:SI T_REG))]
2642   "TARGET_SH1"
2643   "shar %S0\;rotcr      %R0"
2644   [(set_attr "length" "4")
2645    (set_attr "type" "arith")])
2646
2647 (define_insn "ashrdi3_media"
2648   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2649         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2650                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2651   "TARGET_SHMEDIA"
2652   "@
2653         shard   %1, %2, %0
2654         shari   %1, %2, %0"
2655   [(set_attr "type" "arith_media")])
2656
2657 (define_expand "ashrdi3"
2658   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2659                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2660                                 (match_operand:DI 2 "immediate_operand" "")))
2661               (clobber (reg:SI T_REG))])]
2662   ""
2663   "
2664 {
2665   if (TARGET_SHMEDIA)
2666     {
2667       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
2668       DONE;
2669     }
2670   if (GET_CODE (operands[2]) != CONST_INT
2671       || INTVAL (operands[2]) != 1)
2672     FAIL;
2673 }")
2674
2675 ;; combined left/right shift
2676
2677 (define_split
2678   [(set (match_operand:SI 0 "register_operand" "")
2679         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2680                            (match_operand:SI 2 "const_int_operand" ""))
2681                 (match_operand:SI 3 "const_int_operand" "")))]
2682   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
2683   [(use (reg:SI R0_REG))]
2684   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2685    DONE;")
2686
2687 (define_split
2688   [(set (match_operand:SI 0 "register_operand" "")
2689         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2690                            (match_operand:SI 2 "const_int_operand" ""))
2691                 (match_operand:SI 3 "const_int_operand" "")))
2692    (clobber (reg:SI T_REG))]
2693   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
2694   [(use (reg:SI R0_REG))]
2695   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2696    DONE;")
2697
2698 (define_insn ""
2699   [(set (match_operand:SI 0 "register_operand" "=r")
2700         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2701                            (match_operand:SI 2 "const_int_operand" "n"))
2702                 (match_operand:SI 3 "const_int_operand" "n")))
2703    (clobber (reg:SI T_REG))]
2704   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
2705  "#"
2706   [(set (attr "length")
2707         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2708                (const_string "4")
2709                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2710                (const_string "6")
2711                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2712                (const_string "8")
2713                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
2714                (const_string "10")
2715                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
2716                (const_string "12")
2717                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
2718                (const_string "14")
2719                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
2720                (const_string "16")]
2721               (const_string "18")))
2722    (set_attr "type" "arith")])
2723
2724 (define_insn ""
2725   [(set (match_operand:SI 0 "register_operand" "=z")
2726         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2727                            (match_operand:SI 2 "const_int_operand" "n"))
2728                 (match_operand:SI 3 "const_int_operand" "n")))
2729    (clobber (reg:SI T_REG))]
2730   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
2731  "#"
2732   [(set (attr "length")
2733         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2734                (const_string "4")
2735                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2736                (const_string "6")
2737                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2738                (const_string "8")]
2739               (const_string "10")))
2740    (set_attr "type" "arith")])
2741
2742 ;; shift left / and combination with a scratch register: The combine pass
2743 ;; does not accept the individual instructions, even though they are
2744 ;; cheap.  But it needs a precise description so that it is usable after
2745 ;; reload.
2746 (define_insn "and_shl_scratch"
2747   [(set (match_operand:SI 0 "register_operand" "=r,&r")
2748         (lshiftrt:SI
2749          (ashift:SI
2750           (and:SI
2751            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
2752                         (match_operand:SI 2 "const_int_operand" "N,n"))
2753            (match_operand:SI 3 "" "0,r"))
2754           (match_operand:SI 4 "const_int_operand" "n,n"))
2755          (match_operand:SI 5 "const_int_operand" "n,n")))
2756    (clobber (reg:SI T_REG))]
2757   "TARGET_SH1"
2758   "#"
2759   [(set (attr "length")
2760         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
2761                (const_string "4")
2762                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
2763                (const_string "6")
2764                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
2765                (const_string "8")
2766                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
2767                (const_string "10")]
2768               (const_string "12")))
2769    (set_attr "type" "arith")])
2770
2771 (define_split
2772   [(set (match_operand:SI 0 "register_operand" "")
2773         (lshiftrt:SI
2774          (ashift:SI
2775           (and:SI
2776            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
2777                         (match_operand:SI 2 "const_int_operand" ""))
2778            (match_operand:SI 3 "register_operand" ""))
2779           (match_operand:SI 4 "const_int_operand" ""))
2780          (match_operand:SI 5 "const_int_operand" "")))
2781    (clobber (reg:SI T_REG))]
2782   "TARGET_SH1"
2783   [(use (reg:SI R0_REG))]
2784   "
2785 {
2786   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
2787
2788   if (INTVAL (operands[2]))
2789     {
2790       gen_shifty_op (LSHIFTRT, operands);
2791     }
2792   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
2793   operands[2] = operands[4];
2794   gen_shifty_op (ASHIFT, operands);
2795   if (INTVAL (operands[5]))
2796     {
2797       operands[2] = operands[5];
2798       gen_shifty_op (LSHIFTRT, operands);
2799     }
2800   DONE;
2801 }")
2802
2803 ;; signed left/right shift combination.
2804 (define_split
2805   [(set (match_operand:SI 0 "register_operand" "")
2806         (sign_extract:SI
2807          (ashift:SI (match_operand:SI 1 "register_operand" "")
2808                     (match_operand:SI 2 "const_int_operand" ""))
2809          (match_operand:SI 3 "const_int_operand" "")
2810          (const_int 0)))
2811    (clobber (reg:SI T_REG))]
2812   "TARGET_SH1"
2813   [(use (reg:SI R0_REG))]
2814   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
2815    DONE;")
2816
2817 (define_insn "shl_sext_ext"
2818   [(set (match_operand:SI 0 "register_operand" "=r")
2819         (sign_extract:SI
2820          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2821                     (match_operand:SI 2 "const_int_operand" "n"))
2822          (match_operand:SI 3 "const_int_operand" "n")
2823          (const_int 0)))
2824    (clobber (reg:SI T_REG))]
2825   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
2826   "#"
2827   [(set (attr "length")
2828         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
2829                (const_string "2")
2830                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
2831                (const_string "4")
2832                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2833                (const_string "6")
2834                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2835                (const_string "8")
2836                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2837                (const_string "10")
2838                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2839                (const_string "12")
2840                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
2841                (const_string "14")
2842                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
2843                (const_string "16")]
2844               (const_string "18")))
2845     (set_attr "type" "arith")])
2846
2847 (define_insn "shl_sext_sub"
2848   [(set (match_operand:SI 0 "register_operand" "=z")
2849         (sign_extract:SI
2850          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2851                     (match_operand:SI 2 "const_int_operand" "n"))
2852          (match_operand:SI 3 "const_int_operand" "n")
2853          (const_int 0)))
2854    (clobber (reg:SI T_REG))]
2855   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
2856   "#"
2857   [(set (attr "length")
2858         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2859                (const_string "6")
2860                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2861                (const_string "8")
2862                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2863                (const_string "10")
2864                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2865                (const_string "12")]
2866               (const_string "14")))
2867     (set_attr "type" "arith")])
2868
2869 ;; These patterns are found in expansions of DImode shifts by 16, and
2870 ;; allow the xtrct instruction to be generated from C source.
2871
2872 (define_insn "xtrct_left"
2873   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2874         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
2875                            (const_int 16))
2876                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
2877                              (const_int 16))))]
2878   "TARGET_SH1"
2879   "xtrct        %1,%0"
2880   [(set_attr "type" "arith")])
2881
2882 (define_insn "xtrct_right"
2883   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2884         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2885                              (const_int 16))
2886                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
2887                            (const_int 16))))]
2888   "TARGET_SH1"
2889   "xtrct        %2,%0"
2890   [(set_attr "type" "arith")])
2891
2892 ;; -------------------------------------------------------------------------
2893 ;; Unary arithmetic
2894 ;; -------------------------------------------------------------------------
2895
2896 (define_insn "negc"
2897   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2898         (neg:SI (plus:SI (reg:SI T_REG)
2899                          (match_operand:SI 1 "arith_reg_operand" "r"))))
2900    (set (reg:SI T_REG)
2901         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
2902                (const_int 0)))]
2903   "TARGET_SH1"
2904   "negc %1,%0"
2905   [(set_attr "type" "arith")])
2906
2907 (define_insn "*negdi_media"
2908   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2909         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
2910   "TARGET_SHMEDIA"
2911   "sub  r63, %1, %0"
2912   [(set_attr "type" "arith_media")])
2913
2914 (define_expand "negdi2"
2915   [(set (match_operand:DI 0 "arith_reg_operand" "")
2916         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
2917   ""
2918   "
2919 {
2920   if (TARGET_SH1)
2921     {
2922       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
2923       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
2924
2925       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
2926       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
2927
2928       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
2929       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
2930
2931       emit_insn (gen_clrt ());
2932       emit_insn (gen_negc (low_dst, low_src));
2933       emit_insn (gen_negc (high_dst, high_src));
2934       DONE;
2935     }
2936 }")
2937
2938 (define_insn "negsi2"
2939   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2940         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2941   "TARGET_SH1"
2942   "neg  %1,%0"
2943   [(set_attr "type" "arith")])
2944
2945 (define_insn "one_cmplsi2"
2946   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2947         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2948   "TARGET_SH1"
2949   "not  %1,%0"
2950   [(set_attr "type" "arith")])
2951
2952 (define_expand "one_cmpldi2"
2953   [(set (match_operand:DI 0 "arith_reg_operand" "")
2954         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
2955                 (const_int -1)))]
2956   "TARGET_SHMEDIA" "")
2957 \f
2958 ;; -------------------------------------------------------------------------
2959 ;; Zero extension instructions
2960 ;; -------------------------------------------------------------------------
2961
2962 (define_insn "zero_extendsidi2"
2963   [(set (match_operand:DI 0 "register_operand" "=r")
2964         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
2965   "TARGET_SHMEDIA"
2966   "addz.l       %1, r63, %0"
2967   [(set_attr "type" "arith_media")])
2968
2969 (define_insn "zero_extendhidi2"
2970   [(set (match_operand:DI 0 "register_operand" "=r,r")
2971         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
2972   "TARGET_SHMEDIA"
2973   "@
2974         #
2975         ld%M1.uw        %m1, %0"
2976   [(set_attr "type" "*,load_media")])
2977
2978 (define_split
2979   [(set (match_operand:DI 0 "register_operand" "")
2980         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
2981   "TARGET_SHMEDIA && reload_completed"
2982   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
2983    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
2984   "
2985 {
2986   if (GET_CODE (operands[1]) == TRUNCATE)
2987     operands[1] = XEXP (operands[1], 0);
2988 }")
2989
2990 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
2991 ;; reload the entire truncate expression.
2992 (define_insn_and_split "*loaddi_trunc"
2993   [(set (match_operand 0 "int_gpr_dest" "=r")
2994         (truncate (match_operand:DI 1 "memory_operand" "m")))]
2995   "TARGET_SHMEDIA && reload_completed"
2996   "#"
2997   "TARGET_SHMEDIA && reload_completed"
2998   [(set (match_dup 0) (match_dup 1))]
2999   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
3000
3001 (define_insn "zero_extendqidi2"
3002   [(set (match_operand:DI 0 "register_operand" "=r,r")
3003         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3004   "TARGET_SHMEDIA"
3005   "@
3006         andi    %1, 255, %0
3007         ld%M1.ub        %m1, %0"
3008   [(set_attr "type" "arith_media,load_media")])
3009
3010 (define_expand "zero_extendhisi2"
3011   [(set (match_operand:SI 0 "arith_reg_operand" "")
3012         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
3013   ""
3014   "
3015 {
3016   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
3017     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3018 }")
3019
3020 (define_insn "*zero_extendhisi2_compact"
3021   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3022         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
3023   "TARGET_SH1"
3024   "extu.w       %1,%0"
3025   [(set_attr "type" "arith")])
3026
3027 (define_insn "*zero_extendhisi2_media"
3028   [(set (match_operand:SI 0 "register_operand" "=r,r")
3029         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3030   "TARGET_SHMEDIA"
3031   "@
3032         #
3033         ld%M1.uw        %m1, %0"
3034   [(set_attr "type" "arith_media,load_media")])
3035
3036 (define_split
3037   [(set (match_operand:SI 0 "register_operand" "")
3038         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
3039   "TARGET_SHMEDIA && reload_completed"
3040   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16)))
3041    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
3042   "
3043 {
3044   if (GET_CODE (operands[1]) == TRUNCATE)
3045     operands[1] = XEXP (operands[1], 0);
3046 }")
3047
3048 (define_expand "zero_extendqisi2"
3049   [(set (match_operand:SI 0 "arith_reg_operand" "")
3050         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
3051   ""
3052   "
3053 {
3054   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
3055     operands[1] = copy_to_mode_reg (QImode, operands[1]);
3056 }")
3057
3058 (define_insn "*zero_extendqisi2_compact"
3059   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3060         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
3061   "TARGET_SH1"
3062   "extu.b       %1,%0"
3063   [(set_attr "type" "arith")])
3064
3065 (define_insn "*zero_extendqisi2_media"
3066   [(set (match_operand:SI 0 "register_operand" "=r,r")
3067         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3068   "TARGET_SHMEDIA"
3069   "@
3070         andi    %1, 255, %0
3071         ld%M1.ub        %m1, %0"
3072   [(set_attr "type" "arith_media,load_media")])
3073
3074 (define_insn "zero_extendqihi2"
3075   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
3076         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
3077   "TARGET_SH1"
3078   "extu.b       %1,%0"
3079   [(set_attr "type" "arith")])
3080
3081 ;; -------------------------------------------------------------------------
3082 ;; Sign extension instructions
3083 ;; -------------------------------------------------------------------------
3084
3085 ;; ??? This should be a define expand.
3086 ;; ??? Or perhaps it should be dropped?
3087
3088 ;; convert_move generates good code for SH[1-4].
3089 (define_insn "extendsidi2"
3090   [(set (match_operand:DI 0 "register_operand" "=r,r")
3091         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
3092   "TARGET_SHMEDIA"
3093   "@
3094         add.l   %1, r63, %0
3095         ld%M1.l %m1, %0"
3096   [(set_attr "type" "arith_media,load_media")])
3097
3098 (define_insn "extendhidi2"
3099   [(set (match_operand:DI 0 "register_operand" "=r,r")
3100         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3101   "TARGET_SHMEDIA"
3102   "@
3103         #
3104         ld%M1.w %m1, %0"
3105   [(set_attr "type" "*,load_media")])
3106
3107 (define_split
3108   [(set (match_operand:DI 0 "register_operand" "")
3109         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
3110   "TARGET_SHMEDIA && reload_completed"
3111   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
3112    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
3113   "
3114 {
3115   if (GET_CODE (operands[1]) == TRUNCATE)
3116     operands[1] = XEXP (operands[1], 0);
3117 }")
3118
3119 (define_insn "extendqidi2"
3120   [(set (match_operand:DI 0 "register_operand" "=r,r")
3121         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3122   "TARGET_SHMEDIA"
3123   "@
3124         #
3125         ld%M1.b %m1, %0"
3126   [(set_attr "type" "*,load_media")])
3127
3128 (define_split
3129   [(set (match_operand:DI 0 "register_operand" "")
3130         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
3131   "TARGET_SHMEDIA && reload_completed"
3132   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
3133    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
3134   "
3135 {
3136   if (GET_CODE (operands[1]) == TRUNCATE)
3137     operands[1] = XEXP (operands[1], 0);
3138 }")
3139
3140 (define_expand "extendhisi2"
3141   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3142         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3143   ""
3144   "")
3145
3146 (define_insn "*extendhisi2_compact"
3147   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3148         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
3149   "TARGET_SH1"
3150   "@
3151         exts.w  %1,%0
3152         mov.w   %1,%0"
3153   [(set_attr "type" "arith,load")])
3154
3155 (define_insn "*extendhisi2_media"
3156   [(set (match_operand:SI 0 "register_operand" "=r,r")
3157         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3158   "TARGET_SHMEDIA"
3159   "@
3160         #
3161         ld%M1.w %m1, %0"
3162   [(set_attr "type" "arith_media,load_media")])
3163
3164 (define_split
3165   [(set (match_operand:SI 0 "register_operand" "")
3166         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
3167   "TARGET_SHMEDIA && reload_completed"
3168   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16)))
3169    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
3170   "
3171 {
3172   if (GET_CODE (operands[1]) == TRUNCATE)
3173     operands[1] = XEXP (operands[1], 0);
3174 }")
3175
3176 (define_expand "extendqisi2"
3177   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3178         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3179   ""
3180   "")
3181
3182 (define_insn "*extendqisi2_compact"
3183   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3184         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
3185   "TARGET_SH1"
3186   "@
3187         exts.b  %1,%0
3188         mov.b   %1,%0"
3189   [(set_attr "type" "arith,load")])
3190
3191 (define_insn "*extendqisi2_media"
3192   [(set (match_operand:SI 0 "register_operand" "=r,r")
3193         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3194   "TARGET_SHMEDIA"
3195   "@
3196         #
3197         ld%M1.b %m1, %0"
3198   [(set_attr "type" "arith_media,load_media")])
3199
3200 (define_split
3201   [(set (match_operand:SI 0 "register_operand" "")
3202         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
3203   "TARGET_SHMEDIA && reload_completed"
3204   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 24)))
3205    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
3206    "
3207 {
3208   if (GET_CODE (operands[1]) == TRUNCATE)
3209     operands[1] = XEXP (operands[1], 0);
3210 }")
3211
3212 (define_insn "extendqihi2"
3213   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
3214         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
3215   "TARGET_SH1"
3216   "@
3217         exts.b  %1,%0
3218         mov.b   %1,%0"
3219   [(set_attr "type" "arith,load")])
3220
3221 /* It would seem useful to combine the truncXi patterns into the movXi
3222    patterns, but unary operators are ignored when matching constraints,
3223    so we need separate patterns.  */
3224 (define_insn "truncdisi2"
3225   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
3226         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
3227   "TARGET_SHMEDIA"
3228   "@
3229         add.l   %1, r63, %0
3230         st%M0.l %m0, %1
3231         fst%M0.s        %m0, %T1
3232         fmov.ls %1, %0
3233         fmov.sl %T1, %0
3234         fmov.s  %T1, %0"
3235   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")])
3236
3237
3238 (define_insn "truncdihi2"
3239   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
3240         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
3241   "TARGET_SHMEDIA"
3242   "@
3243         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
3244         st%M0.w %m0, %1"
3245   [(set_attr "type"   "arith_media,store_media")
3246    (set_attr "length" "8,4")])
3247
3248 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
3249 ; Because we use zero extension, we can't provide signed QImode compares
3250 ; using a simple compare or conditional banch insn.
3251 (define_insn "truncdiqi2"
3252   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
3253         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
3254   "TARGET_SHMEDIA"
3255   "@
3256         andi    %1, 255, %0
3257         st%M0.b %m0, %1"
3258   [(set_attr "type"   "arith_media,store")])
3259
3260 ;; -------------------------------------------------------------------------
3261 ;; Move instructions
3262 ;; -------------------------------------------------------------------------
3263
3264 ;; define push and pop so it is easy for sh.c
3265 ;; We can't use push and pop on SHcompact because the stack must always
3266 ;; be 8-byte aligned.
3267
3268 (define_expand "push"
3269   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
3270         (match_operand:SI 0 "register_operand" "r,l,x"))]
3271   "TARGET_SH1 && ! TARGET_SH5"
3272   "")
3273
3274 (define_expand "pop"
3275   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
3276         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
3277   "TARGET_SH1 && ! TARGET_SH5"
3278   "")
3279
3280 (define_expand "push_e"
3281   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
3282                    (match_operand:SF 0 "" ""))
3283               (use (reg:PSI FPSCR_REG))
3284               (clobber (scratch:SI))])]
3285   "TARGET_SH1 && ! TARGET_SH5"
3286   "")
3287
3288 (define_insn "push_fpul"
3289   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
3290   "TARGET_SH2E && ! TARGET_SH5"
3291   "sts.l        fpul,@-r15"
3292   [(set_attr "type" "store")
3293    (set_attr "late_fp_use" "yes")
3294    (set_attr "hit_stack" "yes")])
3295
3296 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
3297 ;; so use that.
3298 (define_expand "push_4"
3299   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
3300                    (match_operand:DF 0 "" ""))
3301               (use (reg:PSI FPSCR_REG))
3302               (clobber (scratch:SI))])]
3303   "TARGET_SH1 && ! TARGET_SH5"
3304   "")
3305
3306 (define_expand "pop_e"
3307   [(parallel [(set (match_operand:SF 0 "" "")
3308               (mem:SF (post_inc:SI (reg:SI SP_REG))))
3309               (use (reg:PSI FPSCR_REG))
3310               (clobber (scratch:SI))])]
3311   "TARGET_SH1 && ! TARGET_SH5"
3312   "")
3313
3314 (define_insn "pop_fpul"
3315   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
3316   "TARGET_SH2E && ! TARGET_SH5"
3317   "lds.l        @r15+,fpul"
3318   [(set_attr "type" "load")
3319    (set_attr "hit_stack" "yes")])
3320
3321 (define_expand "pop_4"
3322   [(parallel [(set (match_operand:DF 0 "" "")
3323                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
3324               (use (reg:PSI FPSCR_REG))
3325               (clobber (scratch:SI))])]
3326   "TARGET_SH1 && ! TARGET_SH5"
3327   "")
3328
3329 (define_expand "push_fpscr"
3330   [(const_int 0)]
3331   "TARGET_SH2E"
3332   "
3333 {
3334   rtx insn = emit_insn (gen_fpu_switch (gen_rtx_MEM (PSImode,
3335                                                  gen_rtx_PRE_DEC (Pmode,
3336                                                           stack_pointer_rtx)),
3337                                         get_fpscr_rtx ()));
3338   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
3339   DONE;
3340 }")
3341
3342 (define_expand "pop_fpscr"
3343   [(const_int 0)]
3344   "TARGET_SH2E"
3345   "
3346 {
3347   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
3348                                         gen_rtx_MEM (PSImode,
3349                                                  gen_rtx_POST_INC (Pmode,
3350                                                           stack_pointer_rtx))));
3351   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
3352   DONE;
3353 }")
3354
3355 ;; These two patterns can happen as the result of optimization, when
3356 ;; comparisons get simplified to a move of zero or 1 into the T reg.
3357 ;; They don't disappear completely, because the T reg is a fixed hard reg.
3358
3359 (define_insn "clrt"
3360   [(set (reg:SI T_REG) (const_int 0))]
3361   "TARGET_SH1"
3362   "clrt")
3363
3364 (define_insn "sett"
3365   [(set (reg:SI T_REG) (const_int 1))]
3366   "TARGET_SH1"
3367   "sett")
3368
3369 ;; t/r must come after r/r, lest reload will try to reload stuff like
3370 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
3371 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
3372 (define_insn "movsi_i"
3373   [(set (match_operand:SI 0 "general_movdst_operand"
3374             "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
3375         (match_operand:SI 1 "general_movsrc_operand"
3376          "Q,rI08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
3377   "TARGET_SH1
3378    && ! TARGET_SH2E
3379    && ! TARGET_SH2A
3380    && (register_operand (operands[0], SImode)
3381        || register_operand (operands[1], SImode))"
3382   "@
3383         mov.l   %1,%0
3384         mov     %1,%0
3385         cmp/pl  %1
3386         mov.l   %1,%0
3387         sts     %1,%0
3388         sts     %1,%0
3389         movt    %0
3390         mov.l   %1,%0
3391         sts.l   %1,%0
3392         sts.l   %1,%0
3393         lds     %1,%0
3394         lds     %1,%0
3395         lds.l   %1,%0
3396         lds.l   %1,%0
3397         fake    %1,%0"
3398   [(set_attr "type" "pcload_si,move,mt_group,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
3399    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
3400
3401 ;; t/r must come after r/r, lest reload will try to reload stuff like
3402 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
3403 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
3404 ;; will require a reload.
3405 ;; ??? We can't include f/f because we need the proper FPSCR setting when
3406 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
3407 (define_insn "movsi_ie"
3408   [(set (match_operand:SI 0 "general_movdst_operand"
3409             "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
3410         (match_operand:SI 1 "general_movsrc_operand"
3411          "Q,rI08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
3412   "(TARGET_SH2E || TARGET_SH2A)
3413    && (register_operand (operands[0], SImode)
3414        || register_operand (operands[1], SImode))"
3415   "@
3416         mov.l   %1,%0
3417         mov     %1,%0
3418         movi20  %1,%0
3419         cmp/pl  %1
3420         mov.l   %1,%0
3421         sts     %1,%0
3422         sts     %1,%0
3423         movt    %0
3424         mov.l   %1,%0
3425         sts.l   %1,%0
3426         sts.l   %1,%0
3427         lds     %1,%0
3428         lds     %1,%0
3429         lds.l   %1,%0
3430         lds.l   %1,%0
3431         lds.l   %1,%0
3432         sts.l   %1,%0
3433         fake    %1,%0
3434         lds     %1,%0
3435         sts     %1,%0
3436         fsts    fpul,%0
3437         flds    %1,fpul
3438         fmov    %1,%0
3439         ! move optimized away"
3440   [(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")
3441    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
3442    (set_attr "length" "*,*,4,*,4,*,*,*,4,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
3443
3444 (define_insn "movsi_i_lowpart"
3445   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
3446         (match_operand:SI 1 "general_movsrc_operand" "Q,rI08,mr,x,l,t,r,i"))]
3447    "TARGET_SH1
3448     && (register_operand (operands[0], SImode)
3449         || register_operand (operands[1], SImode))"
3450   "@
3451         mov.l   %1,%0
3452         mov     %1,%0
3453         mov.l   %1,%0
3454         sts     %1,%0
3455         sts     %1,%0
3456         movt    %0
3457         mov.l   %1,%0
3458         fake    %1,%0"
3459   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
3460
3461 (define_insn_and_split "load_ra"
3462   [(set (match_operand:SI 0 "general_movdst_operand" "")
3463         (unspec:SI [(match_operand 1 "register_operand" "")] UNSPEC_RA))]
3464   "TARGET_SH1"
3465   "#"
3466   "&& ! currently_expanding_to_rtl"
3467   [(set (match_dup 0) (match_dup 1))]
3468   "
3469 {
3470   if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
3471     operands[1] = gen_rtx_MEM (SImode, return_address_pointer_rtx);
3472 }")
3473
3474 (define_insn "*movsi_media"
3475   [(set (match_operand:SI 0 "general_movdst_operand"
3476                 "=r,r,r,r,m,f,m,f,r,f,*b,r,b")
3477         (match_operand:SI 1 "general_movsrc_operand"
3478          "r,I16C16,nCpg,m,rZ,m,f,rZ,f,f,r,*b,Csy"))]
3479   "TARGET_SHMEDIA_FPU
3480    && (register_operand (operands[0], SImode)
3481        || sh_register_operand (operands[1], SImode))"
3482   "@
3483         add.l   %1, r63, %0
3484         movi    %1, %0
3485         #
3486         ld%M1.l %m1, %0
3487         st%M0.l %m0, %N1
3488         fld%M1.s        %m1, %0
3489         fst%M0.s        %m0, %1
3490         fmov.ls %N1, %0
3491         fmov.sl %1, %0
3492         fmov.s  %1, %0
3493         ptabs   %1, %0
3494         gettr   %1, %0
3495         pt      %1, %0"
3496   [(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")
3497    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")])
3498
3499 (define_insn "*movsi_media_nofpu"
3500   [(set (match_operand:SI 0 "general_movdst_operand"
3501                 "=r,r,r,r,m,*b,r,b")
3502         (match_operand:SI 1 "general_movsrc_operand"
3503          "r,I16C16,nCpg,m,rZ,r,*b,Csy"))]
3504   "TARGET_SHMEDIA
3505    && (register_operand (operands[0], SImode)
3506        || sh_register_operand (operands[1], SImode))"
3507   "@
3508         add.l   %1, r63, %0
3509         movi    %1, %0
3510         #
3511         ld%M1.l %m1, %0
3512         st%M0.l %m0, %N1
3513         ptabs   %1, %0
3514         gettr   %1, %0
3515         pt      %1, %0"
3516   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3517    (set_attr "length" "4,4,8,4,4,4,4,12")])
3518
3519 (define_split
3520   [(set (match_operand:SI 0 "arith_reg_operand" "")
3521         (match_operand:SI 1 "immediate_operand" ""))]
3522   "TARGET_SHMEDIA && reload_completed
3523    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3524   [(set (subreg:DI (match_dup 0) 0) (match_dup 2))]
3525   "
3526 {
3527   operands[2] = shallow_copy_rtx (operands[1]);
3528   PUT_MODE (operands[2], DImode);
3529 }")
3530
3531 (define_split
3532   [(set (match_operand:SI 0 "register_operand" "")
3533         (match_operand:SI 1 "immediate_operand" ""))]
3534   "TARGET_SHMEDIA && reload_completed
3535    && ((GET_CODE (operands[1]) == CONST_INT
3536         && ! CONST_OK_FOR_I16 (INTVAL (operands[1])))
3537        || GET_CODE (operands[1]) == CONST_DOUBLE)"
3538   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3539
3540 (define_expand "movsi"
3541   [(set (match_operand:SI 0 "general_movdst_operand" "")
3542         (match_operand:SI 1 "general_movsrc_operand" ""))]
3543   ""
3544   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
3545
3546 (define_expand "ic_invalidate_line"
3547   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
3548                                 (match_dup 1)] UNSPEC_ICACHE)
3549               (clobber (scratch:SI))])]
3550   "TARGET_HARD_SH4 || TARGET_SH5"
3551   "
3552 {
3553   if (TARGET_SHMEDIA)
3554     {
3555       emit_insn (gen_ic_invalidate_line_media (operands[0]));
3556       DONE;
3557     }
3558   else if (TARGET_SHCOMPACT)
3559     {
3560       operands[1] = function_symbol (\"__ic_invalidate\");
3561       operands[1] = force_reg (Pmode, operands[1]);
3562       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
3563       DONE;
3564     }
3565   else if (TARGET_SH4A_ARCH)
3566     {
3567       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
3568       DONE;
3569     }
3570   operands[0] = force_reg (Pmode, operands[0]);
3571   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
3572                                                                Pmode)));
3573 }")
3574
3575 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
3576 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
3577 ;; the requirement *1*00 for associative address writes.  The alignment of
3578 ;; %0 implies that its least significant bit is cleared,
3579 ;; thus we clear the V bit of a matching entry if there is one.
3580 (define_insn "ic_invalidate_line_i"
3581   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
3582                      (match_operand:SI 1 "register_operand" "r")]
3583                      UNSPEC_ICACHE)
3584    (clobber (match_scratch:SI 2 "=&r"))]
3585   "TARGET_HARD_SH4"
3586   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
3587   [(set_attr "length" "8")
3588    (set_attr "type" "cwb")])
3589
3590 (define_insn "ic_invalidate_line_sh4a"
3591   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
3592                     UNSPEC_ICACHE)]
3593   "TARGET_SH4A_ARCH"
3594   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
3595   [(set_attr "length" "16")
3596    (set_attr "type" "cwb")])
3597
3598 ;; ??? could make arg 0 an offsettable memory operand to allow to save
3599 ;; an add in the code that calculates the address.
3600 (define_insn "ic_invalidate_line_media"
3601   [(unspec_volatile [(match_operand 0 "register_operand" "r")]
3602                     UNSPEC_ICACHE)]
3603   "TARGET_SHMEDIA"
3604   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
3605   [(set_attr "length" "16")
3606    (set_attr "type" "invalidate_line_media")])
3607
3608 (define_insn "ic_invalidate_line_compact"
3609   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3610                      (match_operand:SI 1 "register_operand" "r")]
3611                     UNSPEC_ICACHE)
3612    (clobber (reg:SI PR_REG))]
3613   "TARGET_SHCOMPACT"
3614   "jsr @%1%#"
3615   [(set_attr "type" "sfunc")
3616    (set_attr "needs_delay_slot" "yes")])
3617
3618 (define_expand "initialize_trampoline"
3619   [(match_operand:SI 0 "" "")
3620    (match_operand:SI 1 "" "")
3621    (match_operand:SI 2 "" "")]
3622   "TARGET_SHCOMPACT"
3623   "
3624 {
3625   rtx sfun, tramp;
3626
3627   tramp = force_reg (Pmode, operands[0]);
3628   sfun = force_reg (Pmode, function_symbol (\"__init_trampoline\"));
3629   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
3630   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
3631
3632   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
3633   DONE;
3634 }")
3635
3636 (define_insn "initialize_trampoline_compact"
3637   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3638                      (match_operand:SI 1 "register_operand" "r")
3639                      (reg:SI R2_REG) (reg:SI R3_REG)]
3640                     UNSPEC_INIT_TRAMP)
3641
3642    (clobber (reg:SI PR_REG))]
3643   "TARGET_SHCOMPACT"
3644   "jsr @%1%#"
3645   [(set_attr "type" "sfunc")
3646    (set_attr "needs_delay_slot" "yes")])
3647
3648 (define_insn "movqi_i"
3649   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
3650         (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
3651   "TARGET_SH1
3652    && (arith_reg_operand (operands[0], QImode)
3653        || arith_reg_operand (operands[1], QImode))"
3654   "@
3655         mov     %1,%0
3656         mov.b   %1,%0
3657         mov.b   %1,%0
3658         movt    %0
3659         sts     %1,%0
3660         lds     %1,%0"
3661  [(set_attr "type" "move,load,store,move,move,move")])
3662
3663 (define_insn "*movqi_media"
3664   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
3665         (match_operand:QI 1 "general_movsrc_operand" "r,I16C16,m,rZ"))]
3666   "TARGET_SHMEDIA
3667    && (arith_reg_operand (operands[0], QImode)
3668        || arith_reg_or_0_operand (operands[1], QImode))"
3669   "@
3670         add.l   %1, r63, %0
3671         movi    %1, %0
3672         ld%M1.ub        %m1, %0
3673         st%M0.b %m0, %N1"
3674   [(set_attr "type" "arith_media,arith_media,load_media,store_media")])
3675
3676 (define_expand "movqi"
3677   [(set (match_operand:QI 0 "general_operand" "")
3678         (match_operand:QI 1 "general_operand"  ""))]
3679   ""
3680   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
3681
3682 (define_expand "reload_inqi"
3683   [(set (match_operand:SI 2 "" "=&r")
3684         (match_operand:QI 1 "inqhi_operand" ""))
3685    (set (match_operand:QI 0 "arith_reg_operand" "=r")
3686         (truncate:QI (match_dup 3)))]
3687   "TARGET_SHMEDIA"
3688   "
3689 {
3690   rtx inner = XEXP (operands[1], 0);
3691   int regno = REGNO (inner);
3692
3693   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3694   operands[1] = gen_rtx_REG (SImode, regno);
3695   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3696 }")
3697
3698 /* When storing r0, we have to avoid reg+reg addressing.  */
3699 (define_insn "movhi_i"
3700   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
3701         (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
3702   "TARGET_SH1
3703    && (arith_reg_operand (operands[0], HImode)
3704        || arith_reg_operand (operands[1], HImode))
3705    && (GET_CODE (operands[0]) != MEM
3706        || GET_CODE (XEXP (operands[0], 0)) != PLUS
3707        || GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != REG
3708        || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
3709   "@
3710         mov.w   %1,%0
3711         mov     %1,%0
3712         mov.w   %1,%0
3713         movt    %0
3714         mov.w   %1,%0
3715         sts     %1,%0
3716         lds     %1,%0
3717         fake    %1,%0"
3718   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
3719
3720 (define_insn "*movhi_media"
3721   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
3722         (match_operand:HI 1 "general_movsrc_operand" "r,I16C16,n,m,rZ"))]
3723   "TARGET_SHMEDIA
3724    && (arith_reg_operand (operands[0], HImode)
3725        || arith_reg_or_0_operand (operands[1], HImode))"
3726   "@
3727         add.l   %1, r63, %0
3728         movi    %1, %0
3729         #
3730         ld%M1.w %m1, %0
3731         st%M0.w %m0, %N1"
3732   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")])
3733
3734 (define_split
3735   [(set (match_operand:HI 0 "register_operand" "")
3736         (match_operand:HI 1 "immediate_operand" ""))]
3737   "TARGET_SHMEDIA && reload_completed
3738    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
3739   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3740
3741 (define_expand "movhi"
3742   [(set (match_operand:HI 0 "general_movdst_operand" "")
3743         (match_operand:HI 1 "general_movsrc_operand"  ""))]
3744   ""
3745   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
3746
3747 (define_expand "reload_inhi"
3748   [(set (match_operand:SI 2 "" "=&r")
3749         (match_operand:HI 1 "inqhi_operand" ""))
3750    (set (match_operand:HI 0 "arith_reg_operand" "=r")
3751         (truncate:HI (match_dup 3)))]
3752   "TARGET_SHMEDIA"
3753   "
3754 {
3755   rtx inner = XEXP (operands[1], 0);
3756   int regno = REGNO (inner);
3757
3758   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3759   operands[1] = gen_rtx_REG (SImode, regno);
3760   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3761 }")
3762
3763 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
3764 ;; compiled with -m2 -ml -O3 -funroll-loops
3765 (define_insn "*movdi_i"
3766   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
3767         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
3768   "TARGET_SH1
3769    && (arith_reg_operand (operands[0], DImode)
3770        || arith_reg_operand (operands[1], DImode))"
3771   "* return output_movedouble (insn, operands, DImode);"
3772   [(set_attr "length" "4")
3773    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
3774
3775 ;; If the output is a register and the input is memory or a register, we have
3776 ;; to be careful and see which word needs to be loaded first.
3777
3778 (define_split
3779   [(set (match_operand:DI 0 "general_movdst_operand" "")
3780         (match_operand:DI 1 "general_movsrc_operand" ""))]
3781   "TARGET_SH1 && reload_completed"
3782   [(set (match_dup 2) (match_dup 3))
3783    (set (match_dup 4) (match_dup 5))]
3784   "
3785 {
3786   int regno;
3787
3788   if ((GET_CODE (operands[0]) == MEM
3789        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
3790       || (GET_CODE (operands[1]) == MEM
3791           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
3792     FAIL;
3793
3794   if (GET_CODE (operands[0]) == REG)
3795     regno = REGNO (operands[0]);
3796   else if (GET_CODE (operands[0]) == SUBREG)
3797     regno = subreg_regno (operands[0]);
3798   else if (GET_CODE (operands[0]) == MEM)
3799     regno = -1;
3800   else
3801     abort ();
3802
3803   if (regno == -1
3804       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
3805     {
3806       operands[2] = operand_subword (operands[0], 0, 0, DImode);
3807       operands[3] = operand_subword (operands[1], 0, 0, DImode);
3808       operands[4] = operand_subword (operands[0], 1, 0, DImode);
3809       operands[5] = operand_subword (operands[1], 1, 0, DImode);
3810     }
3811   else
3812     {
3813       operands[2] = operand_subword (operands[0], 1, 0, DImode);
3814       operands[3] = operand_subword (operands[1], 1, 0, DImode);
3815       operands[4] = operand_subword (operands[0], 0, 0, DImode);
3816       operands[5] = operand_subword (operands[1], 0, 0, DImode);
3817     }
3818
3819   if (operands[2] == 0 || operands[3] == 0
3820       || operands[4] == 0 || operands[5] == 0)
3821     FAIL;
3822 }")
3823
3824 (define_insn "*movdi_media"
3825   [(set (match_operand:DI 0 "general_movdst_operand"
3826                  "=r,r,r,rl,m,f,m,f,r,f,*b,r,b")
3827         (match_operand:DI 1 "general_movsrc_operand"
3828          "r,I16C16,nCpgF,m,rlZ,m,f,rZ,f,f,r,*b,Csy"))]
3829   "TARGET_SHMEDIA_FPU
3830    && (register_operand (operands[0], DImode)
3831        || sh_register_operand (operands[1], DImode))"
3832   "@
3833         add     %1, r63, %0
3834         movi    %1, %0
3835         #
3836         ld%M1.q %m1, %0
3837         st%M0.q %m0, %N1
3838         fld%M1.d        %m1, %0
3839         fst%M0.d        %m0, %1
3840         fmov.qd %N1, %0
3841         fmov.dq %1, %0
3842         fmov.d  %1, %0
3843         ptabs   %1, %0
3844         gettr   %1, %0
3845         pt      %1, %0"
3846   [(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")
3847    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
3848
3849 (define_insn "*movdi_media_nofpu"
3850   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,b")
3851         (match_operand:DI 1 "general_movsrc_operand" "r,I16C16,nCpgF,m,rlZ,r,*b,Csy"))]
3852   "TARGET_SHMEDIA
3853    && (register_operand (operands[0], DImode)
3854        || sh_register_operand (operands[1], DImode))"
3855   "@
3856         add     %1, r63, %0
3857         movi    %1, %0
3858         #
3859         ld%M1.q %m1, %0
3860         st%M0.q %m0, %N1
3861         ptabs   %1, %0
3862         gettr   %1, %0
3863         pt      %1, %0"
3864   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3865    (set_attr "length" "4,4,16,4,4,4,4,*")])
3866
3867 (define_split
3868   [(set (match_operand:DI 0 "arith_reg_operand" "")
3869         (match_operand:DI 1 "immediate_operand" ""))]
3870   "TARGET_SHMEDIA && reload_completed
3871    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3872   [(set (match_dup 0) (match_dup 1))]
3873   "
3874 {
3875   rtx insn;
3876
3877   if (TARGET_SHMEDIA64)
3878     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
3879   else
3880     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
3881
3882   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
3883                                         REG_NOTES (insn));
3884
3885   DONE;
3886 }")
3887
3888 (define_expand "movdi_const"
3889   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3890         (const:DI (sign_extend:DI
3891                    (truncate:HI
3892                     (ashiftrt:DI
3893                      (match_operand:DI 1 "immediate_operand" "s")
3894                      (const_int 48))))))
3895    (set (match_dup 0)
3896         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3897                 (zero_extend:DI
3898                  (truncate:HI
3899                   (const:DI
3900                    (sign_extend:DI
3901                     (truncate:HI
3902                      (ashiftrt:SI
3903                       (match_dup 1)
3904                       (const_int 32)))))))))
3905    (set (match_dup 0)
3906         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3907                 (zero_extend:DI
3908                  (truncate:HI
3909                   (const:DI
3910                    (sign_extend:DI
3911                     (truncate:HI
3912                      (ashiftrt:SI
3913                       (match_dup 1)
3914                       (const_int 16)))))))))
3915    (set (match_dup 0)
3916         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3917                 (zero_extend:DI
3918                  (truncate:HI
3919                   (const:DI
3920                    (sign_extend:DI
3921                     (truncate:HI
3922                      (match_dup 1))))))))]
3923   "TARGET_SHMEDIA64 && reload_completed
3924    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3925   "
3926 {
3927   sh_mark_label (operands[1], 4);
3928 }")
3929
3930 (define_expand "movdi_const_32bit"
3931   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3932         (const:DI (sign_extend:DI
3933                    (truncate:HI
3934                     (ashiftrt:DI
3935                      (match_operand:DI 1 "immediate_operand" "s")
3936                      (const_int 16))))))
3937    (set (match_dup 0)
3938         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3939                 (zero_extend:DI
3940                  (truncate:HI
3941                   (const:DI
3942                    (sign_extend:DI
3943                     (truncate:HI
3944                      (match_dup 1))))))))]
3945   "TARGET_SHMEDIA32 && reload_completed
3946    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3947   "
3948 {
3949   sh_mark_label (operands[1], 2);
3950 }")
3951
3952 (define_expand "movdi_const_16bit"
3953   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3954         (const:DI (sign_extend:DI
3955                    (truncate:HI
3956                     (match_operand:DI 1 "immediate_operand" "s")))))]
3957   "TARGET_SHMEDIA && flag_pic && reload_completed
3958    && GET_CODE (operands[1]) == SYMBOL_REF"
3959   "")
3960
3961 (define_split
3962   [(set (match_operand:DI 0 "arith_reg_operand" "")
3963         (match_operand:DI 1 "immediate_operand" ""))]
3964   "TARGET_SHMEDIA && reload_completed
3965    && GET_CODE (operands[1]) == CONST_INT
3966    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
3967   [(set (match_dup 0) (match_dup 2))
3968    (match_dup 1)]
3969   "
3970 {
3971   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3972   unsigned HOST_WIDE_INT low = val;
3973   unsigned HOST_WIDE_INT high = val;
3974   unsigned HOST_WIDE_INT sign;
3975   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
3976
3977   /* Sign-extend the 16 least-significant bits.  */
3978   low &= 0xffff;
3979   low ^= 0x8000;
3980   low -= 0x8000;
3981
3982   /* Arithmetic shift right the word by 16 bits.  */
3983   high >>= 16;
3984   sign = 1;
3985   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
3986   high ^= sign;
3987   high -= sign;
3988   do
3989     {
3990       /* If we can't generate the constant with a two-insn movi / shori
3991          sequence, try some other strategies.  */
3992       if (! CONST_OK_FOR_I16 (high))
3993         {
3994           /* Try constant load / left shift.  We know VAL != 0.  */
3995           val2 = val ^ (val-1);
3996           if (val2 > 0x1ffff)
3997             {
3998               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
3999
4000               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
4001                   || (! CONST_OK_FOR_I16 (high >> 16)
4002                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
4003                 {
4004                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
4005                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
4006                                                    GEN_INT (trailing_zeroes));
4007                   break;
4008                 }
4009             }
4010           /* Try constant load / right shift.  */
4011           val2 = (val >> 15) + 1;
4012           if (val2 == (val2 & -val2))
4013             {
4014               int shift = 49 - exact_log2 (val2);
4015
4016               val2 = trunc_int_for_mode (val << shift, DImode);
4017               if (CONST_OK_FOR_I16 (val2))
4018                 {
4019                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
4020                                                    GEN_INT (shift));
4021                   break;
4022                 }
4023             }
4024           /* Try mperm.w .  */
4025           val2 = val & 0xffff;
4026           if ((val >> 16 & 0xffff) == val2
4027               && (val >> 32 & 0xffff) == val2
4028               && (val >> 48 & 0xffff) == val2)
4029             {
4030               val2 = (HOST_WIDE_INT) val >> 48;
4031               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
4032               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
4033               break;
4034             }
4035           /* Try movi / mshflo.l  */
4036           val2 = (HOST_WIDE_INT) val >> 32;
4037           if (val2 == ((unsigned HOST_WIDE_INT)
4038                         trunc_int_for_mode (val, SImode)))
4039             {
4040               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4041                                              operands[0]);
4042               break;
4043             }
4044           /* Try movi / mshflo.l w/ r63.  */
4045           val2 = val + ((HOST_WIDE_INT) -1 << 32);
4046           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
4047             {
4048               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4049                                              const0_rtx);
4050               break;
4051             }
4052         }
4053       val2 = high;
4054       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
4055     }
4056   while (0);
4057   operands[2] = GEN_INT (val2);
4058 }")
4059
4060 (define_split
4061   [(set (match_operand:DI 0 "arith_reg_operand" "")
4062         (match_operand:DI 1 "immediate_operand" ""))]
4063   "TARGET_SHMEDIA && reload_completed
4064    && GET_CODE (operands[1]) == CONST_DOUBLE"
4065   [(set (match_dup 0) (match_dup 2))
4066   (set (match_dup 0)
4067        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
4068                (zero_extend:DI (truncate:HI (match_dup 1)))))]
4069   "
4070 {
4071   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
4072   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
4073   unsigned HOST_WIDE_INT val = low;
4074   unsigned HOST_WIDE_INT sign;
4075
4076   /* Sign-extend the 16 least-significant bits.  */
4077   val &= 0xffff;
4078   val ^= 0x8000;
4079   val -= 0x8000;
4080   operands[1] = GEN_INT (val);
4081
4082   /* Arithmetic shift right the double-word by 16 bits.  */
4083   low >>= 16;
4084   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
4085   high >>= 16;
4086   sign = 1;
4087   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
4088   high ^= sign;
4089   high -= sign;
4090
4091   /* This will only be true if high is a sign-extension of low, i.e.,
4092      it must be either 0 or (unsigned)-1, and be zero iff the
4093      most-significant bit of low is set.  */
4094   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
4095     operands[2] = GEN_INT (low);
4096   else
4097     operands[2] = immed_double_const (low, high, DImode);
4098 }")
4099
4100 (define_insn "shori_media"
4101   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
4102         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
4103                            (const_int 16))
4104                 (zero_extend:DI
4105                  (truncate:HI
4106                   (match_operand:DI 2 "immediate_operand" "I16C16,nF")))))]
4107   "TARGET_SHMEDIA"
4108   "@
4109         shori   %u2, %0
4110         #"
4111   [(set_attr "type" "arith_media,*")])
4112
4113 (define_expand "movdi"
4114   [(set (match_operand:DI 0 "general_movdst_operand" "")
4115         (match_operand:DI 1 "general_movsrc_operand" ""))]
4116   ""
4117   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
4118
4119 (define_insn "movdf_media"
4120   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4121         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
4122   "TARGET_SHMEDIA_FPU
4123    && (register_operand (operands[0], DFmode)
4124        || sh_register_operand (operands[1], DFmode))"
4125   "@
4126         fmov.d  %1, %0
4127         fmov.qd %N1, %0
4128         fmov.dq %1, %0
4129         add     %1, r63, %0
4130         #
4131         fld%M1.d        %m1, %0
4132         fst%M0.d        %m0, %1
4133         ld%M1.q %m1, %0
4134         st%M0.q %m0, %N1"
4135   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4136
4137 (define_insn "movdf_media_nofpu"
4138   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4139         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
4140   "TARGET_SHMEDIA
4141    && (register_operand (operands[0], DFmode)
4142        || sh_register_operand (operands[1], DFmode))"
4143   "@
4144         add     %1, r63, %0
4145         #
4146         ld%M1.q %m1, %0
4147         st%M0.q %m0, %N1"
4148   [(set_attr "type" "arith_media,*,load_media,store_media")])
4149
4150 (define_split
4151   [(set (match_operand:DF 0 "arith_reg_operand" "")
4152         (match_operand:DF 1 "immediate_operand" ""))]
4153   "TARGET_SHMEDIA && reload_completed"
4154   [(set (match_dup 3) (match_dup 2))]
4155   "
4156 {
4157   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
4158   long values[2];
4159   REAL_VALUE_TYPE value;
4160
4161   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4162   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
4163
4164   if (HOST_BITS_PER_WIDE_INT >= 64)
4165     operands[2] = immed_double_const ((unsigned long) values[endian]
4166                                       | ((HOST_WIDE_INT) values[1 - endian]
4167                                          << 32), 0, DImode);
4168   else if (HOST_BITS_PER_WIDE_INT == 32)
4169     operands[2] = immed_double_const (values[endian], values[1 - endian],
4170                                       DImode);
4171   else
4172     abort ();
4173
4174   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4175 }")
4176
4177 ;; ??? This should be a define expand.
4178
4179 (define_insn "movdf_k"
4180   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4181         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
4182   "TARGET_SH1
4183    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
4184        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
4185        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4186        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4187    && (arith_reg_operand (operands[0], DFmode)
4188        || arith_reg_operand (operands[1], DFmode))"
4189   "* return output_movedouble (insn, operands, DFmode);"
4190   [(set_attr "length" "4")
4191    (set_attr "type" "move,pcload,load,store")])
4192
4193 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
4194 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
4195 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
4196 ;; the d/m/c/X alternative, which is split later into single-precision
4197 ;; instructions.  And when not optimizing, no splits are done before fixing
4198 ;; up pcloads, so we need usable length information for that.
4199 (define_insn "movdf_i4"
4200   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
4201         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
4202    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
4203    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
4204   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
4205    && (arith_reg_operand (operands[0], DFmode)
4206        || arith_reg_operand (operands[1], DFmode))"
4207   "@
4208         fmov    %1,%0
4209         #
4210         #
4211         fmov.d  %1,%0
4212         fmov.d  %1,%0
4213         #
4214         #
4215         #
4216         #
4217         #"
4218   [(set_attr_alternative "length"
4219      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
4220       (const_int 4)
4221       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4222       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4223       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4224       (const_int 4)
4225       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
4226       ;; We can't use 4-byte push/pop on SHcompact, so we have to
4227       ;; increment or decrement r15 explicitly.
4228       (if_then_else
4229        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4230        (const_int 10) (const_int 8))
4231       (if_then_else
4232        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4233        (const_int 10) (const_int 8))])
4234    (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
4235    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
4236    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4237                                            (const_string "double")
4238                                            (const_string "none")))])
4239
4240 ;; Moving DFmode between fp/general registers through memory
4241 ;; (the top of the stack) is faster than moving through fpul even for
4242 ;; little endian.  Because the type of an instruction is important for its
4243 ;; scheduling,  it is beneficial to split these operations, rather than
4244 ;; emitting them in one single chunk, even if this will expose a stack
4245 ;; use that will prevent scheduling of other stack accesses beyond this
4246 ;; instruction.
4247 (define_split
4248   [(set (match_operand:DF 0 "register_operand" "")
4249         (match_operand:DF 1 "register_operand" ""))
4250    (use (match_operand:PSI 2 "fpscr_operand" ""))
4251    (clobber (match_scratch:SI 3 "=X"))]
4252   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
4253    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
4254   [(const_int 0)]
4255   "
4256 {
4257   rtx insn, tos;
4258
4259   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
4260     {
4261       emit_move_insn (stack_pointer_rtx,
4262                       plus_constant (stack_pointer_rtx, -8));
4263       tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4264     }
4265   else
4266     tos = gen_rtx_MEM (DFmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
4267   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
4268   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
4269     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4270   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4271     tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4272   else
4273     tos = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
4274   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
4275   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4276     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
4277   else
4278     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4279   DONE;
4280 }")
4281
4282 ;; local-alloc sometimes allocates scratch registers even when not required,
4283 ;; so we must be prepared to handle these.
4284
4285 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
4286 (define_split
4287   [(set (match_operand:DF 0 "general_movdst_operand" "")
4288         (match_operand:DF 1 "general_movsrc_operand"  ""))
4289    (use (match_operand:PSI 2 "fpscr_operand" ""))
4290    (clobber (match_scratch:SI 3 ""))]
4291   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
4292    && reload_completed
4293    && true_regnum (operands[0]) < 16
4294    && true_regnum (operands[1]) < 16"
4295   [(set (match_dup 0) (match_dup 1))]
4296   "
4297 {
4298   /* If this was a reg <-> mem operation with base + index reg addressing,
4299      we have to handle this in a special way.  */
4300   rtx mem = operands[0];
4301   int store_p = 1;
4302   if (! memory_operand (mem, DFmode))
4303     {
4304       mem = operands[1];
4305       store_p = 0;
4306     }
4307   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
4308     mem = SUBREG_REG (mem);
4309   if (GET_CODE (mem) == MEM)
4310     {
4311       rtx addr = XEXP (mem, 0);
4312       if (GET_CODE (addr) == PLUS
4313           && GET_CODE (XEXP (addr, 0)) == REG
4314           && GET_CODE (XEXP (addr, 1)) == REG)
4315         {
4316           int offset;
4317           rtx reg0 = gen_rtx_REG (Pmode, 0);
4318           rtx regop = operands[store_p], word0 ,word1;
4319
4320           if (GET_CODE (regop) == SUBREG)
4321             alter_subreg (&regop);
4322           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
4323             offset = 2;
4324           else
4325             offset = 4;
4326           mem = copy_rtx (mem);
4327           PUT_MODE (mem, SImode);
4328           word0 = gen_rtx_SUBREG (SImode, regop, 0);
4329           alter_subreg (&word0);
4330           word1 = gen_rtx_SUBREG (SImode, regop, 4);
4331           alter_subreg (&word1);
4332           if (store_p || ! refers_to_regno_p (REGNO (word0),
4333                                               REGNO (word0) + 1, addr, 0))
4334             {
4335               emit_insn (store_p
4336                          ? gen_movsi_ie (mem, word0)
4337                          : gen_movsi_ie (word0, mem));
4338               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4339               mem = copy_rtx (mem);
4340               emit_insn (store_p
4341                          ? gen_movsi_ie (mem, word1)
4342                          : gen_movsi_ie (word1, mem));
4343               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4344             }
4345           else
4346             {
4347               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4348               emit_insn (gen_movsi_ie (word1, mem));
4349               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4350               mem = copy_rtx (mem);
4351               emit_insn (gen_movsi_ie (word0, mem));
4352             }
4353           DONE;
4354         }
4355     }
4356 }")
4357
4358 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
4359 (define_split
4360   [(set (match_operand:DF 0 "register_operand" "")
4361         (match_operand:DF 1 "memory_operand"  ""))
4362    (use (match_operand:PSI 2 "fpscr_operand" ""))
4363    (clobber (reg:SI R0_REG))]
4364   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
4365   [(parallel [(set (match_dup 0) (match_dup 1))
4366               (use (match_dup 2))
4367               (clobber (scratch:SI))])]
4368   "")
4369
4370 (define_expand "reload_indf"
4371   [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
4372                    (match_operand:DF 1 "immediate_operand" "FQ"))
4373               (use (reg:PSI FPSCR_REG))
4374               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4375   "TARGET_SH1"
4376   "")
4377
4378 (define_expand "reload_outdf"
4379   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
4380                    (match_operand:DF 1 "register_operand" "af,r"))
4381               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
4382   "TARGET_SH1"
4383   "")
4384
4385 ;; Simplify no-op moves.
4386 (define_split
4387   [(set (match_operand:SF 0 "register_operand" "")
4388         (match_operand:SF 1 "register_operand" ""))
4389    (use (match_operand:PSI 2 "fpscr_operand" ""))
4390    (clobber (match_scratch:SI 3 ""))]
4391   "TARGET_SH2E && reload_completed
4392    && true_regnum (operands[0]) == true_regnum (operands[1])"
4393   [(set (match_dup 0) (match_dup 0))]
4394   "")
4395
4396 ;; fmovd substitute post-reload splits
4397 (define_split
4398   [(set (match_operand:DF 0 "register_operand" "")
4399         (match_operand:DF 1 "register_operand" ""))
4400    (use (match_operand:PSI 2 "fpscr_operand" ""))
4401    (clobber (match_scratch:SI 3 ""))]
4402   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4403    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4404    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4405   [(const_int 0)]
4406   "
4407 {
4408   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
4409   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
4410                            gen_rtx_REG (SFmode, src), operands[2]));
4411   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
4412                            gen_rtx_REG (SFmode, src + 1), operands[2]));
4413   DONE;
4414 }")
4415
4416 (define_split
4417   [(set (match_operand:DF 0 "register_operand" "")
4418         (mem:DF (match_operand:SI 1 "register_operand" "")))
4419    (use (match_operand:PSI 2 "fpscr_operand" ""))
4420    (clobber (match_scratch:SI 3 ""))]
4421   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
4422    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4423    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
4424   [(const_int 0)]
4425   "
4426 {
4427   int regno = true_regnum (operands[0]);
4428   rtx insn;
4429   rtx mem2 = gen_rtx_MEM (SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
4430
4431   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
4432                                            regno + !! TARGET_LITTLE_ENDIAN),
4433                                   mem2, operands[2]));
4434   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
4435   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
4436                                            regno + ! TARGET_LITTLE_ENDIAN),
4437                                   gen_rtx_MEM (SFmode, operands[1]),
4438                                   operands[2]));
4439   DONE;
4440 }")
4441
4442 (define_split
4443   [(set (match_operand:DF 0 "register_operand" "")
4444         (match_operand:DF 1 "memory_operand" ""))
4445    (use (match_operand:PSI 2 "fpscr_operand" ""))
4446    (clobber (match_scratch:SI 3 ""))]
4447   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
4448    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
4449   [(const_int 0)]
4450   "
4451 {
4452   int regno = true_regnum (operands[0]);
4453   rtx addr, insn, adjust = NULL_RTX;
4454   rtx mem2 = copy_rtx (operands[1]);
4455   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
4456   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
4457
4458   PUT_MODE (mem2, SFmode);
4459   operands[1] = copy_rtx (mem2);
4460   addr = XEXP (mem2, 0);
4461   if (GET_CODE (addr) != POST_INC)
4462     {
4463       /* If we have to modify the stack pointer, the value that we have
4464          read with post-increment might be modified by an interrupt,
4465          so write it back.  */
4466       if (REGNO (addr) == STACK_POINTER_REGNUM)
4467         adjust = gen_push_e (reg0);
4468       else
4469         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
4470       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
4471     }
4472   addr = XEXP (addr, 0);
4473   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
4474   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4475   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
4476   if (adjust)
4477     emit_insn (adjust);
4478   else
4479     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4480   DONE;
4481 }")
4482
4483 (define_split
4484   [(set (match_operand:DF 0 "memory_operand" "")
4485         (match_operand:DF 1 "register_operand" ""))
4486    (use (match_operand:PSI 2 "fpscr_operand" ""))
4487    (clobber (match_scratch:SI 3 ""))]
4488   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
4489    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4490   [(const_int 0)]
4491   "
4492 {
4493   int regno = true_regnum (operands[1]);
4494   rtx insn, addr, adjust = NULL_RTX;
4495
4496   operands[0] = copy_rtx (operands[0]);
4497   PUT_MODE (operands[0], SFmode);
4498   insn = emit_insn (gen_movsf_ie (operands[0],
4499                                   gen_rtx_REG (SFmode,
4500                                            regno + ! TARGET_LITTLE_ENDIAN),
4501                                   operands[2]));
4502   operands[0] = copy_rtx (operands[0]);
4503   addr = XEXP (operands[0], 0);
4504   if (GET_CODE (addr) != PRE_DEC)
4505     {
4506       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
4507       emit_insn_before (adjust, insn);
4508       XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
4509     }
4510   addr = XEXP (addr, 0);
4511   if (! adjust)
4512     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4513   insn = emit_insn (gen_movsf_ie (operands[0],
4514                                   gen_rtx_REG (SFmode,
4515                                            regno + !! TARGET_LITTLE_ENDIAN),
4516                                   operands[2]));
4517   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4518   DONE;
4519 }")
4520
4521 ;; If the output is a register and the input is memory or a register, we have
4522 ;; to be careful and see which word needs to be loaded first.
4523
4524 (define_split
4525   [(set (match_operand:DF 0 "general_movdst_operand" "")
4526         (match_operand:DF 1 "general_movsrc_operand" ""))]
4527   "TARGET_SH1 && reload_completed"
4528   [(set (match_dup 2) (match_dup 3))
4529    (set (match_dup 4) (match_dup 5))]
4530   "
4531 {
4532   int regno;
4533
4534   if ((GET_CODE (operands[0]) == MEM
4535        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
4536       || (GET_CODE (operands[1]) == MEM
4537           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
4538     FAIL;
4539
4540   if (GET_CODE (operands[0]) == REG)
4541     regno = REGNO (operands[0]);
4542   else if (GET_CODE (operands[0]) == SUBREG)
4543     regno = subreg_regno (operands[0]);
4544   else if (GET_CODE (operands[0]) == MEM)
4545     regno = -1;
4546   else
4547     abort ();
4548
4549   if (regno == -1
4550       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
4551     {
4552       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
4553       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
4554       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
4555       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
4556     }
4557   else
4558     {
4559       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
4560       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
4561       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
4562       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
4563     }
4564
4565   if (operands[2] == 0 || operands[3] == 0
4566       || operands[4] == 0 || operands[5] == 0)
4567     FAIL;
4568 }")
4569
4570 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
4571 ;; used only once, let combine add in the index again.
4572
4573 (define_split
4574   [(set (match_operand:SI 0 "register_operand" "")
4575         (match_operand:SI 1 "" ""))
4576    (clobber (match_operand 2 "register_operand" ""))]
4577   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4578   [(use (reg:SI R0_REG))]
4579   "
4580 {
4581   rtx addr, reg, const_int;
4582
4583   if (GET_CODE (operands[1]) != MEM)
4584     FAIL;
4585   addr = XEXP (operands[1], 0);
4586   if (GET_CODE (addr) != PLUS)
4587     FAIL;
4588   reg = XEXP (addr, 0);
4589   const_int = XEXP (addr, 1);
4590   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4591          && GET_CODE (const_int) == CONST_INT))
4592     FAIL;
4593   emit_move_insn (operands[2], const_int);
4594   emit_move_insn (operands[0],
4595                   change_address (operands[1], VOIDmode,
4596                                   gen_rtx_PLUS (SImode, reg, operands[2])));
4597   DONE;
4598 }")
4599
4600 (define_split
4601   [(set (match_operand:SI 1 "" "")
4602         (match_operand:SI 0 "register_operand" ""))
4603    (clobber (match_operand 2 "register_operand" ""))]
4604   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4605   [(use (reg:SI R0_REG))]
4606   "
4607 {
4608   rtx addr, reg, const_int;
4609
4610   if (GET_CODE (operands[1]) != MEM)
4611     FAIL;
4612   addr = XEXP (operands[1], 0);
4613   if (GET_CODE (addr) != PLUS)
4614     FAIL;
4615   reg = XEXP (addr, 0);
4616   const_int = XEXP (addr, 1);
4617   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4618          && GET_CODE (const_int) == CONST_INT))
4619     FAIL;
4620   emit_move_insn (operands[2], const_int);
4621   emit_move_insn (change_address (operands[1], VOIDmode,
4622                                   gen_rtx_PLUS (SImode, reg, operands[2])),
4623                   operands[0]);
4624   DONE;
4625 }")
4626
4627 (define_expand "movdf"
4628   [(set (match_operand:DF 0 "general_movdst_operand" "")
4629         (match_operand:DF 1 "general_movsrc_operand" ""))]
4630   ""
4631   "
4632 {
4633   if (prepare_move_operands (operands, DFmode)) DONE;
4634   if (TARGET_SHMEDIA)
4635     {
4636       if (TARGET_SHMEDIA_FPU)
4637         emit_insn (gen_movdf_media (operands[0], operands[1]));
4638       else
4639         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
4640       DONE;
4641     }
4642   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
4643     {
4644       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
4645       DONE;
4646     }
4647 }")
4648
4649 ;;This is incompatible with the way gcc uses subregs.
4650 ;;(define_insn "movv2sf_i"
4651 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
4652 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
4653 ;;  "TARGET_SHMEDIA_FPU
4654 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
4655 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
4656 ;;  "@
4657 ;;      #
4658 ;;      fld%M1.p        %m1, %0
4659 ;;      fst%M0.p        %m0, %1"
4660 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
4661
4662 (define_insn_and_split "movv2sf_i"
4663   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
4664         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
4665   "TARGET_SHMEDIA_FPU"
4666   "#"
4667   "TARGET_SHMEDIA_FPU && reload_completed"
4668   [(set (match_dup 0) (match_dup 1))]
4669   "
4670 {
4671   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
4672   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
4673 }")
4674
4675 (define_expand "movv2sf"
4676   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
4677         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
4678   "TARGET_SHMEDIA_FPU"
4679   "
4680 {
4681   if (prepare_move_operands (operands, V2SFmode))
4682     DONE;
4683 }")
4684
4685 (define_expand "addv2sf3"
4686   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4687    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4688    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4689   "TARGET_SHMEDIA_FPU"
4690   "
4691 {
4692   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
4693   DONE;
4694 }")
4695
4696 (define_expand "subv2sf3"
4697   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4698    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4699    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4700   "TARGET_SHMEDIA_FPU"
4701   "
4702 {
4703   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
4704   DONE;
4705 }")
4706
4707 (define_expand "mulv2sf3"
4708   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4709    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4710    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4711   "TARGET_SHMEDIA_FPU"
4712   "
4713 {
4714   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
4715   DONE;
4716 }")
4717
4718 (define_expand "divv2sf3"
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 (DIV, operands[0], operands[1], operands[2]);
4726   DONE;
4727 }")
4728
4729 (define_insn_and_split "*movv4sf_i"
4730   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
4731         (match_operand:V4SF 1 "general_operand" "fZ,m,fZ"))]
4732   "TARGET_SHMEDIA_FPU"
4733   "#"
4734   "&& reload_completed"
4735   [(const_int 0)]
4736   "
4737 {
4738   int i;
4739
4740   for (i = 0; i < 4/2; i++)
4741     {
4742       rtx x, y;
4743
4744       if (GET_CODE (operands[0]) == MEM)
4745         x = gen_rtx_MEM (V2SFmode,
4746                          plus_constant (XEXP (operands[0], 0),
4747                                         i * GET_MODE_SIZE (V2SFmode)));
4748       else
4749         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
4750
4751       if (GET_CODE (operands[1]) == MEM)
4752         y = gen_rtx_MEM (V2SFmode,
4753                          plus_constant (XEXP (operands[1], 0),
4754                                         i * GET_MODE_SIZE (V2SFmode)));
4755       else
4756         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
4757
4758       emit_insn (gen_movv2sf_i (x, y));
4759     }
4760
4761   DONE;
4762 }"
4763   [(set_attr "length" "8")])
4764
4765 (define_expand "movv4sf"
4766   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
4767         (match_operand:V4SF 1 "general_operand" ""))]
4768   "TARGET_SHMEDIA_FPU"
4769   "
4770 {
4771   if (prepare_move_operands (operands, V4SFmode))
4772     DONE;
4773 }")
4774
4775 (define_insn_and_split "*movv16sf_i"
4776   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4777         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4778   "TARGET_SHMEDIA_FPU"
4779   "#"
4780   "&& reload_completed"
4781   [(const_int 0)]
4782   "
4783 {
4784   int i;
4785
4786   for (i = 0; i < 16/2; i++)
4787     {
4788       rtx x,y;
4789
4790       if (GET_CODE (operands[0]) == MEM)
4791         x = gen_rtx_MEM (V2SFmode,
4792                          plus_constant (XEXP (operands[0], 0),
4793                                         i * GET_MODE_SIZE (V2SFmode)));
4794       else
4795         {
4796           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
4797           alter_subreg (&x);
4798         }
4799
4800       if (GET_CODE (operands[1]) == MEM)
4801         y = gen_rtx_MEM (V2SFmode,
4802                          plus_constant (XEXP (operands[1], 0),
4803                                         i * GET_MODE_SIZE (V2SFmode)));
4804       else
4805         {
4806           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
4807           alter_subreg (&y);
4808         }
4809
4810       emit_insn (gen_movv2sf_i (x, y));
4811     }
4812
4813   DONE;
4814 }"
4815   [(set_attr "length" "32")])
4816
4817 (define_expand "movv16sf"
4818   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4819         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4820   "TARGET_SHMEDIA_FPU"
4821   "
4822 {
4823   if (prepare_move_operands (operands, V16SFmode))
4824     DONE;
4825 }")
4826
4827 (define_insn "movsf_media"
4828   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4829         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
4830   "TARGET_SHMEDIA_FPU
4831    && (register_operand (operands[0], SFmode)
4832        || sh_register_operand (operands[1], SFmode))"
4833   "@
4834         fmov.s  %1, %0
4835         fmov.ls %N1, %0
4836         fmov.sl %1, %0
4837         add.l   %1, r63, %0
4838         #
4839         fld%M1.s        %m1, %0
4840         fst%M0.s        %m0, %1
4841         ld%M1.l %m1, %0
4842         st%M0.l %m0, %N1"
4843   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4844
4845 (define_insn "movsf_media_nofpu"
4846   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
4847         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
4848   "TARGET_SHMEDIA
4849    && (register_operand (operands[0], SFmode)
4850        || sh_register_operand (operands[1], SFmode))"
4851   "@
4852         add.l   %1, r63, %0
4853         #
4854         ld%M1.l %m1, %0
4855         st%M0.l %m0, %N1"
4856   [(set_attr "type" "arith_media,*,load_media,store_media")])
4857
4858 (define_split
4859   [(set (match_operand:SF 0 "arith_reg_operand" "")
4860         (match_operand:SF 1 "immediate_operand" ""))]
4861   "TARGET_SHMEDIA && reload_completed
4862    && ! FP_REGISTER_P (true_regnum (operands[0]))"
4863   [(set (match_dup 3) (match_dup 2))]
4864   "
4865 {
4866   long values;
4867   REAL_VALUE_TYPE value;
4868
4869   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4870   REAL_VALUE_TO_TARGET_SINGLE (value, values);
4871   operands[2] = GEN_INT (values);
4872
4873   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4874 }")
4875
4876 (define_insn "movsf_i"
4877   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
4878         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
4879   "TARGET_SH1
4880    && (! TARGET_SH2E
4881        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
4882        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4883        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4884    && (arith_reg_operand (operands[0], SFmode)
4885        || arith_reg_operand (operands[1], SFmode))"
4886   "@
4887         mov     %1,%0
4888         mov     #0,%0
4889         mov.l   %1,%0
4890         mov.l   %1,%0
4891         mov.l   %1,%0
4892         lds     %1,%0
4893         sts     %1,%0"
4894   [(set_attr "type" "move,move,pcload,load,store,move,move")])
4895
4896 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
4897 ;; update_flow_info would not know where to put REG_EQUAL notes
4898 ;; when the destination changes mode.
4899 (define_insn "movsf_ie"
4900   [(set (match_operand:SF 0 "general_movdst_operand"
4901          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
4902         (match_operand:SF 1 "general_movsrc_operand"
4903           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
4904    (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"))
4905    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
4906
4907   "TARGET_SH2E
4908    && (arith_reg_operand (operands[0], SFmode)
4909        || arith_reg_operand (operands[1], SFmode)
4910        || arith_reg_operand (operands[3], SImode)
4911        || (fpul_operand (operands[0], SFmode)
4912            && memory_operand (operands[1], SFmode)
4913            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
4914        || (fpul_operand (operands[1], SFmode)
4915            && memory_operand (operands[0], SFmode)
4916            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
4917   "@
4918         fmov    %1,%0
4919         mov     %1,%0
4920         fldi0   %0
4921         fldi1   %0
4922         #
4923         fmov.s  %1,%0
4924         fmov.s  %1,%0
4925         mov.l   %1,%0
4926         mov.l   %1,%0
4927         mov.l   %1,%0
4928         fsts    fpul,%0
4929         flds    %1,fpul
4930         lds.l   %1,%0
4931         #
4932         sts     %1,%0
4933         lds     %1,%0
4934         sts.l   %1,%0
4935         lds.l   %1,%0
4936         ! move optimized away"
4937   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
4938    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
4939    (set_attr "length" "*,*,*,*,4,4,4,*,*,*,2,2,2,4,2,2,2,2,0")
4940    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4941                                            (const_string "single")
4942                                            (const_string "none")))])
4943
4944 (define_split
4945   [(set (match_operand:SF 0 "register_operand" "")
4946         (match_operand:SF 1 "register_operand" ""))
4947    (use (match_operand:PSI 2 "fpscr_operand" ""))
4948    (clobber (reg:SI FPUL_REG))]
4949   "TARGET_SH1"
4950   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
4951               (use (match_dup 2))
4952               (clobber (scratch:SI))])
4953    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
4954               (use (match_dup 2))
4955               (clobber (scratch:SI))])]
4956   "")
4957
4958 (define_expand "movsf"
4959   [(set (match_operand:SF 0 "general_movdst_operand" "")
4960         (match_operand:SF 1 "general_movsrc_operand" ""))]
4961   ""
4962   "
4963 {
4964   if (prepare_move_operands (operands, SFmode))
4965     DONE;
4966   if (TARGET_SHMEDIA)
4967     {
4968       if (TARGET_SHMEDIA_FPU)
4969         emit_insn (gen_movsf_media (operands[0], operands[1]));
4970       else
4971         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
4972       DONE;
4973     }
4974   if (TARGET_SH2E)
4975     {
4976       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
4977       DONE;
4978     }
4979 }")
4980
4981 (define_insn "mov_nop"
4982   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
4983   "TARGET_SH2E"
4984   ""
4985   [(set_attr "length" "0")
4986    (set_attr "type" "nil")])
4987
4988 (define_expand "reload_insf"
4989   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
4990                    (match_operand:SF 1 "immediate_operand" "FQ"))
4991               (use (reg:PSI FPSCR_REG))
4992               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4993   "TARGET_SH1"
4994   "")
4995
4996 (define_expand "reload_insi"
4997   [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
4998                    (match_operand:SF 1 "immediate_operand" "FQ"))
4999               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5000   "TARGET_SH1"
5001   "")
5002
5003 (define_insn "*movsi_y"
5004   [(set (match_operand:SI 0 "register_operand" "=y,y")
5005         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
5006    (clobber (match_scratch:SI 2 "=&z,r"))]
5007   "TARGET_SH2E
5008    && (reload_in_progress || reload_completed)"
5009   "#"
5010   [(set_attr "length" "4")
5011    (set_attr "type" "pcload,move")])
5012
5013 (define_split
5014   [(set (match_operand:SI 0 "register_operand" "")
5015         (match_operand:SI 1 "immediate_operand" ""))
5016    (clobber (match_operand:SI 2 "register_operand" ""))]
5017   "TARGET_SH1"
5018   [(set (match_dup 2) (match_dup 1))
5019    (set (match_dup 0) (match_dup 2))]
5020   "")
5021
5022 (define_split
5023   [(set (match_operand:SI 0 "register_operand" "")
5024         (match_operand:SI 1 "memory_operand" ""))
5025    (clobber (reg:SI R0_REG))]
5026   "TARGET_SH1"
5027   [(set (match_dup 0) (match_dup 1))]
5028   "")
5029 \f
5030 ;; ------------------------------------------------------------------------
5031 ;; Define the real conditional branch instructions.
5032 ;; ------------------------------------------------------------------------
5033
5034 (define_insn "branch_true"
5035   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
5036                            (label_ref (match_operand 0 "" ""))
5037                            (pc)))]
5038   "TARGET_SH1"
5039   "* return output_branch (1, insn, operands);"
5040   [(set_attr "type" "cbranch")])
5041
5042 (define_insn "branch_false"
5043   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
5044                            (label_ref (match_operand 0 "" ""))
5045                            (pc)))]
5046   "TARGET_SH1"
5047   "* return output_branch (0, insn, operands);"
5048   [(set_attr "type" "cbranch")])
5049
5050 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
5051 ;; which destination is too far away.
5052 ;; The const_int_operand is distinct for each branch target; it avoids
5053 ;; unwanted matches with redundant_insn.
5054 (define_insn "block_branch_redirect"
5055   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
5056   "TARGET_SH1"
5057   ""
5058   [(set_attr "length" "0")])
5059
5060 ;; This one has the additional purpose to record a possible scratch register
5061 ;; for the following branch.
5062 ;; ??? Unfortunately, just setting the scratch register is not good enough,
5063 ;; because the insn then might be deemed dead and deleted.  And we can't
5064 ;; make the use in the jump insn explicit because that would disable
5065 ;; delay slot scheduling from the target.
5066 (define_insn "indirect_jump_scratch"
5067   [(set (match_operand:SI 0 "register_operand" "=r")
5068         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
5069    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
5070   "TARGET_SH1"
5071   ""
5072   [(set_attr "length" "0")])
5073
5074 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
5075 ;; being pulled into the delay slot of a condbranch that has been made to
5076 ;; jump around the unconditional jump because it was out of range.
5077 (define_insn "stuff_delay_slot"
5078   [(set (pc)
5079         (unspec [(match_operand 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
5080    (set (reg:SI T_REG) (match_operand 1 "const_int_operand" ""))]
5081   "TARGET_SH1"
5082   ""
5083   [(set_attr "length" "0")
5084    (set_attr "cond_delay_slot" "yes")])
5085 \f
5086 ;; Conditional branch insns
5087
5088 (define_expand "beq_media"
5089   [(set (pc)
5090         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
5091                           (match_operand:DI 2 "arith_operand" "r,I06"))
5092                       (label_ref:DI (match_operand 0 "" ""))
5093                       (pc)))]
5094   "TARGET_SHMEDIA"
5095   "")
5096
5097 (define_insn "*beq_media_i"
5098   [(set (pc)
5099         (if_then_else (match_operator 3 "equality_comparison_operator"
5100                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
5101                          (match_operand:DI 2 "arith_operand" "r,I06")])
5102                       (match_operand:DI 0 "target_operand" "b,b")
5103                       (pc)))]
5104   "TARGET_SHMEDIA"
5105   "@
5106         b%o3%'  %1, %2, %0
5107         b%o3i%' %1, %2, %0"
5108   [(set_attr "type" "cbranch_media")])
5109
5110 (define_expand "bne_media"
5111   [(set (pc)
5112         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
5113                           (match_operand:DI 2 "arith_operand" "r,I06"))
5114                       (label_ref:DI (match_operand 0 "" ""))
5115                       (pc)))]
5116   "TARGET_SHMEDIA"
5117   "")
5118
5119 (define_expand "bgt_media"
5120   [(set (pc)
5121         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5122                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5123                       (label_ref:DI (match_operand 0 "" ""))
5124                       (pc)))]
5125   "TARGET_SHMEDIA"
5126   "")
5127
5128 (define_expand "bge_media"
5129   [(set (pc)
5130         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5131                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5132                       (label_ref:DI (match_operand 0 "" ""))
5133                       (pc)))]
5134   "TARGET_SHMEDIA"
5135   "")
5136
5137 (define_expand "bgtu_media"
5138   [(set (pc)
5139         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5140                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5141                       (label_ref:DI (match_operand 0 "" ""))
5142                       (pc)))]
5143   "TARGET_SHMEDIA"
5144   "")
5145
5146 (define_expand "bgeu_media"
5147   [(set (pc)
5148         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5149                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5150                       (label_ref:DI (match_operand 0 "" ""))
5151                       (pc)))]
5152   "TARGET_SHMEDIA"
5153   "")
5154
5155 (define_insn "*bgt_media_i"
5156   [(set (pc)
5157         (if_then_else (match_operator 3 "greater_comparison_operator"
5158                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5159                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5160                       (match_operand:DI 0 "target_operand" "b")
5161                       (pc)))]
5162   "TARGET_SHMEDIA"
5163   "b%o3%'       %N1, %N2, %0"
5164   [(set_attr "type" "cbranch_media")])
5165
5166 ;; These are only needed to make invert_jump() happy.
5167 (define_insn "*blt_media_i"
5168   [(set (pc)
5169         (if_then_else (match_operator 3 "less_comparison_operator"
5170                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5171                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5172                       (match_operand:DI 0 "target_operand" "b")
5173                       (pc)))]
5174   "TARGET_SHMEDIA"
5175   "b%o3%'       %N2, %N1, %0"
5176   [(set_attr "type" "cbranch_media")])
5177
5178 (define_expand "beq"
5179   [(set (pc)
5180         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5181                       (label_ref (match_operand 0 "" ""))
5182                       (pc)))]
5183   ""
5184   "
5185 {
5186   if (TARGET_SHMEDIA)
5187     {
5188       if (GET_MODE (sh_compare_op0) != DImode)
5189         {
5190           rtx tmp = gen_reg_rtx (DImode);
5191
5192           emit_insn (gen_seq (tmp));
5193           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5194           DONE;
5195         }
5196
5197       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5198       emit_jump_insn (gen_beq_media (operands[0],
5199                                      sh_compare_op0, sh_compare_op1));
5200       DONE;
5201     }
5202
5203   from_compare (operands, EQ);
5204 }")
5205
5206 (define_expand "bne"
5207   [(set (pc)
5208         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5209                       (label_ref (match_operand 0 "" ""))
5210                       (pc)))]
5211   ""
5212   "
5213 {
5214   if (TARGET_SHMEDIA)
5215     {
5216       if (GET_MODE (sh_compare_op0) != DImode)
5217         {
5218           rtx tmp = gen_reg_rtx (DImode);
5219
5220           emit_insn (gen_seq (tmp));
5221           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
5222           DONE;
5223         }
5224
5225       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5226       emit_jump_insn (gen_bne_media (operands[0],
5227                                      sh_compare_op0, sh_compare_op1));
5228       DONE;
5229     }
5230
5231   from_compare (operands, EQ);
5232 }")
5233
5234 (define_expand "bgt"
5235   [(set (pc)
5236         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5237                       (label_ref (match_operand 0 "" ""))
5238                       (pc)))]
5239   ""
5240   "
5241 {
5242   if (TARGET_SHMEDIA)
5243     {
5244       if (GET_MODE (sh_compare_op0) != DImode)
5245         {
5246           rtx tmp = gen_reg_rtx (DImode);
5247
5248           emit_insn (gen_sgt (tmp));
5249           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5250           DONE;
5251         }
5252
5253       if (sh_compare_op0 != const0_rtx)
5254         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5255       if (sh_compare_op1 != const0_rtx)
5256         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5257       emit_jump_insn (gen_bgt_media (operands[0],
5258                                      sh_compare_op0, sh_compare_op1));
5259       DONE;
5260     }
5261
5262   from_compare (operands, GT);
5263 }")
5264
5265 (define_expand "blt"
5266   [(set (pc)
5267         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5268                       (label_ref (match_operand 0 "" ""))
5269                       (pc)))]
5270   ""
5271   "
5272 {
5273   if (TARGET_SHMEDIA)
5274     {
5275       if (GET_MODE (sh_compare_op0) != DImode)
5276         {
5277           rtx tmp = gen_reg_rtx (DImode);
5278
5279           emit_insn (gen_slt (tmp));
5280           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5281           DONE;
5282         }
5283
5284       if (sh_compare_op0 != const0_rtx)
5285         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5286       if (sh_compare_op1 != const0_rtx)
5287         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5288       emit_jump_insn (gen_bgt_media (operands[0],
5289                                      sh_compare_op1, sh_compare_op0));
5290       DONE;
5291     }
5292
5293   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5294     {
5295       rtx tmp = sh_compare_op0;
5296       sh_compare_op0 = sh_compare_op1;
5297       sh_compare_op1 = tmp;
5298       emit_insn (gen_bgt (operands[0]));
5299       DONE;
5300     }
5301   from_compare (operands, GE);
5302 }")
5303
5304 (define_expand "ble"
5305   [(set (pc)
5306         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5307                       (label_ref (match_operand 0 "" ""))
5308                       (pc)))]
5309   ""
5310   "
5311 {
5312   if (TARGET_SHMEDIA)
5313     {
5314       if (GET_MODE (sh_compare_op0) != DImode)
5315         {
5316           rtx tmp = gen_reg_rtx (DImode);
5317
5318           emit_insn (gen_sle (tmp));
5319           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5320           DONE;
5321         }
5322
5323       if (sh_compare_op0 != const0_rtx)
5324         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5325       if (sh_compare_op1 != const0_rtx)
5326         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5327       emit_jump_insn (gen_bge_media (operands[0],
5328                                      sh_compare_op1, sh_compare_op0));
5329       DONE;
5330     }
5331
5332   if (TARGET_SH2E
5333       && TARGET_IEEE
5334       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5335     {
5336       rtx tmp = sh_compare_op0;
5337       sh_compare_op0 = sh_compare_op1;
5338       sh_compare_op1 = tmp;
5339       emit_insn (gen_bge (operands[0]));
5340       DONE;
5341     }
5342   from_compare (operands, GT);
5343 }")
5344
5345 (define_expand "bge"
5346   [(set (pc)
5347         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5348                       (label_ref (match_operand 0 "" ""))
5349                       (pc)))]
5350   ""
5351   "
5352 {
5353   if (TARGET_SHMEDIA)
5354     {
5355       if (GET_MODE (sh_compare_op0) != DImode)
5356         {
5357           rtx tmp = gen_reg_rtx (DImode);
5358
5359           emit_insn (gen_sge (tmp));
5360           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5361           DONE;
5362         }
5363
5364       if (sh_compare_op0 != const0_rtx)
5365         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5366       if (sh_compare_op1 != const0_rtx)
5367         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5368       emit_jump_insn (gen_bge_media (operands[0],
5369                                      sh_compare_op0, sh_compare_op1));
5370       DONE;
5371     }
5372
5373   if (TARGET_SH2E
5374       && ! TARGET_IEEE
5375       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5376     {
5377       rtx tmp = sh_compare_op0;
5378       sh_compare_op0 = sh_compare_op1;
5379       sh_compare_op1 = tmp;
5380       emit_insn (gen_ble (operands[0]));
5381       DONE;
5382     }
5383   from_compare (operands, GE);
5384 }")
5385
5386 (define_expand "bgtu"
5387   [(set (pc)
5388         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5389                       (label_ref (match_operand 0 "" ""))
5390                       (pc)))]
5391   ""
5392   "
5393 {
5394   if (TARGET_SHMEDIA)
5395     {
5396       if (sh_compare_op0 != const0_rtx)
5397         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5398       if (sh_compare_op1 != const0_rtx)
5399         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5400       emit_jump_insn (gen_bgtu_media (operands[0],
5401                                       sh_compare_op0, sh_compare_op1));
5402       DONE;
5403     }
5404
5405   from_compare (operands, GTU);
5406 }")
5407
5408 (define_expand "bltu"
5409   [(set (pc)
5410         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5411                       (label_ref (match_operand 0 "" ""))
5412                       (pc)))]
5413   ""
5414   "
5415 {
5416   if (TARGET_SHMEDIA)
5417     {
5418       if (sh_compare_op0 != const0_rtx)
5419         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5420       if (sh_compare_op1 != const0_rtx)
5421         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5422       emit_jump_insn (gen_bgtu_media (operands[0],
5423                                       sh_compare_op1, sh_compare_op0));
5424       DONE;
5425     }
5426
5427   from_compare (operands, GEU);
5428 }")
5429
5430 (define_expand "bgeu"
5431   [(set (pc)
5432         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5433                       (label_ref (match_operand 0 "" ""))
5434                       (pc)))]
5435   ""
5436   "
5437 {
5438   if (TARGET_SHMEDIA)
5439     {
5440       if (sh_compare_op0 != const0_rtx)
5441         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5442       if (sh_compare_op1 != const0_rtx)
5443         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5444       emit_jump_insn (gen_bgeu_media (operands[0],
5445                                       sh_compare_op0, sh_compare_op1));
5446       DONE;
5447     }
5448
5449   from_compare (operands, GEU);
5450 }")
5451
5452 (define_expand "bleu"
5453   [(set (pc)
5454         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5455                       (label_ref (match_operand 0 "" ""))
5456                       (pc)))]
5457   ""
5458   "
5459 {
5460   if (TARGET_SHMEDIA)
5461     {
5462       if (sh_compare_op0 != const0_rtx)
5463         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5464       if (sh_compare_op1 != const0_rtx)
5465         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5466       emit_jump_insn (gen_bgeu_media (operands[0],
5467                                       sh_compare_op1, sh_compare_op0));
5468       DONE;
5469     }
5470
5471   from_compare (operands, GTU);
5472 }")
5473
5474 (define_expand "bunordered"
5475   [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
5476    (set (pc)
5477         (if_then_else (ne (match_dup 1) (const_int 0))
5478                       (label_ref:DI (match_operand 0 "" ""))
5479                       (pc)))]
5480   "TARGET_SHMEDIA"
5481   "
5482 {
5483   operands[1] = gen_reg_rtx (DImode);
5484   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
5485   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
5486 }")
5487 \f
5488 ;; ------------------------------------------------------------------------
5489 ;; Jump and linkage insns
5490 ;; ------------------------------------------------------------------------
5491
5492 (define_insn "jump_compact"
5493   [(set (pc)
5494         (label_ref (match_operand 0 "" "")))]
5495   "TARGET_SH1"
5496   "*
5497 {
5498   /* The length is 16 if the delay slot is unfilled.  */
5499   if (get_attr_length(insn) > 4)
5500     return output_far_jump(insn, operands[0]);
5501   else
5502     return   \"bra      %l0%#\";
5503 }"
5504   [(set_attr "type" "jump")
5505    (set_attr "needs_delay_slot" "yes")])
5506
5507 ;; ??? It would be much saner to explicitly use the scratch register
5508 ;; in the jump insn, and have indirect_jump_scratch only set it,
5509 ;; but fill_simple_delay_slots would refuse to do delay slot filling
5510 ;; from the target then, as it uses simplejump_p.
5511 ;;(define_insn "jump_compact_far"
5512 ;;  [(set (pc)
5513 ;;      (label_ref (match_operand 0 "" "")))
5514 ;;   (use (match_operand 1 "register_operand" "r")]
5515 ;;  "TARGET_SH1"
5516 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
5517 ;;  [(set_attr "type" "jump")
5518 ;;   (set_attr "needs_delay_slot" "yes")])
5519
5520 (define_insn "jump_media"
5521   [(set (pc)
5522         (match_operand:DI 0 "target_operand" "b"))]
5523   "TARGET_SHMEDIA"
5524   "blink        %0, r63"
5525   [(set_attr "type" "jump_media")])
5526
5527 (define_expand "jump"
5528   [(set (pc)
5529         (label_ref (match_operand 0 "" "")))]
5530   ""
5531   "
5532 {
5533   if (TARGET_SH1)
5534     emit_jump_insn (gen_jump_compact (operands[0]));
5535   else if (TARGET_SHMEDIA)
5536     {
5537       if (reload_in_progress || reload_completed)
5538         FAIL;
5539       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode,
5540                                                          operands[0])));
5541     }
5542   DONE;
5543 }")
5544
5545 (define_insn "force_mode_for_call"
5546   [(use (reg:PSI FPSCR_REG))]
5547   "TARGET_SHCOMPACT"
5548   ""
5549   [(set_attr "length" "0")
5550    (set (attr "fp_mode")
5551         (if_then_else (eq_attr "fpu_single" "yes")
5552                       (const_string "single") (const_string "double")))])
5553
5554 (define_insn "calli"
5555   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5556          (match_operand 1 "" ""))
5557    (use (reg:PSI FPSCR_REG))
5558    (clobber (reg:SI PR_REG))]
5559   "TARGET_SH1"
5560   "jsr  @%0%#"
5561   [(set_attr "type" "call")
5562    (set (attr "fp_mode")
5563         (if_then_else (eq_attr "fpu_single" "yes")
5564                       (const_string "single") (const_string "double")))
5565    (set_attr "needs_delay_slot" "yes")
5566    (set_attr "fp_set" "unknown")])
5567
5568 ;; This is a pc-rel call, using bsrf, for use with PIC.
5569
5570 (define_insn "calli_pcrel"
5571   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5572          (match_operand 1 "" ""))
5573    (use (reg:PSI FPSCR_REG))
5574    (use (reg:SI PIC_REG))
5575    (use (match_operand 2 "" ""))
5576    (clobber (reg:SI PR_REG))]
5577   "TARGET_SH2"
5578   "bsrf %0\\n%O2:%#"
5579   [(set_attr "type" "call")
5580    (set (attr "fp_mode")
5581         (if_then_else (eq_attr "fpu_single" "yes")
5582                       (const_string "single") (const_string "double")))
5583    (set_attr "needs_delay_slot" "yes")
5584    (set_attr "fp_set" "unknown")])
5585
5586 (define_insn_and_split "call_pcrel"
5587   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
5588          (match_operand 1 "" ""))
5589    (use (reg:PSI FPSCR_REG))
5590    (use (reg:SI PIC_REG))
5591    (clobber (reg:SI PR_REG))
5592    (clobber (match_scratch:SI 2 "=r"))]
5593   "TARGET_SH2"
5594   "#"
5595   "reload_completed"
5596   [(const_int 0)]
5597   "
5598 {
5599   rtx lab = PATTERN (gen_call_site ());
5600
5601   if (SYMBOL_REF_LOCAL_P (operands[0]))
5602     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
5603   else
5604     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
5605   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
5606   DONE;
5607 }"
5608   [(set_attr "type" "call")
5609    (set (attr "fp_mode")
5610         (if_then_else (eq_attr "fpu_single" "yes")
5611                       (const_string "single") (const_string "double")))
5612    (set_attr "needs_delay_slot" "yes")
5613    (set_attr "fp_set" "unknown")])
5614
5615 (define_insn "call_compact"
5616   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5617          (match_operand 1 "" ""))
5618    (match_operand 2 "immediate_operand" "n")
5619    (use (reg:SI R0_REG))
5620    (use (reg:SI R1_REG))
5621    (use (reg:PSI FPSCR_REG))
5622    (clobber (reg:SI PR_REG))]
5623   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5624   "jsr  @%0%#"
5625   [(set_attr "type" "call")
5626    (set (attr "fp_mode")
5627         (if_then_else (eq_attr "fpu_single" "yes")
5628                       (const_string "single") (const_string "double")))
5629    (set_attr "needs_delay_slot" "yes")])
5630
5631 (define_insn "call_compact_rettramp"
5632   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5633          (match_operand 1 "" ""))
5634    (match_operand 2 "immediate_operand" "n")
5635    (use (reg:SI R0_REG))
5636    (use (reg:SI R1_REG))
5637    (use (reg:PSI FPSCR_REG))
5638    (clobber (reg:SI R10_REG))
5639    (clobber (reg:SI PR_REG))]
5640   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5641   "jsr  @%0%#"
5642   [(set_attr "type" "call")
5643    (set (attr "fp_mode")
5644         (if_then_else (eq_attr "fpu_single" "yes")
5645                       (const_string "single") (const_string "double")))
5646    (set_attr "needs_delay_slot" "yes")])
5647
5648 (define_insn "call_media"
5649   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b"))
5650          (match_operand 1 "" ""))
5651    (clobber (reg:DI PR_MEDIA_REG))]
5652   "TARGET_SHMEDIA"
5653   "blink        %0, r18"
5654   [(set_attr "type" "jump_media")])
5655
5656 (define_insn "call_valuei"
5657   [(set (match_operand 0 "" "=rf")
5658         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5659               (match_operand 2 "" "")))
5660    (use (reg:PSI FPSCR_REG))
5661    (clobber (reg:SI PR_REG))]
5662   "TARGET_SH1"
5663   "jsr  @%1%#"
5664   [(set_attr "type" "call")
5665    (set (attr "fp_mode")
5666         (if_then_else (eq_attr "fpu_single" "yes")
5667                       (const_string "single") (const_string "double")))
5668    (set_attr "needs_delay_slot" "yes")
5669    (set_attr "fp_set" "unknown")])
5670
5671 (define_insn "call_valuei_pcrel"
5672   [(set (match_operand 0 "" "=rf")
5673         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5674               (match_operand 2 "" "")))
5675    (use (reg:PSI FPSCR_REG))
5676    (use (reg:SI PIC_REG))
5677    (use (match_operand 3 "" ""))
5678    (clobber (reg:SI PR_REG))]
5679   "TARGET_SH2"
5680   "bsrf %1\\n%O3:%#"
5681   [(set_attr "type" "call")
5682    (set (attr "fp_mode")
5683         (if_then_else (eq_attr "fpu_single" "yes")
5684                       (const_string "single") (const_string "double")))
5685    (set_attr "needs_delay_slot" "yes")
5686    (set_attr "fp_set" "unknown")])
5687
5688 (define_insn_and_split "call_value_pcrel"
5689   [(set (match_operand 0 "" "=rf")
5690         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
5691               (match_operand 2 "" "")))
5692    (use (reg:PSI FPSCR_REG))
5693    (use (reg:SI PIC_REG))
5694    (clobber (reg:SI PR_REG))
5695    (clobber (match_scratch:SI 3 "=r"))]
5696   "TARGET_SH2"
5697   "#"
5698   "reload_completed"
5699   [(const_int 0)]
5700   "
5701 {
5702   rtx lab = PATTERN (gen_call_site ());
5703
5704   if (SYMBOL_REF_LOCAL_P (operands[1]))
5705     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
5706   else
5707     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
5708   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
5709                                          operands[2], lab));
5710   DONE;
5711 }"
5712   [(set_attr "type" "call")
5713    (set (attr "fp_mode")
5714         (if_then_else (eq_attr "fpu_single" "yes")
5715                       (const_string "single") (const_string "double")))
5716    (set_attr "needs_delay_slot" "yes")
5717    (set_attr "fp_set" "unknown")])
5718
5719 (define_insn "call_value_compact"
5720   [(set (match_operand 0 "" "=rf")
5721         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5722               (match_operand 2 "" "")))
5723    (match_operand 3 "immediate_operand" "n")
5724    (use (reg:SI R0_REG))
5725    (use (reg:SI R1_REG))
5726    (use (reg:PSI FPSCR_REG))
5727    (clobber (reg:SI PR_REG))]
5728   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5729   "jsr  @%1%#"
5730   [(set_attr "type" "call")
5731    (set (attr "fp_mode")
5732         (if_then_else (eq_attr "fpu_single" "yes")
5733                       (const_string "single") (const_string "double")))
5734    (set_attr "needs_delay_slot" "yes")])
5735
5736 (define_insn "call_value_compact_rettramp"
5737   [(set (match_operand 0 "" "=rf")
5738         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5739               (match_operand 2 "" "")))
5740    (match_operand 3 "immediate_operand" "n")
5741    (use (reg:SI R0_REG))
5742    (use (reg:SI R1_REG))
5743    (use (reg:PSI FPSCR_REG))
5744    (clobber (reg:SI R10_REG))
5745    (clobber (reg:SI PR_REG))]
5746   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5747   "jsr  @%1%#"
5748   [(set_attr "type" "call")
5749    (set (attr "fp_mode")
5750         (if_then_else (eq_attr "fpu_single" "yes")
5751                       (const_string "single") (const_string "double")))
5752    (set_attr "needs_delay_slot" "yes")])
5753
5754 (define_insn "call_value_media"
5755   [(set (match_operand 0 "" "=rf")
5756         (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b"))
5757               (match_operand 2 "" "")))
5758    (clobber (reg:DI PR_MEDIA_REG))]
5759   "TARGET_SHMEDIA"
5760   "blink        %1, r18"
5761   [(set_attr "type" "jump_media")])
5762
5763 (define_expand "call"
5764   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5765                             (match_operand 1 "" ""))
5766               (match_operand 2 "" "")
5767               (use (reg:PSI FPSCR_REG))
5768               (clobber (reg:SI PR_REG))])]
5769   ""
5770   "
5771 {
5772   if (TARGET_SHMEDIA)
5773     {
5774       operands[0] = XEXP (operands[0], 0);
5775       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
5776         {
5777           if (! SYMBOL_REF_LOCAL_P (operands[0]))
5778             {
5779               rtx reg = gen_reg_rtx (Pmode);
5780
5781               emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5782               operands[0] = reg;
5783             }
5784           else
5785             {
5786               operands[0] = gen_sym2PIC (operands[0]);
5787               PUT_MODE (operands[0], Pmode);
5788             }
5789         }
5790       if (GET_MODE (operands[0]) == SImode)
5791         {
5792           if (GET_CODE (operands[0]) == REG)
5793             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5794           else if (GET_CODE (operands[0]) == SUBREG)
5795             {
5796               operands[0] = SUBREG_REG (operands[0]);
5797               if (GET_MODE (operands[0]) != DImode)
5798                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5799             }
5800           else
5801             {
5802               operands[0] = shallow_copy_rtx (operands[0]);
5803               PUT_MODE (operands[0], DImode);
5804             }
5805         }
5806       if (! target_reg_operand (operands[0], DImode))
5807         operands[0] = copy_to_mode_reg (DImode, operands[0]);
5808       emit_call_insn (gen_call_media (operands[0], operands[1]));
5809       DONE;
5810     }
5811   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
5812     {
5813       rtx cookie_rtx = operands[2];
5814       long cookie = INTVAL (cookie_rtx);
5815       rtx func = XEXP (operands[0], 0);
5816       rtx r0, r1;
5817
5818       if (flag_pic)
5819         {
5820           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
5821             {
5822               rtx reg = gen_reg_rtx (Pmode);
5823
5824               emit_insn (gen_symGOTPLT2reg (reg, func));
5825               func = reg;
5826             }
5827           else
5828             func = legitimize_pic_address (func, Pmode, 0);
5829         }
5830
5831       r0 = gen_rtx_REG (SImode, R0_REG);
5832       r1 = gen_rtx_REG (SImode, R1_REG);
5833
5834       /* Since such a call function may use all call-clobbered
5835          registers, we force a mode switch earlier, so that we don't
5836          run out of registers when adjusting fpscr for the call.  */
5837       emit_insn (gen_force_mode_for_call ());
5838
5839       operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\");
5840       if (flag_pic)
5841         {
5842           rtx reg = gen_reg_rtx (Pmode);
5843
5844           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5845           operands[0] = reg;
5846         }
5847       operands[0] = force_reg (SImode, operands[0]);
5848
5849       emit_move_insn (r0, func);
5850       emit_move_insn (r1, cookie_rtx);
5851
5852       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5853         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
5854                                                    operands[2]));
5855       else
5856         emit_call_insn (gen_call_compact (operands[0], operands[1],
5857                                           operands[2]));
5858
5859       DONE;
5860     }
5861   else if (TARGET_SHCOMPACT && flag_pic
5862            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5863            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
5864     {
5865       rtx reg = gen_reg_rtx (Pmode);
5866
5867       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
5868       XEXP (operands[0], 0) = reg;
5869     }
5870   if (flag_pic && TARGET_SH2
5871       && GET_CODE (operands[0]) == MEM
5872       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5873     {
5874       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
5875       DONE;
5876     }
5877   else
5878   {
5879     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
5880     operands[1] = operands[2];
5881   }
5882
5883   emit_call_insn (gen_calli (operands[0], operands[1]));
5884   DONE;
5885 }")
5886
5887 (define_insn "call_pop_compact"
5888   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5889          (match_operand 1 "" ""))
5890    (match_operand 2 "immediate_operand" "n")
5891    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5892                                  (match_operand 3 "immediate_operand" "n")))
5893    (use (reg:SI R0_REG))
5894    (use (reg:SI R1_REG))
5895    (use (reg:PSI FPSCR_REG))
5896    (clobber (reg:SI PR_REG))]
5897   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5898   "jsr  @%0%#"
5899   [(set_attr "type" "call")
5900    (set (attr "fp_mode")
5901         (if_then_else (eq_attr "fpu_single" "yes")
5902                       (const_string "single") (const_string "double")))
5903    (set_attr "needs_delay_slot" "yes")])
5904
5905 (define_insn "call_pop_compact_rettramp"
5906   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5907          (match_operand 1 "" ""))
5908    (match_operand 2 "immediate_operand" "n")
5909    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5910                                  (match_operand 3 "immediate_operand" "n")))
5911    (use (reg:SI R0_REG))
5912    (use (reg:SI R1_REG))
5913    (use (reg:PSI FPSCR_REG))
5914    (clobber (reg:SI R10_REG))
5915    (clobber (reg:SI PR_REG))]
5916   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5917   "jsr  @%0%#"
5918   [(set_attr "type" "call")
5919    (set (attr "fp_mode")
5920         (if_then_else (eq_attr "fpu_single" "yes")
5921                       (const_string "single") (const_string "double")))
5922    (set_attr "needs_delay_slot" "yes")])
5923
5924 (define_expand "call_pop"
5925   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5926                     (match_operand 1 "" ""))
5927              (match_operand 2 "" "")
5928              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5929                                            (match_operand 3 "" "")))])]
5930   "TARGET_SHCOMPACT"
5931   "
5932 {
5933   if (operands[2] && INTVAL (operands[2]))
5934     {
5935       rtx cookie_rtx = operands[2];
5936       long cookie = INTVAL (cookie_rtx);
5937       rtx func = XEXP (operands[0], 0);
5938       rtx r0, r1;
5939
5940       if (flag_pic)
5941         {
5942           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
5943             {
5944               rtx reg = gen_reg_rtx (Pmode);
5945
5946               emit_insn (gen_symGOTPLT2reg (reg, func));
5947               func = reg;
5948             }
5949           else
5950             func = legitimize_pic_address (func, Pmode, 0);
5951         }
5952
5953       r0 = gen_rtx_REG (SImode, R0_REG);
5954       r1 = gen_rtx_REG (SImode, R1_REG);
5955
5956       /* Since such a call function may use all call-clobbered
5957          registers, we force a mode switch earlier, so that we don't
5958          run out of registers when adjusting fpscr for the call.  */
5959       emit_insn (gen_force_mode_for_call ());
5960
5961       operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\");
5962       if (flag_pic)
5963         {
5964           rtx reg = gen_reg_rtx (Pmode);
5965
5966           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5967           operands[0] = reg;
5968         }
5969       operands[0] = force_reg (SImode, operands[0]);
5970
5971       emit_move_insn (r0, func);
5972       emit_move_insn (r1, cookie_rtx);
5973
5974       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5975         emit_call_insn (gen_call_pop_compact_rettramp
5976                         (operands[0], operands[1], operands[2], operands[3]));
5977       else
5978         emit_call_insn (gen_call_pop_compact
5979                         (operands[0], operands[1], operands[2], operands[3]));
5980
5981       DONE;
5982     }
5983
5984   abort ();
5985 }")
5986
5987 (define_expand "call_value"
5988   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
5989                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
5990                                  (match_operand 2 "" "")))
5991               (match_operand 3 "" "")
5992               (use (reg:PSI FPSCR_REG))
5993               (clobber (reg:SI PR_REG))])]
5994   ""
5995   "
5996 {
5997   if (TARGET_SHMEDIA)
5998     {
5999       operands[1] = XEXP (operands[1], 0);
6000       if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
6001         {
6002           if (! SYMBOL_REF_LOCAL_P (operands[1]))
6003             {
6004               rtx reg = gen_reg_rtx (Pmode);
6005
6006               emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6007               operands[1] = reg;
6008             }
6009           else
6010             {
6011               operands[1] = gen_sym2PIC (operands[1]);
6012               PUT_MODE (operands[1], Pmode);
6013             }
6014         }
6015       if (GET_MODE (operands[1]) == SImode)
6016         {
6017           if (GET_CODE (operands[1]) == REG)
6018             operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6019           else if (GET_CODE (operands[1]) == SUBREG)
6020             {
6021               operands[1] = SUBREG_REG (operands[1]);
6022               if (GET_MODE (operands[1]) != DImode)
6023                 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6024             }
6025           else
6026             {
6027               operands[1] = shallow_copy_rtx (operands[1]);
6028               PUT_MODE (operands[1], DImode);
6029             }
6030         }
6031       if (! target_reg_operand (operands[1], DImode))
6032         operands[1] = copy_to_mode_reg (DImode, operands[1]);
6033       emit_call_insn (gen_call_value_media (operands[0], operands[1],
6034                                             operands[2]));
6035       DONE;
6036     }
6037   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
6038     {
6039       rtx cookie_rtx = operands[3];
6040       long cookie = INTVAL (cookie_rtx);
6041       rtx func = XEXP (operands[1], 0);
6042       rtx r0, r1;
6043
6044       if (flag_pic)
6045         {
6046           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
6047             {
6048               rtx reg = gen_reg_rtx (Pmode);
6049
6050               emit_insn (gen_symGOTPLT2reg (reg, func));
6051               func = reg;
6052             }
6053           else
6054             func = legitimize_pic_address (func, Pmode, 0);
6055         }
6056
6057       r0 = gen_rtx_REG (SImode, R0_REG);
6058       r1 = gen_rtx_REG (SImode, R1_REG);
6059
6060       /* Since such a call function may use all call-clobbered
6061          registers, we force a mode switch earlier, so that we don't
6062          run out of registers when adjusting fpscr for the call.  */
6063       emit_insn (gen_force_mode_for_call ());
6064
6065       operands[1] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6066       if (flag_pic)
6067         {
6068           rtx reg = gen_reg_rtx (Pmode);
6069
6070           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6071           operands[1] = reg;
6072         }
6073       operands[1] = force_reg (SImode, operands[1]);
6074
6075       emit_move_insn (r0, func);
6076       emit_move_insn (r1, cookie_rtx);
6077
6078       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6079         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
6080                                                          operands[1],
6081                                                          operands[2],
6082                                                          operands[3]));
6083       else
6084         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
6085                                                 operands[2], operands[3]));
6086
6087       DONE;
6088     }
6089   else if (TARGET_SHCOMPACT && flag_pic
6090            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6091            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
6092     {
6093       rtx reg = gen_reg_rtx (Pmode);
6094
6095       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
6096       XEXP (operands[1], 0) = reg;
6097     }
6098   if (flag_pic && TARGET_SH2
6099       && GET_CODE (operands[1]) == MEM
6100       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6101     {
6102       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
6103                                             operands[2]));
6104       DONE;
6105     }
6106   else
6107     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
6108
6109   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
6110   DONE;
6111 }")
6112
6113 (define_insn "sibcalli"
6114   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
6115          (match_operand 1 "" ""))
6116    (use (reg:PSI FPSCR_REG))
6117    (return)]
6118   "TARGET_SH1"
6119   "jmp  @%0%#"
6120   [(set_attr "needs_delay_slot" "yes")
6121    (set (attr "fp_mode")
6122         (if_then_else (eq_attr "fpu_single" "yes")
6123                       (const_string "single") (const_string "double")))
6124    (set_attr "type" "jump_ind")])
6125
6126 (define_insn "sibcalli_pcrel"
6127   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
6128          (match_operand 1 "" ""))
6129    (use (match_operand 2 "" ""))
6130    (use (reg:PSI FPSCR_REG))
6131    (return)]
6132   "TARGET_SH2"
6133   "braf %0\\n%O2:%#"
6134   [(set_attr "needs_delay_slot" "yes")
6135    (set (attr "fp_mode")
6136         (if_then_else (eq_attr "fpu_single" "yes")
6137                       (const_string "single") (const_string "double")))
6138    (set_attr "type" "jump_ind")])
6139
6140 (define_insn_and_split "sibcall_pcrel"
6141   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
6142          (match_operand 1 "" ""))
6143    (use (reg:PSI FPSCR_REG))
6144    (clobber (match_scratch:SI 2 "=k"))
6145    (return)]
6146   "TARGET_SH2"
6147   "#"
6148   "reload_completed"
6149   [(const_int 0)]
6150   "
6151 {
6152   rtx lab = PATTERN (gen_call_site ());
6153   rtx call_insn;
6154
6155   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
6156   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
6157                                                   lab));
6158   SIBLING_CALL_P (call_insn) = 1;
6159   DONE;
6160 }"
6161   [(set_attr "needs_delay_slot" "yes")
6162    (set (attr "fp_mode")
6163         (if_then_else (eq_attr "fpu_single" "yes")
6164                       (const_string "single") (const_string "double")))
6165    (set_attr "type" "jump_ind")])
6166
6167 (define_insn "sibcall_compact"
6168   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
6169          (match_operand 1 "" ""))
6170    (return)
6171    (use (match_operand:SI 2 "register_operand" "z,x"))
6172    (use (reg:SI R1_REG))
6173    (use (reg:PSI FPSCR_REG))
6174    ;; We want to make sure the `x' above will only match MACH_REG
6175    ;; because sibcall_epilogue may clobber MACL_REG.
6176    (clobber (reg:SI MACL_REG))]
6177   "TARGET_SHCOMPACT"
6178   "@
6179         jmp     @%0%#
6180         jmp     @%0\\n  sts     %2, r0"
6181   [(set_attr "needs_delay_slot" "yes,no")
6182    (set_attr "length" "2,4")
6183    (set (attr "fp_mode") (const_string "single"))
6184    (set_attr "type" "jump_ind")])
6185
6186 (define_insn "sibcall_media"
6187   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
6188          (match_operand 1 "" ""))
6189    (use (reg:SI PR_MEDIA_REG))
6190    (return)]
6191   "TARGET_SHMEDIA"
6192   "blink        %0, r63"
6193   [(set_attr "type" "jump_media")])
6194
6195 (define_expand "sibcall"
6196   [(parallel
6197     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
6198            (match_operand 1 "" ""))
6199      (match_operand 2 "" "")
6200      (use (reg:PSI FPSCR_REG))
6201      (return)])]
6202   ""
6203   "
6204 {
6205   if (TARGET_SHMEDIA)
6206     {
6207       operands[0] = XEXP (operands[0], 0);
6208       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
6209         {
6210           if (! SYMBOL_REF_LOCAL_P (operands[0]))
6211             {
6212               rtx reg = gen_reg_rtx (Pmode);
6213
6214               /* We must not use GOTPLT for sibcalls, because PIC_REG
6215                  must be restored before the PLT code gets to run.  */
6216               emit_insn (gen_symGOT2reg (reg, operands[0]));
6217               operands[0] = reg;
6218             }
6219           else
6220             {
6221               operands[0] = gen_sym2PIC (operands[0]);
6222               PUT_MODE (operands[0], Pmode);
6223             }
6224         }
6225       if (GET_MODE (operands[0]) == SImode)
6226         {
6227           if (GET_CODE (operands[0]) == REG)
6228             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6229           else if (GET_CODE (operands[0]) == SUBREG)
6230             {
6231               operands[0] = SUBREG_REG (operands[0]);
6232               if (GET_MODE (operands[0]) != DImode)
6233                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6234             }
6235           else
6236             {
6237               operands[0] = shallow_copy_rtx (operands[0]);
6238               PUT_MODE (operands[0], DImode);
6239             }
6240         }
6241       if (! target_reg_operand (operands[0], DImode))
6242         operands[0] = copy_to_mode_reg (DImode, operands[0]);
6243       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
6244       DONE;
6245     }
6246   else if (TARGET_SHCOMPACT && operands[2]
6247            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
6248     {
6249       rtx cookie_rtx = operands[2];
6250       long cookie = INTVAL (cookie_rtx);
6251       rtx func = XEXP (operands[0], 0);
6252       rtx mach, r1;
6253
6254       if (flag_pic)
6255         {
6256           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
6257             {
6258               rtx reg = gen_reg_rtx (Pmode);
6259
6260               emit_insn (gen_symGOT2reg (reg, func));
6261               func = reg;
6262             }
6263           else
6264             func = legitimize_pic_address (func, Pmode, 0);
6265         }
6266
6267       /* FIXME: if we could tell whether all argument registers are
6268          already taken, we could decide whether to force the use of
6269          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
6270          simple way to tell.  We could use the CALL_COOKIE, but we
6271          can't currently tell a register used for regular argument
6272          passing from one that is unused.  If we leave it up to reload
6273          to decide which register to use, it seems to always choose
6274          R0_REG, which leaves no available registers in SIBCALL_REGS
6275          to hold the address of the trampoline.  */
6276       mach = gen_rtx_REG (SImode, MACH_REG);
6277       r1 = gen_rtx_REG (SImode, R1_REG);
6278
6279       /* Since such a call function may use all call-clobbered
6280          registers, we force a mode switch earlier, so that we don't
6281          run out of registers when adjusting fpscr for the call.  */
6282       emit_insn (gen_force_mode_for_call ());
6283
6284       operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6285       if (flag_pic)
6286         {
6287           rtx reg = gen_reg_rtx (Pmode);
6288
6289           emit_insn (gen_symGOT2reg (reg, operands[0]));
6290           operands[0] = reg;
6291         }
6292       operands[0] = force_reg (SImode, operands[0]);
6293
6294       /* We don't need a return trampoline, since the callee will
6295          return directly to the upper caller.  */
6296       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6297         {
6298           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
6299           cookie_rtx = GEN_INT (cookie);
6300         }
6301
6302       emit_move_insn (mach, func);
6303       emit_move_insn (r1, cookie_rtx);
6304
6305       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
6306       DONE;
6307     }
6308   else if (TARGET_SHCOMPACT && flag_pic
6309            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6310            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
6311     {
6312       rtx reg = gen_reg_rtx (Pmode);
6313
6314       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
6315       XEXP (operands[0], 0) = reg;
6316     }
6317   if (flag_pic && TARGET_SH2
6318       && GET_CODE (operands[0]) == MEM
6319       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6320       /* The PLT needs the PIC register, but the epilogue would have
6321          to restore it, so we can only use PC-relative PIC calls for
6322          static functions.  */
6323       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
6324     {
6325       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
6326       DONE;
6327     }
6328   else
6329     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
6330
6331   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
6332   DONE;
6333 }")
6334
6335 (define_expand "sibcall_value"
6336   [(set (match_operand 0 "" "")
6337         (call (match_operand 1 "" "")
6338               (match_operand 2 "" "")))
6339    (match_operand 3 "" "")]
6340   ""
6341   "
6342 {
6343   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
6344   DONE;
6345 }")
6346
6347 (define_insn "call_value_pop_compact"
6348   [(set (match_operand 0 "" "=rf")
6349         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6350               (match_operand 2 "" "")))
6351    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6352                                  (match_operand 4 "immediate_operand" "n")))
6353    (match_operand 3 "immediate_operand" "n")
6354    (use (reg:SI R0_REG))
6355    (use (reg:SI R1_REG))
6356    (use (reg:PSI FPSCR_REG))
6357    (clobber (reg:SI PR_REG))]
6358   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6359   "jsr  @%1%#"
6360   [(set_attr "type" "call")
6361    (set (attr "fp_mode")
6362         (if_then_else (eq_attr "fpu_single" "yes")
6363                       (const_string "single") (const_string "double")))
6364    (set_attr "needs_delay_slot" "yes")])
6365
6366 (define_insn "call_value_pop_compact_rettramp"
6367   [(set (match_operand 0 "" "=rf")
6368         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6369               (match_operand 2 "" "")))
6370    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6371                                  (match_operand 4 "immediate_operand" "n")))
6372    (match_operand 3 "immediate_operand" "n")
6373    (use (reg:SI R0_REG))
6374    (use (reg:SI R1_REG))
6375    (use (reg:PSI FPSCR_REG))
6376    (clobber (reg:SI R10_REG))
6377    (clobber (reg:SI PR_REG))]
6378   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6379   "jsr  @%1%#"
6380   [(set_attr "type" "call")
6381    (set (attr "fp_mode")
6382         (if_then_else (eq_attr "fpu_single" "yes")
6383                       (const_string "single") (const_string "double")))
6384    (set_attr "needs_delay_slot" "yes")])
6385
6386 (define_expand "call_value_pop"
6387   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
6388                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
6389                                  (match_operand 2 "" "")))
6390               (match_operand 3 "" "")
6391               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6392                                             (match_operand 4 "" "")))])]
6393   "TARGET_SHCOMPACT"
6394   "
6395 {
6396   if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
6397     {
6398       rtx cookie_rtx = operands[3];
6399       long cookie = INTVAL (cookie_rtx);
6400       rtx func = XEXP (operands[1], 0);
6401       rtx r0, r1;
6402
6403       if (flag_pic)
6404         {
6405           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
6406             {
6407               rtx reg = gen_reg_rtx (Pmode);
6408
6409               emit_insn (gen_symGOTPLT2reg (reg, func));
6410               func = reg;
6411             }
6412           else
6413             func = legitimize_pic_address (func, Pmode, 0);
6414         }
6415
6416       r0 = gen_rtx_REG (SImode, R0_REG);
6417       r1 = gen_rtx_REG (SImode, R1_REG);
6418
6419       /* Since such a call function may use all call-clobbered
6420          registers, we force a mode switch earlier, so that we don't
6421          run out of registers when adjusting fpscr for the call.  */
6422       emit_insn (gen_force_mode_for_call ());
6423
6424       operands[1] = function_symbol (\"__GCC_shcompact_call_trampoline\");
6425       if (flag_pic)
6426         {
6427           rtx reg = gen_reg_rtx (Pmode);
6428
6429           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6430           operands[1] = reg;
6431         }
6432       operands[1] = force_reg (SImode, operands[1]);
6433
6434       emit_move_insn (r0, func);
6435       emit_move_insn (r1, cookie_rtx);
6436
6437       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6438         emit_call_insn (gen_call_value_pop_compact_rettramp
6439                         (operands[0], operands[1], operands[2],
6440                          operands[3], operands[4]));
6441       else
6442         emit_call_insn (gen_call_value_pop_compact
6443                         (operands[0], operands[1], operands[2],
6444                          operands[3], operands[4]));
6445
6446       DONE;
6447     }
6448
6449   abort ();
6450 }")
6451
6452 (define_expand "sibcall_epilogue"
6453   [(return)]
6454   ""
6455   "
6456 {
6457   sh_expand_epilogue (1);
6458   if (TARGET_SHCOMPACT)
6459     {
6460       rtx insn, set;
6461
6462       /* If epilogue clobbers r0, preserve it in macl.  */
6463       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6464         if ((set = single_set (insn))
6465             && GET_CODE (SET_DEST (set)) == REG
6466             && REGNO (SET_DEST (set)) == R0_REG)
6467           {
6468             rtx r0 = gen_rtx_REG (SImode, R0_REG);
6469             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
6470             rtx i;
6471
6472             /* We can't tell at this point whether the sibcall is a
6473                sibcall_compact and, if it is, whether it uses r0 or
6474                mach as operand 2, so let the instructions that
6475                preserve r0 be optimized away if r0 turns out to be
6476                dead.  */
6477             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
6478             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6479                                                REG_NOTES (i));
6480             i = emit_move_insn (r0, tmp);
6481             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6482                                                REG_NOTES (i));
6483             break;
6484           }
6485     }
6486   DONE;
6487 }")
6488
6489 (define_insn "indirect_jump_compact"
6490   [(set (pc)
6491         (match_operand:SI 0 "arith_reg_operand" "r"))]
6492   "TARGET_SH1"
6493   "jmp  @%0%#"
6494   [(set_attr "needs_delay_slot" "yes")
6495    (set_attr "type" "jump_ind")])
6496
6497 (define_expand "indirect_jump"
6498   [(set (pc)
6499         (match_operand 0 "register_operand" ""))]
6500   ""
6501   "
6502 {
6503   if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode)
6504     operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6505 }")
6506
6507 ;; The use of operand 1 / 2 helps us distinguish case table jumps
6508 ;; which can be present in structured code from indirect jumps which can not
6509 ;; be present in structured code.  This allows -fprofile-arcs to work.
6510
6511 ;; For SH1 processors.
6512 (define_insn "casesi_jump_1"
6513   [(set (pc)
6514         (match_operand:SI 0 "register_operand" "r"))
6515    (use (label_ref (match_operand 1 "" "")))]
6516   "TARGET_SH1"
6517   "jmp  @%0%#"
6518   [(set_attr "needs_delay_slot" "yes")
6519    (set_attr "type" "jump_ind")])
6520
6521 ;; For all later processors.
6522 (define_insn "casesi_jump_2"
6523   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
6524                       (label_ref (match_operand 1 "" ""))))
6525    (use (label_ref (match_operand 2 "" "")))]
6526   "TARGET_SH2
6527    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
6528   "braf %0%#"
6529   [(set_attr "needs_delay_slot" "yes")
6530    (set_attr "type" "jump_ind")])
6531
6532 (define_insn "casesi_jump_media"
6533   [(set (pc) (match_operand:DI 0 "target_reg_operand" "b"))
6534    (use (label_ref (match_operand 1 "" "")))]
6535   "TARGET_SHMEDIA"
6536   "blink        %0, r63"
6537   [(set_attr "type" "jump_media")])
6538
6539 ;; Call subroutine returning any type.
6540 ;; ??? This probably doesn't work.
6541
6542 (define_expand "untyped_call"
6543   [(parallel [(call (match_operand 0 "" "")
6544                     (const_int 0))
6545               (match_operand 1 "" "")
6546               (match_operand 2 "" "")])]
6547   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
6548   "
6549 {
6550   int i;
6551
6552   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
6553
6554   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6555     {
6556       rtx set = XVECEXP (operands[2], 0, i);
6557       emit_move_insn (SET_DEST (set), SET_SRC (set));
6558     }
6559
6560   /* The optimizer does not know that the call sets the function value
6561      registers we stored in the result block.  We avoid problems by
6562      claiming that all hard registers are used and clobbered at this
6563      point.  */
6564   emit_insn (gen_blockage ());
6565
6566   DONE;
6567 }")
6568 \f
6569 ;; ------------------------------------------------------------------------
6570 ;; Misc insns
6571 ;; ------------------------------------------------------------------------
6572
6573 (define_insn "dect"
6574   [(set (reg:SI T_REG)
6575         (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1)))
6576    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
6577   "TARGET_SH2"
6578   "dt   %0"
6579   [(set_attr "type" "arith")])
6580
6581 (define_insn "nop"
6582   [(const_int 0)]
6583   ""
6584   "nop")
6585
6586 ;; Load address of a label. This is only generated by the casesi expand,
6587 ;; and by machine_dependent_reorg (fixing up fp moves).
6588 ;; This must use unspec, because this only works for labels that are
6589 ;; within range,
6590
6591 (define_insn "mova"
6592   [(set (reg:SI R0_REG)
6593         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
6594   "TARGET_SH1"
6595   "mova %O0,r0"
6596   [(set_attr "in_delay_slot" "no")
6597    (set_attr "type" "arith")])
6598
6599 ;; machine_dependent_reorg will make this a `mova'.
6600 (define_insn "mova_const"
6601   [(set (reg:SI R0_REG)
6602         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
6603   "TARGET_SH1"
6604   "#"
6605   [(set_attr "in_delay_slot" "no")
6606    (set_attr "type" "arith")])
6607
6608 (define_expand "GOTaddr2picreg"
6609   [(set (reg:SI R0_REG)
6610         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
6611                    UNSPEC_MOVA))
6612    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
6613    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6614   "" "
6615 {
6616   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
6617   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
6618
6619   if (TARGET_SH5)
6620     operands[1] = gen_datalabel_ref (operands[1]);
6621
6622   if (TARGET_SHMEDIA)
6623     {
6624       rtx tr = gen_rtx_REG (DImode, TR0_REG);
6625       rtx dipic = operands[0];
6626       rtx lab = PATTERN (gen_call_site ());
6627       rtx insn, equiv;
6628
6629       equiv = operands[1];
6630       operands[1] = gen_rtx_MINUS (DImode,
6631                                    operands[1],
6632                                    gen_rtx_CONST
6633                                    (DImode,
6634                                     gen_rtx_MINUS (DImode,
6635                                                    gen_rtx_CONST (DImode,
6636                                                                   lab),
6637                                                    pc_rtx)));
6638       operands[1] = gen_sym2PIC (operands[1]);
6639       PUT_MODE (operands[1], DImode);
6640
6641       if (GET_MODE (dipic) != DImode)
6642         dipic = gen_rtx_SUBREG (DImode, dipic, 0);
6643
6644       if (TARGET_SHMEDIA64)
6645         emit_insn (gen_movdi_const (dipic, operands[1]));
6646       else
6647         emit_insn (gen_movdi_const_32bit (dipic, operands[1]));
6648
6649       emit_insn (gen_ptrel (tr, dipic, lab));
6650
6651       if (GET_MODE (operands[0]) != GET_MODE (tr))
6652         tr = gen_lowpart (GET_MODE (operands[0]), tr);
6653
6654       insn = emit_move_insn (operands[0], tr);
6655
6656       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
6657                                             REG_NOTES (insn));
6658
6659       DONE;
6660     }
6661 }
6662 ")
6663
6664 (define_insn "*ptb"
6665   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6666         (const:DI (unspec:DI [(match_operand:DI 1 "" "Csy")]
6667                              UNSPEC_DATALABEL)))]
6668   "TARGET_SHMEDIA && flag_pic
6669    && EXTRA_CONSTRAINT_Csy (operands[1])"
6670   "ptb/u        datalabel %1, %0"
6671   [(set_attr "type" "pt_media")
6672    (set_attr "length" "*")])
6673
6674 (define_insn "ptrel"
6675   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6676         (plus:DI (match_operand:DI 1 "register_operand" "r")
6677               (pc)))
6678    (match_operand:DI 2 "" "")]
6679   "TARGET_SHMEDIA"
6680   "%O2: ptrel/u %1, %0"
6681   [(set_attr "type" "ptabs_media")])
6682
6683 (define_expand "builtin_setjmp_receiver"
6684   [(match_operand 0 "" "")]
6685   "flag_pic"
6686   "
6687 {
6688   emit_insn (gen_GOTaddr2picreg ());
6689   DONE;
6690 }")
6691
6692 (define_expand "call_site"
6693   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
6694   "TARGET_SH1"
6695   "
6696 {
6697   static HOST_WIDE_INT i = 0;
6698   operands[0] = GEN_INT (i);
6699   i++;
6700 }")
6701
6702 (define_expand "sym_label2reg"
6703   [(set (match_operand:SI 0 "" "")
6704         (const:SI (minus:SI
6705                    (const:SI
6706                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
6707                    (const:SI
6708                     (plus:SI
6709                      (match_operand:SI 2 "" "")
6710                      (const_int 2))))))]
6711   "TARGET_SH1" "")
6712
6713 (define_expand "symGOT_load"
6714   [(set (match_dup 2) (match_operand 1 "" ""))
6715    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
6716    (set (match_operand 0 "" "") (mem (match_dup 3)))]
6717   ""
6718   "
6719 {
6720   rtx insn;
6721
6722   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6723   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6724
6725   if (TARGET_SHMEDIA)
6726     {
6727       rtx reg = operands[2];
6728
6729       if (GET_MODE (reg) != DImode)
6730         reg = gen_rtx_SUBREG (DImode, reg, 0);
6731
6732       if (flag_pic > 1)
6733         emit_insn (gen_movdi_const_32bit (reg, operands[1]));
6734       else
6735         emit_insn (gen_movdi_const_16bit (reg, operands[1]));
6736     }
6737   else
6738     emit_move_insn (operands[2], operands[1]);
6739
6740   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
6741                                              operands[2],
6742                                              gen_rtx_REG (Pmode, PIC_REG)));
6743
6744   insn = emit_move_insn (operands[0], gen_rtx_MEM (Pmode, operands[3]));
6745
6746   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
6747                                                                   0), 0, 0),
6748                                         REG_NOTES (insn));
6749
6750   DONE;
6751 }")
6752
6753 (define_expand "sym2GOT"
6754   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
6755   ""
6756   "")
6757
6758 (define_expand "symGOT2reg"
6759   [(match_operand 0 "" "") (match_operand 1 "" "")]
6760   ""
6761   "
6762 {
6763   rtx gotsym, insn;
6764
6765   gotsym = gen_sym2GOT (operands[1]);
6766   PUT_MODE (gotsym, Pmode);
6767   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
6768
6769   RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
6770
6771   DONE;
6772 }")
6773
6774 (define_expand "sym2GOTPLT"
6775   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTPLT))]
6776   ""
6777   "")
6778
6779 (define_expand "symGOTPLT2reg"
6780   [(match_operand 0 "" "") (match_operand 1 "" "")]
6781   ""
6782   "
6783 {
6784   emit_insn (gen_symGOT_load (operands[0], gen_sym2GOTPLT (operands[1])));
6785   DONE;
6786 }")
6787
6788 (define_expand "sym2GOTOFF"
6789   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
6790   ""
6791   "")
6792
6793 (define_expand "symGOTOFF2reg"
6794   [(match_operand 0 "" "") (match_operand 1 "" "")]
6795   ""
6796   "
6797 {
6798   rtx gotoffsym, insn;
6799   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6800
6801   gotoffsym = gen_sym2GOTOFF (operands[1]);
6802   PUT_MODE (gotoffsym, Pmode);
6803   emit_move_insn (t, gotoffsym);
6804   insn = emit_move_insn (operands[0],
6805                          gen_rtx_PLUS (Pmode, t,
6806                                        gen_rtx_REG (Pmode, PIC_REG)));
6807
6808   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
6809                                         REG_NOTES (insn));
6810
6811   DONE;
6812 }")
6813
6814 (define_expand "symPLT_label2reg"
6815   [(set (match_operand:SI 0 "" "")
6816         (const:SI (minus:SI
6817                    (const:SI
6818                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
6819                    (const:SI
6820                     (minus:SI
6821                      (const:SI (plus:SI
6822                                 (match_operand:SI 2 "" "")
6823                                 (const_int 2)))
6824                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
6825    ;; Even though the PIC register is not really used by the call
6826    ;; sequence in which this is expanded, the PLT code assumes the PIC
6827    ;; register is set, so we must not skip its initialization.  Since
6828    ;; we only use this expand as part of calling sequences, and never
6829    ;; to take the address of a function, this is the best point to
6830    ;; insert the (use).  Using the PLT to take the address of a
6831    ;; function would be wrong, not only because the PLT entry could
6832    ;; then be called from a function that doesn't initialize the PIC
6833    ;; register to the proper GOT, but also because pointers to the
6834    ;; same function might not compare equal, should they be set by
6835    ;; different shared libraries.
6836    (use (reg:SI PIC_REG))]
6837   "TARGET_SH1"
6838   "")
6839
6840 (define_expand "sym2PIC"
6841   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
6842   ""
6843   "")
6844
6845 ;; TLS code generation.
6846 ;; ??? this should be a define_insn_and_split
6847 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
6848 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
6849 ;; for details.
6850
6851 (define_insn "tls_global_dynamic"
6852   [(set (match_operand:SI 0 "register_operand" "=&z")
6853         (call (unspec:SI [(match_operand:SI 1 "" "")]
6854                           UNSPEC_TLSGD)
6855               (const_int 0)))
6856    (use (reg:PSI FPSCR_REG))
6857    (use (reg:SI PIC_REG))
6858    (clobber (reg:SI PR_REG))
6859    (clobber (scratch:SI))]
6860   "TARGET_SH1"
6861   "*
6862 {
6863   return \"\\
6864 mov.l\\t1f,r4\\n\\
6865 \\tmova\\t2f,r0\\n\\
6866 \\tmov.l\\t2f,r1\\n\\
6867 \\tadd\\tr0,r1\\n\\
6868 \\tjsr\\t@r1\\n\\
6869 \\tadd\\tr12,r4\\n\\
6870 \\tbra\\t3f\\n\\
6871 \\tnop\\n\\
6872 \\t.align\\t2\\n\\
6873 1:\\t.long\\t%a1@TLSGD\\n\\
6874 2:\\t.long\\t__tls_get_addr@PLT\\n\\
6875 3:\";
6876 }"
6877   [(set_attr "type" "tls_load")
6878    (set_attr "length" "26")])
6879
6880 (define_insn "tls_local_dynamic"
6881   [(set (match_operand:SI 0 "register_operand" "=&z")
6882         (call (unspec:SI [(match_operand:SI 1 "" "")]
6883                           UNSPEC_TLSLDM)
6884               (const_int 0)))
6885    (use (reg:PSI FPSCR_REG))
6886    (use (reg:SI PIC_REG))
6887    (clobber (reg:SI PR_REG))
6888    (clobber (scratch:SI))]
6889   "TARGET_SH1"
6890   "*
6891 {
6892   return \"\\
6893 mov.l\\t1f,r4\\n\\
6894 \\tmova\\t2f,r0\\n\\
6895 \\tmov.l\\t2f,r1\\n\\
6896 \\tadd\\tr0,r1\\n\\
6897 \\tjsr\\t@r1\\n\\
6898 \\tadd\\tr12,r4\\n\\
6899 \\tbra\\t3f\\n\\
6900 \\tnop\\n\\
6901 \\t.align\\t2\\n\\
6902 1:\\t.long\\t%a1@TLSLDM\\n\\
6903 2:\\t.long\\t__tls_get_addr@PLT\\n\\
6904 3:\";
6905 }"
6906   [(set_attr "type" "tls_load")
6907    (set_attr "length" "26")])
6908
6909 (define_expand "sym2DTPOFF"
6910   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
6911   ""
6912   "")
6913
6914 (define_expand "symDTPOFF2reg"
6915   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
6916   ""
6917   "
6918 {
6919   rtx dtpoffsym, insn;
6920   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6921
6922   dtpoffsym = gen_sym2DTPOFF (operands[1]);
6923   PUT_MODE (dtpoffsym, Pmode);
6924   emit_move_insn (t, dtpoffsym);
6925   insn = emit_move_insn (operands[0],
6926                          gen_rtx_PLUS (Pmode, t, operands[2]));
6927   DONE;
6928 }")
6929
6930 (define_expand "sym2GOTTPOFF"
6931   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
6932   ""
6933   "")
6934
6935 (define_insn "tls_initial_exec"
6936   [(set (match_operand:SI 0 "register_operand" "=&r")
6937         (unspec:SI [(match_operand:SI 1 "" "")]
6938                     UNSPEC_TLSIE))
6939    (use (reg:SI GBR_REG))
6940    (use (reg:SI PIC_REG))
6941    (clobber (reg:SI R0_REG))]
6942   ""
6943   "*
6944 {
6945   return \"\\
6946 mov.l\\t1f,r0\\n\\
6947 \\tstc\\tgbr,%0\\n\\
6948 \\tmov.l\\t@(r0,r12),r0\\n\\
6949 \\tbra\\t2f\\n\\
6950 \\tadd\\tr0,%0\\n\\
6951 \\t.align\\t2\\n\\
6952 1:\\t.long\\t%a1\\n\\
6953 2:\";
6954 }"
6955   [(set_attr "type" "tls_load")
6956    (set_attr "length" "16")])
6957
6958 (define_expand "sym2TPOFF"
6959   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
6960   ""
6961   "")
6962
6963 (define_expand "symTPOFF2reg"
6964   [(match_operand 0 "" "") (match_operand 1 "" "")]
6965   ""
6966   "
6967 {
6968   rtx tpoffsym, insn;
6969
6970   tpoffsym = gen_sym2TPOFF (operands[1]);
6971   PUT_MODE (tpoffsym, Pmode);
6972   insn = emit_move_insn (operands[0], tpoffsym);
6973   DONE;
6974 }")
6975
6976 (define_insn "load_gbr"
6977   [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
6978    (use (reg:SI GBR_REG))]
6979   ""
6980   "stc  gbr,%0"
6981   [(set_attr "type" "tls_load")])
6982
6983 ;; case instruction for switch statements.
6984
6985 ;; Operand 0 is index
6986 ;; operand 1 is the minimum bound
6987 ;; operand 2 is the maximum bound - minimum bound + 1
6988 ;; operand 3 is CODE_LABEL for the table;
6989 ;; operand 4 is the CODE_LABEL to go to if index out of range.
6990
6991 (define_expand "casesi"
6992   [(match_operand:SI 0 "arith_reg_operand" "")
6993    (match_operand:SI 1 "arith_reg_operand" "")
6994    (match_operand:SI 2 "arith_reg_operand" "")
6995    (match_operand 3 "" "") (match_operand 4 "" "")]
6996   ""
6997   "
6998 {
6999   rtx reg = gen_reg_rtx (SImode);
7000   rtx reg2 = gen_reg_rtx (SImode);
7001   if (TARGET_SHMEDIA)
7002     {
7003       rtx reg = gen_reg_rtx (DImode);
7004       rtx reg2 = gen_reg_rtx (DImode);
7005       rtx reg3 = gen_reg_rtx (DImode);
7006       rtx reg4 = gen_reg_rtx (DImode);
7007       rtx reg5 = gen_reg_rtx (DImode);
7008
7009       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
7010       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
7011       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
7012
7013       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
7014       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
7015       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
7016       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
7017       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
7018                                                (DImode, operands[3])));
7019       emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3]));
7020       emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4));
7021       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
7022       emit_barrier ();
7023       DONE;
7024     }
7025   operands[1] = copy_to_mode_reg (SImode, operands[1]);
7026   operands[2] = copy_to_mode_reg (SImode, operands[2]);
7027   /* If optimizing, casesi_worker depends on the mode of the instruction
7028      before label it 'uses' - operands[3].  */
7029   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
7030                            reg));
7031   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
7032   if (TARGET_SH2)
7033     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
7034   else
7035     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
7036   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
7037      operands[3], but to lab.  We will fix this up in
7038      machine_dependent_reorg.  */
7039   emit_barrier ();
7040   DONE;
7041 }")
7042
7043 (define_expand "casesi_0"
7044   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
7045    (set (match_dup 4) (minus:SI (match_dup 4)
7046                                 (match_operand:SI 1 "arith_operand" "")))
7047    (set (reg:SI T_REG)
7048         (gtu:SI (match_dup 4)
7049                 (match_operand:SI 2 "arith_reg_operand" "")))
7050    (set (pc)
7051         (if_then_else (ne (reg:SI T_REG)
7052                           (const_int 0))
7053                       (label_ref (match_operand 3 "" ""))
7054                       (pc)))]
7055   "TARGET_SH1"
7056   "")
7057
7058 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
7059 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
7060 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
7061
7062 (define_insn "casesi_worker_0"
7063   [(set (match_operand:SI 0 "register_operand" "=r,r")
7064         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
7065                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7066    (clobber (match_scratch:SI 3 "=X,1"))
7067    (clobber (match_scratch:SI 4 "=&z,z"))]
7068   "TARGET_SH1"
7069   "#")
7070
7071 (define_split
7072   [(set (match_operand:SI 0 "register_operand" "")
7073         (unspec:SI [(match_operand:SI 1 "register_operand" "")
7074                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7075    (clobber (match_scratch:SI 3 ""))
7076    (clobber (match_scratch:SI 4 ""))]
7077   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
7078   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
7079    (parallel [(set (match_dup 0)
7080               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
7081                           (label_ref (match_dup 2))] UNSPEC_CASESI))
7082               (clobber (match_dup 3))])
7083    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
7084   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
7085
7086 (define_split
7087   [(set (match_operand:SI 0 "register_operand" "")
7088         (unspec:SI [(match_operand:SI 1 "register_operand" "")
7089                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7090    (clobber (match_scratch:SI 3 ""))
7091    (clobber (match_scratch:SI 4 ""))]
7092   "TARGET_SH2 && reload_completed"
7093   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
7094    (parallel [(set (match_dup 0)
7095               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
7096                           (label_ref (match_dup 2))] UNSPEC_CASESI))
7097               (clobber (match_dup 3))])]
7098   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
7099
7100 (define_insn "casesi_worker_1"
7101   [(set (match_operand:SI 0 "register_operand" "=r,r")
7102         (unspec:SI [(reg:SI R0_REG)
7103                     (match_operand:SI 1 "register_operand" "0,r")
7104                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
7105    (clobber (match_scratch:SI 3 "=X,1"))]
7106   "TARGET_SH1"
7107   "*
7108 {
7109   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
7110
7111   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
7112     abort ();
7113
7114   switch (GET_MODE (diff_vec))
7115     {
7116     case SImode:
7117       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
7118     case HImode:
7119       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
7120     case QImode:
7121       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7122         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
7123       return \"mov.b    @(r0,%1),%0\";
7124     default:
7125       abort ();
7126     }
7127 }"
7128   [(set_attr "length" "4")])
7129
7130 (define_insn "casesi_worker_2"
7131   [(set (match_operand:SI 0 "register_operand" "=r,r")
7132         (unspec:SI [(reg:SI R0_REG)
7133                     (match_operand:SI 1 "register_operand" "0,r")
7134                     (label_ref (match_operand 2 "" ""))
7135                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
7136    (clobber (match_operand:SI 4 "" "=X,1"))]
7137   "TARGET_SH2 && reload_completed && flag_pic"
7138   "*
7139 {
7140   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
7141   const char *load;
7142
7143   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
7144     abort ();
7145
7146   switch (GET_MODE (diff_vec))
7147     {
7148     case SImode:
7149       output_asm_insn (\"shll2    %1\", operands);
7150       load = \"mov.l    @(r0,%1),%0\"; break;
7151     case HImode:
7152       output_asm_insn (\"add    %1,%1\", operands);
7153       load = \"mov.w    @(r0,%1),%0\"; break;
7154     case QImode:
7155       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7156         load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
7157       else
7158         load = \"mov.b  @(r0,%1),%0\";
7159       break;
7160     default:
7161       abort ();
7162     }
7163   output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
7164   return load;
7165 }"
7166   [(set_attr "length" "8")])
7167
7168 (define_insn "casesi_shift_media"
7169   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7170         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
7171                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
7172                     UNSPEC_CASESI)))]
7173   "TARGET_SHMEDIA"
7174   "*
7175 {
7176   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
7177
7178   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
7179     abort ();
7180
7181   switch (GET_MODE (diff_vec))
7182     {
7183     case SImode:
7184       return \"shlli    %1, 2, %0\";
7185     case HImode:
7186       return \"shlli    %1, 1, %0\";
7187     case QImode:
7188       if (rtx_equal_p (operands[0], operands[1]))
7189         return \"\";
7190       return \"add      %1, r63, %0\";
7191     default:
7192       abort ();
7193     }
7194 }"
7195   [(set_attr "type" "arith_media")])
7196
7197 (define_insn "casesi_load_media"
7198   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7199         (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r")
7200                          (match_operand 2 "arith_reg_operand" "r")
7201                          (label_ref:DI (match_operand 3 "" ""))] 2)))]
7202   "TARGET_SHMEDIA"
7203   "*
7204 {
7205   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
7206
7207   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
7208     abort ();
7209
7210   switch (GET_MODE (diff_vec))
7211     {
7212     case SImode:
7213       return \"ldx.l    %1, %2, %0\";
7214     case HImode:
7215 #if 0
7216       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7217         return \"ldx.uw %1, %2, %0\";
7218 #endif
7219       return \"ldx.w    %1, %2, %0\";
7220     case QImode:
7221       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7222         return \"ldx.ub %1, %2, %0\";
7223       return \"ldx.b    %1, %2, %0\";
7224     default:
7225       abort ();
7226     }
7227 }"
7228   [(set_attr "type" "load_media")])
7229
7230 (define_expand "return"
7231   [(return)]
7232   "reload_completed && ! sh_need_epilogue ()"
7233   "
7234 {
7235   if (TARGET_SHMEDIA)
7236     {
7237       emit_jump_insn (gen_return_media ());
7238       DONE;
7239     }
7240
7241   if (TARGET_SHCOMPACT
7242       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
7243     {
7244       emit_jump_insn (gen_shcompact_return_tramp ());
7245       DONE;
7246     }
7247 }")
7248
7249 (define_insn "*return_i"
7250   [(return)]
7251   "TARGET_SH1 && ! (TARGET_SHCOMPACT
7252                     && (current_function_args_info.call_cookie
7253                         & CALL_COOKIE_RET_TRAMP (1)))
7254    && reload_completed"
7255   "%@   %#"
7256   [(set_attr "type" "return")
7257    (set_attr "needs_delay_slot" "yes")])
7258
7259 (define_expand "shcompact_return_tramp"
7260   [(return)]
7261   "TARGET_SHCOMPACT
7262    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7263   "
7264 {
7265   rtx reg = gen_rtx_REG (Pmode, R0_REG);
7266   rtx sym = function_symbol (\"__GCC_shcompact_return_trampoline\");
7267
7268   if (flag_pic)
7269     emit_insn (gen_symGOTPLT2reg (reg, sym));
7270   else
7271     emit_move_insn (reg, sym);
7272
7273   emit_jump_insn (gen_shcompact_return_tramp_i ());
7274   DONE;
7275 }")
7276
7277 (define_insn "shcompact_return_tramp_i"
7278   [(parallel [(return) (use (reg:SI R0_REG))])]
7279   "TARGET_SHCOMPACT
7280    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7281   "jmp  @r0%#"
7282   [(set_attr "type" "jump_ind")
7283    (set_attr "needs_delay_slot" "yes")])
7284
7285 (define_insn "return_media_i"
7286   [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])]
7287   "TARGET_SHMEDIA && reload_completed"
7288   "blink        %0, r63"
7289   [(set_attr "type" "jump_media")])
7290
7291 (define_insn "return_media_rte"
7292   [(return)]
7293   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
7294   "rte"
7295   [(set_attr "type" "jump_media")])
7296
7297 (define_expand "return_media"
7298   [(return)]
7299   "TARGET_SHMEDIA && reload_completed"
7300   "
7301 {
7302   int tr_regno = sh_media_register_for_return ();
7303   rtx tr;
7304
7305   if (current_function_interrupt)
7306     {
7307       emit_jump_insn (gen_return_media_rte ());
7308       DONE;
7309     }
7310   if (tr_regno < 0)
7311     {
7312       rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
7313
7314       if (! call_used_regs[TR0_REG] || fixed_regs[TR0_REG])
7315         abort ();
7316       tr_regno = TR0_REG;
7317       tr = gen_rtx_REG (DImode, tr_regno);
7318       emit_move_insn (tr, r18);
7319     }
7320   else
7321     tr = gen_rtx_REG (DImode, tr_regno);
7322
7323   emit_jump_insn (gen_return_media_i (tr));
7324   DONE;
7325 }")
7326
7327 (define_insn "shcompact_preserve_incoming_args"
7328   [(set (match_operand:SI 0 "register_operand" "+r")
7329         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
7330   "TARGET_SHCOMPACT"
7331   ""
7332   [(set_attr "length" "0")])
7333
7334 (define_insn "shcompact_incoming_args"
7335   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
7336    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
7337    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
7338    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
7339    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
7340    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
7341    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
7342    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
7343    (set (mem:BLK (reg:SI MACL_REG))
7344         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
7345    (use (reg:SI R0_REG))
7346    (clobber (reg:SI R0_REG))
7347    (clobber (reg:SI MACL_REG))
7348    (clobber (reg:SI MACH_REG))
7349    (clobber (reg:SI PR_REG))]
7350   "TARGET_SHCOMPACT"
7351   "jsr  @r0%#"
7352   [(set_attr "needs_delay_slot" "yes")])
7353
7354 (define_insn "shmedia_save_restore_regs_compact"
7355   [(set (reg:SI SP_REG)
7356         (plus:SI (reg:SI SP_REG)
7357                  (match_operand:SI 0 "immediate_operand" "i")))
7358    (use (reg:SI R0_REG))
7359    (clobber (reg:SI PR_REG))]
7360   "TARGET_SHCOMPACT
7361    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
7362        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
7363   "jsr @r0%#"
7364   [(set_attr "needs_delay_slot" "yes")])
7365
7366 (define_expand "prologue"
7367   [(const_int 0)]
7368   ""
7369   "sh_expand_prologue (); DONE;")
7370
7371 (define_expand "epilogue"
7372   [(return)]
7373   ""
7374   "
7375 {
7376   sh_expand_epilogue (0);
7377   emit_jump_insn (gen_return ());
7378   DONE;
7379 }")
7380
7381 (define_expand "eh_return"
7382   [(use (match_operand 0 "register_operand" ""))]
7383   ""
7384 {
7385   rtx ra = operands[0];
7386
7387   if (TARGET_SHMEDIA64)
7388     emit_insn (gen_eh_set_ra_di (ra));
7389   else
7390     emit_insn (gen_eh_set_ra_si (ra));
7391
7392   DONE;
7393 })
7394
7395 ;; Clobber the return address on the stack.  We can't expand this
7396 ;; until we know where it will be put in the stack frame.
7397
7398 (define_insn "eh_set_ra_si"
7399   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
7400    (clobber (match_scratch:SI 1 "=&r"))]
7401   "! TARGET_SHMEDIA64"
7402   "#")
7403
7404 (define_insn "eh_set_ra_di"
7405   [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
7406    (clobber (match_scratch:DI 1 "=&r"))]
7407   "TARGET_SHMEDIA64"
7408   "#")
7409
7410 (define_split
7411   [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
7412    (clobber (match_scratch 1 ""))]
7413   "reload_completed"
7414   [(const_int 0)]
7415   "
7416 {
7417   sh_set_return_address (operands[0], operands[1]);
7418   DONE;
7419 }")
7420
7421 (define_insn "blockage"
7422   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7423   ""
7424   ""
7425   [(set_attr "length" "0")])
7426 \f
7427 ;; ------------------------------------------------------------------------
7428 ;; Scc instructions
7429 ;; ------------------------------------------------------------------------
7430
7431 (define_insn "movt"
7432   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7433         (eq:SI (reg:SI T_REG) (const_int 1)))]
7434   "TARGET_SH1"
7435   "movt %0"
7436   [(set_attr "type" "arith")])
7437
7438 (define_expand "seq"
7439   [(set (match_operand:SI 0 "arith_reg_operand" "")
7440         (match_dup 1))]
7441   ""
7442   "
7443 {
7444   if (TARGET_SHMEDIA)
7445     {
7446       if (GET_MODE (operands[0]) != DImode)
7447         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7448       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7449       if (sh_compare_op1 != const0_rtx)
7450         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7451                                     ? GET_MODE (sh_compare_op0)
7452                                     : GET_MODE (sh_compare_op1),
7453                                     sh_compare_op1);
7454
7455       switch (GET_MODE (sh_compare_op0))
7456         {
7457         case DImode:
7458           emit_insn (gen_cmpeqdi_media (operands[0],
7459                                         sh_compare_op0, sh_compare_op1));
7460           break;
7461
7462         case SFmode:
7463           if (! TARGET_SHMEDIA_FPU)
7464             FAIL;
7465           emit_insn (gen_cmpeqsf_media (operands[0],
7466                                         sh_compare_op0, sh_compare_op1));
7467           break;
7468
7469         case DFmode:
7470           if (! TARGET_SHMEDIA_FPU)
7471             FAIL;
7472           emit_insn (gen_cmpeqdf_media (operands[0],
7473                                         sh_compare_op0, sh_compare_op1));
7474           break;
7475
7476         default:
7477           FAIL;
7478         }
7479       DONE;
7480     }
7481   if (sh_expand_t_scc (EQ, operands[0]))
7482     DONE;
7483   if (! currently_expanding_to_rtl)
7484     FAIL;
7485   operands[1] = prepare_scc_operands (EQ);
7486 }")
7487
7488 (define_expand "slt"
7489   [(set (match_operand:SI 0 "arith_reg_operand" "")
7490         (match_dup 1))]
7491   ""
7492   "
7493 {
7494   if (TARGET_SHMEDIA)
7495     {
7496       if (GET_MODE (operands[0]) != DImode)
7497         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7498       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7499       if (sh_compare_op1 != const0_rtx)
7500         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7501                                     ? GET_MODE (sh_compare_op0)
7502                                     : GET_MODE (sh_compare_op1),
7503                                     sh_compare_op1);
7504
7505       switch (GET_MODE (sh_compare_op0))
7506         {
7507         case DImode:
7508           emit_insn (gen_cmpgtdi_media (operands[0],
7509                                         sh_compare_op1, sh_compare_op0));
7510           break;
7511
7512         case SFmode:
7513           if (! TARGET_SHMEDIA_FPU)
7514             FAIL;
7515           emit_insn (gen_cmpgtsf_media (operands[0],
7516                                         sh_compare_op1, sh_compare_op0));
7517           break;
7518
7519         case DFmode:
7520           if (! TARGET_SHMEDIA_FPU)
7521             FAIL;
7522           emit_insn (gen_cmpgtdf_media (operands[0],
7523                                         sh_compare_op1, sh_compare_op0));
7524           break;
7525
7526         default:
7527           FAIL;
7528         }
7529       DONE;
7530     }
7531   if (! currently_expanding_to_rtl)
7532     FAIL;
7533   operands[1] = prepare_scc_operands (LT);
7534 }")
7535
7536 (define_expand "sle"
7537   [(match_operand:SI 0 "arith_reg_operand" "")]
7538   ""
7539   "
7540 {
7541   rtx tmp = sh_compare_op0;
7542
7543   if (TARGET_SHMEDIA)
7544     {
7545       if (GET_MODE (operands[0]) != DImode)
7546         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7547       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7548       if (sh_compare_op1 != const0_rtx)
7549         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7550                                     ? GET_MODE (sh_compare_op0)
7551                                     : GET_MODE (sh_compare_op1),
7552                                     sh_compare_op1);
7553
7554       switch (GET_MODE (sh_compare_op0))
7555         {
7556         case DImode:
7557           {
7558             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7559
7560             emit_insn (gen_cmpgtdi_media (tmp,
7561                                           sh_compare_op0, sh_compare_op1));
7562             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7563             break;
7564           }
7565
7566         case SFmode:
7567           if (! TARGET_SHMEDIA_FPU)
7568             FAIL;
7569           emit_insn (gen_cmpgesf_media (operands[0],
7570                                         sh_compare_op1, sh_compare_op0));
7571           break;
7572
7573         case DFmode:
7574           if (! TARGET_SHMEDIA_FPU)
7575             FAIL;
7576           emit_insn (gen_cmpgedf_media (operands[0],
7577                                         sh_compare_op1, sh_compare_op0));
7578           break;
7579
7580         default:
7581           FAIL;
7582         }
7583       DONE;
7584     }
7585
7586   sh_compare_op0 = sh_compare_op1;
7587   sh_compare_op1 = tmp;
7588   emit_insn (gen_sge (operands[0]));
7589   DONE;
7590 }")
7591
7592 (define_expand "sgt"
7593   [(set (match_operand:SI 0 "arith_reg_operand" "")
7594         (match_dup 1))]
7595   ""
7596   "
7597 {
7598   if (TARGET_SHMEDIA)
7599     {
7600       if (GET_MODE (operands[0]) != DImode)
7601         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7602       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7603       if (sh_compare_op1 != const0_rtx)
7604         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7605                                     ? GET_MODE (sh_compare_op0)
7606                                     : GET_MODE (sh_compare_op1),
7607                                     sh_compare_op1);
7608
7609       switch (GET_MODE (sh_compare_op0))
7610         {
7611         case DImode:
7612           emit_insn (gen_cmpgtdi_media (operands[0],
7613                                         sh_compare_op0, sh_compare_op1));
7614           break;
7615
7616         case SFmode:
7617           if (! TARGET_SHMEDIA_FPU)
7618             FAIL;
7619           emit_insn (gen_cmpgtsf_media (operands[0],
7620                                         sh_compare_op0, sh_compare_op1));
7621           break;
7622
7623         case DFmode:
7624           if (! TARGET_SHMEDIA_FPU)
7625             FAIL;
7626           emit_insn (gen_cmpgtdf_media (operands[0],
7627                                         sh_compare_op0, sh_compare_op1));
7628           break;
7629
7630         default:
7631           FAIL;
7632         }
7633       DONE;
7634     }
7635   if (! currently_expanding_to_rtl)
7636     FAIL;
7637   operands[1] = prepare_scc_operands (GT);
7638 }")
7639
7640 (define_expand "sge"
7641   [(set (match_operand:SI 0 "arith_reg_operand" "")
7642         (match_dup 1))]
7643   ""
7644   "
7645 {
7646   if (TARGET_SHMEDIA)
7647     {
7648       if (GET_MODE (operands[0]) != DImode)
7649         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7650       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7651       if (sh_compare_op1 != const0_rtx)
7652         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7653                                     ? GET_MODE (sh_compare_op0)
7654                                     : GET_MODE (sh_compare_op1),
7655                                     sh_compare_op1);
7656
7657       switch (GET_MODE (sh_compare_op0))
7658         {
7659         case DImode:
7660           {
7661             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7662
7663             emit_insn (gen_cmpgtdi_media (tmp,
7664                                           sh_compare_op1, sh_compare_op0));
7665             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7666             break;
7667           }
7668
7669         case SFmode:
7670           if (! TARGET_SHMEDIA_FPU)
7671             FAIL;
7672           emit_insn (gen_cmpgesf_media (operands[0],
7673                                         sh_compare_op0, sh_compare_op1));
7674           break;
7675
7676         case DFmode:
7677           if (! TARGET_SHMEDIA_FPU)
7678             FAIL;
7679           emit_insn (gen_cmpgedf_media (operands[0],
7680                                         sh_compare_op0, sh_compare_op1));
7681           break;
7682
7683         default:
7684           FAIL;
7685         }
7686       DONE;
7687     }
7688
7689   if (! currently_expanding_to_rtl)
7690     FAIL;
7691   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7692     {
7693       if (TARGET_IEEE)
7694         {
7695           rtx lab = gen_label_rtx ();
7696           prepare_scc_operands (EQ);
7697           emit_jump_insn (gen_branch_true (lab));
7698           prepare_scc_operands (GT);
7699           emit_label (lab);
7700           emit_insn (gen_movt (operands[0]));
7701         }
7702       else
7703         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
7704       DONE;
7705     }
7706   operands[1] = prepare_scc_operands (GE);
7707 }")
7708
7709 (define_expand "sgtu"
7710   [(set (match_operand:SI 0 "arith_reg_operand" "")
7711         (match_dup 1))]
7712   ""
7713   "
7714 {
7715   if (TARGET_SHMEDIA)
7716     {
7717       if (GET_MODE (operands[0]) != DImode)
7718         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7719       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7720       if (sh_compare_op1 != const0_rtx)
7721         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7722                                     ? GET_MODE (sh_compare_op0)
7723                                     : GET_MODE (sh_compare_op1),
7724                                     sh_compare_op1);
7725
7726       emit_insn (gen_cmpgtudi_media (operands[0],
7727                                      sh_compare_op0, sh_compare_op1));
7728       DONE;
7729     }
7730   if (! currently_expanding_to_rtl)
7731     FAIL;
7732   operands[1] = prepare_scc_operands (GTU);
7733 }")
7734
7735 (define_expand "sltu"
7736   [(set (match_operand:SI 0 "arith_reg_operand" "")
7737         (match_dup 1))]
7738   ""
7739   "
7740 {
7741   if (TARGET_SHMEDIA)
7742     {
7743       if (GET_MODE (operands[0]) != DImode)
7744         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7745       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7746       if (sh_compare_op1 != const0_rtx)
7747         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7748                                     ? GET_MODE (sh_compare_op0)
7749                                     : GET_MODE (sh_compare_op1),
7750                                     sh_compare_op1);
7751
7752       emit_insn (gen_cmpgtudi_media (operands[0],
7753                                      sh_compare_op1, sh_compare_op0));
7754       DONE;
7755     }
7756   if (! currently_expanding_to_rtl)
7757     FAIL;
7758   operands[1] = prepare_scc_operands (LTU);
7759 }")
7760
7761 (define_expand "sleu"
7762   [(set (match_operand:SI 0 "arith_reg_operand" "")
7763         (match_dup 1))]
7764   ""
7765   "
7766 {
7767   if (TARGET_SHMEDIA)
7768     {
7769       rtx tmp;
7770
7771       if (GET_MODE (operands[0]) != DImode)
7772         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7773       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7774       if (sh_compare_op1 != const0_rtx)
7775         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7776                                     ? GET_MODE (sh_compare_op0)
7777                                     : GET_MODE (sh_compare_op1),
7778                                     sh_compare_op1);
7779
7780       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7781
7782       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
7783       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7784
7785       DONE;
7786     }
7787   if (! currently_expanding_to_rtl)
7788     FAIL;
7789   operands[1] = prepare_scc_operands (LEU);
7790 }")
7791
7792 (define_expand "sgeu"
7793   [(set (match_operand:SI 0 "arith_reg_operand" "")
7794         (match_dup 1))]
7795   ""
7796   "
7797 {
7798   if (TARGET_SHMEDIA)
7799     {
7800       rtx tmp;
7801
7802       if (GET_MODE (operands[0]) != DImode)
7803         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7804       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7805       if (sh_compare_op1 != const0_rtx)
7806         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7807                                     ? GET_MODE (sh_compare_op0)
7808                                     : GET_MODE (sh_compare_op1),
7809                                     sh_compare_op1);
7810
7811       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7812
7813       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
7814       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7815
7816       DONE;
7817     }
7818
7819   if (! currently_expanding_to_rtl)
7820     FAIL;
7821   operands[1] = prepare_scc_operands (GEU);
7822 }")
7823
7824 ;; sne moves the complement of the T reg to DEST like this:
7825 ;;      cmp/eq ...
7826 ;;      mov    #-1,temp
7827 ;;      negc   temp,dest
7828 ;;   This is better than xoring compare result with 1 because it does
7829 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
7830 ;;   loop.
7831
7832 (define_expand "sne"
7833   [(set (match_dup 2) (const_int -1))
7834    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
7835                    (neg:SI (plus:SI (match_dup 1)
7836                                     (match_dup 2))))
7837               (set (reg:SI T_REG)
7838                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
7839                           (const_int 0)))])]
7840   ""
7841   "
7842 {
7843   if (TARGET_SHMEDIA)
7844     {
7845       rtx tmp;
7846
7847       if (GET_MODE (operands[0]) != DImode)
7848         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7849
7850       if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode)
7851         FAIL;
7852
7853       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7854       if (sh_compare_op1 != const0_rtx)
7855         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7856                                     ? GET_MODE (sh_compare_op0)
7857                                     : GET_MODE (sh_compare_op1),
7858                                     sh_compare_op1);
7859
7860       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7861
7862       emit_insn (gen_seq (tmp));
7863       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7864
7865       DONE;
7866     }
7867
7868   if (sh_expand_t_scc (NE, operands[0]))
7869     DONE;
7870   if (! currently_expanding_to_rtl)
7871     FAIL;
7872   operands[1] = prepare_scc_operands (EQ);
7873   operands[2] = gen_reg_rtx (SImode);
7874 }")
7875
7876 (define_expand "sunordered"
7877   [(set (match_operand:DI 0 "arith_reg_operand" "")
7878         (unordered:DI (match_dup 1) (match_dup 2)))]
7879   "TARGET_SHMEDIA_FPU"
7880   "
7881 {
7882   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7883   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7884 }")
7885
7886 ;; Use the same trick for FP sle / sge
7887 (define_expand "movnegt"
7888   [(set (match_dup 2) (const_int -1))
7889    (parallel [(set (match_operand 0 "" "")
7890                    (neg:SI (plus:SI (match_dup 1)
7891                                     (match_dup 2))))
7892               (set (reg:SI T_REG)
7893                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
7894                           (const_int 0)))])]
7895   "TARGET_SH1"
7896   "operands[2] = gen_reg_rtx (SImode);")
7897
7898 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
7899 ;; This prevents a regression that occurred when we switched from xor to
7900 ;; mov/neg for sne.
7901
7902 (define_split
7903   [(set (match_operand:SI 0 "arith_reg_operand" "")
7904         (plus:SI (reg:SI T_REG)
7905                  (const_int -1)))]
7906   "TARGET_SH1"
7907   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
7908    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
7909   "")
7910
7911 ;; -------------------------------------------------------------------------
7912 ;; Instructions to cope with inline literal tables
7913 ;; -------------------------------------------------------------------------
7914
7915 ; 2 byte integer in line
7916
7917 (define_insn "consttable_2"
7918  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7919                     (match_operand 1 "" "")]
7920                    UNSPECV_CONST2)]
7921  ""
7922  "*
7923 {
7924   if (operands[1] != const0_rtx)
7925     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
7926   return \"\";
7927 }"
7928  [(set_attr "length" "2")
7929  (set_attr "in_delay_slot" "no")])
7930
7931 ; 4 byte integer in line
7932
7933 (define_insn "consttable_4"
7934  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7935                     (match_operand 1 "" "")]
7936                    UNSPECV_CONST4)]
7937  ""
7938  "*
7939 {
7940   if (operands[1] != const0_rtx)
7941     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
7942   return \"\";
7943 }"
7944  [(set_attr "length" "4")
7945   (set_attr "in_delay_slot" "no")])
7946
7947 ; 8 byte integer in line
7948
7949 (define_insn "consttable_8"
7950  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7951                     (match_operand 1 "" "")]
7952                    UNSPECV_CONST8)]
7953  ""
7954  "*
7955 {
7956   if (operands[1] != const0_rtx)
7957     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
7958   return \"\";
7959 }"
7960  [(set_attr "length" "8")
7961   (set_attr "in_delay_slot" "no")])
7962
7963 ; 4 byte floating point
7964
7965 (define_insn "consttable_sf"
7966  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
7967                     (match_operand 1 "" "")]
7968                    UNSPECV_CONST4)]
7969  ""
7970  "*
7971 {
7972   if (operands[1] != const0_rtx)
7973     {
7974       REAL_VALUE_TYPE d;
7975       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
7976       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
7977     }
7978   return \"\";
7979 }"
7980  [(set_attr "length" "4")
7981   (set_attr "in_delay_slot" "no")])
7982
7983 ; 8 byte floating point
7984
7985 (define_insn "consttable_df"
7986  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
7987                     (match_operand 1 "" "")]
7988                    UNSPECV_CONST8)]
7989  ""
7990  "*
7991 {
7992   if (operands[1] != const0_rtx)
7993     {
7994       REAL_VALUE_TYPE d;
7995       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
7996       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
7997     }
7998   return \"\";
7999 }"
8000  [(set_attr "length" "8")
8001   (set_attr "in_delay_slot" "no")])
8002
8003 ;; Alignment is needed for some constant tables; it may also be added for
8004 ;; Instructions at the start of loops, or after unconditional branches.
8005 ;; ??? We would get more accurate lengths if we did instruction
8006 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
8007 ;; here is too conservative.
8008
8009 ; align to a two byte boundary
8010
8011 (define_expand "align_2"
8012  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
8013  ""
8014  "")
8015
8016 ; align to a four byte boundary
8017 ;; align_4 and align_log are instructions for the starts of loops, or
8018 ;; after unconditional branches, which may take up extra room.
8019
8020 (define_expand "align_4"
8021  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
8022  ""
8023  "")
8024
8025 ; align to a cache line boundary
8026
8027 (define_insn "align_log"
8028  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
8029  ""
8030  ""
8031  [(set_attr "length" "0")
8032   (set_attr "in_delay_slot" "no")])
8033
8034 ; emitted at the end of the literal table, used to emit the
8035 ; 32bit branch labels if needed.
8036
8037 (define_insn "consttable_end"
8038   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
8039   ""
8040   "* return output_jump_label_table ();"
8041   [(set_attr "in_delay_slot" "no")])
8042
8043 ; emitted at the end of the window in the literal table.
8044
8045 (define_insn "consttable_window_end"
8046   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
8047   ""
8048   ""
8049   [(set_attr "length" "0")
8050    (set_attr "in_delay_slot" "no")])
8051
8052 ;; -------------------------------------------------------------------------
8053 ;; Misc
8054 ;; -------------------------------------------------------------------------
8055
8056 ;; String/block move insn.
8057
8058 (define_expand "movmemsi"
8059   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
8060                    (mem:BLK (match_operand:BLK 1 "" "")))
8061               (use (match_operand:SI 2 "nonmemory_operand" ""))
8062               (use (match_operand:SI 3 "immediate_operand" ""))
8063               (clobber (reg:SI PR_REG))
8064               (clobber (reg:SI R4_REG))
8065               (clobber (reg:SI R5_REG))
8066               (clobber (reg:SI R0_REG))])]
8067   "TARGET_SH1 && ! TARGET_SH5"
8068   "
8069 {
8070   if(expand_block_move (operands))
8071      DONE;
8072   else FAIL;
8073 }")
8074
8075 (define_insn "block_move_real"
8076   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8077                    (mem:BLK (reg:SI R5_REG)))
8078               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8079               (clobber (reg:SI PR_REG))
8080               (clobber (reg:SI R0_REG))])]
8081   "TARGET_SH1 && ! TARGET_HARD_SH4"
8082   "jsr  @%0%#"
8083   [(set_attr "type" "sfunc")
8084    (set_attr "needs_delay_slot" "yes")])
8085
8086 (define_insn "block_lump_real"
8087   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8088                    (mem:BLK (reg:SI R5_REG)))
8089               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8090               (use (reg:SI R6_REG))
8091               (clobber (reg:SI PR_REG))
8092               (clobber (reg:SI T_REG))
8093               (clobber (reg:SI R4_REG))
8094               (clobber (reg:SI R5_REG))
8095               (clobber (reg:SI R6_REG))
8096               (clobber (reg:SI R0_REG))])]
8097   "TARGET_SH1 && ! TARGET_HARD_SH4"
8098   "jsr  @%0%#"
8099   [(set_attr "type" "sfunc")
8100    (set_attr "needs_delay_slot" "yes")])
8101
8102 (define_insn "block_move_real_i4"
8103   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8104                    (mem:BLK (reg:SI R5_REG)))
8105               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8106               (clobber (reg:SI PR_REG))
8107               (clobber (reg:SI R0_REG))
8108               (clobber (reg:SI R1_REG))
8109               (clobber (reg:SI R2_REG))])]
8110   "TARGET_HARD_SH4"
8111   "jsr  @%0%#"
8112   [(set_attr "type" "sfunc")
8113    (set_attr "needs_delay_slot" "yes")])
8114
8115 (define_insn "block_lump_real_i4"
8116   [(parallel [(set (mem:BLK (reg:SI R4_REG))
8117                    (mem:BLK (reg:SI R5_REG)))
8118               (use (match_operand:SI 0 "arith_reg_operand" "r"))
8119               (use (reg:SI R6_REG))
8120               (clobber (reg:SI PR_REG))
8121               (clobber (reg:SI T_REG))
8122               (clobber (reg:SI R4_REG))
8123               (clobber (reg:SI R5_REG))
8124               (clobber (reg:SI R6_REG))
8125               (clobber (reg:SI R0_REG))
8126               (clobber (reg:SI R1_REG))
8127               (clobber (reg:SI R2_REG))
8128               (clobber (reg:SI R3_REG))])]
8129   "TARGET_HARD_SH4"
8130   "jsr  @%0%#"
8131   [(set_attr "type" "sfunc")
8132    (set_attr "needs_delay_slot" "yes")])
8133 \f
8134 ;; -------------------------------------------------------------------------
8135 ;; Floating point instructions.
8136 ;; -------------------------------------------------------------------------
8137
8138 ;; ??? All patterns should have a type attribute.
8139
8140 (define_expand "fpu_switch0"
8141   [(set (match_operand:SI 0 "" "") (match_dup 2))
8142    (set (match_dup 1) (mem:PSI (match_dup 0)))]
8143   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8144   "
8145 {
8146   operands[1] = get_fpscr_rtx ();
8147   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
8148   if (flag_pic)
8149     operands[2] = legitimize_pic_address (operands[2], SImode,
8150                                           no_new_pseudos ? operands[0] : 0);
8151 }")
8152
8153 (define_expand "fpu_switch1"
8154   [(set (match_operand:SI 0 "" "") (match_dup 2))
8155    (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4)))
8156    (set (match_dup 1) (mem:PSI (match_dup 3)))]
8157   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8158   "
8159 {
8160   operands[1] = get_fpscr_rtx ();
8161   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
8162   if (flag_pic)
8163     operands[2] = legitimize_pic_address (operands[2], SImode,
8164                                           no_new_pseudos ? operands[0] : 0);
8165   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
8166 }")
8167
8168 (define_expand "movpsi"
8169   [(set (match_operand:PSI 0 "register_operand" "")
8170         (match_operand:PSI 1 "general_movsrc_operand" ""))]
8171   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8172   "")
8173
8174 ;; The c / m alternative is a fake to guide reload to load directly into
8175 ;; fpscr, since reload doesn't know how to use post-increment.
8176 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
8177 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
8178 ;; predicate after reload.
8179 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
8180 ;; like a mac -> gpr move.
8181 (define_insn "fpu_switch"
8182   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
8183         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
8184   "TARGET_SH2E
8185    && (! reload_completed
8186        || true_regnum (operands[0]) != FPSCR_REG
8187        || GET_CODE (operands[1]) != MEM
8188        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
8189   "@
8190         ! precision stays the same
8191         lds.l   %1,fpscr
8192         mov.l   %1,%0
8193         #
8194         lds     %1,fpscr
8195         mov     %1,%0
8196         mov.l   %1,%0
8197         sts     fpscr,%0
8198         sts.l   fpscr,%0"
8199   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
8200    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
8201
8202 (define_split
8203   [(set (reg:PSI FPSCR_REG)
8204         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
8205   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
8206   [(set (match_dup 0) (match_dup 0))]
8207   "
8208 {
8209   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
8210                                         gen_rtx_MEM (PSImode,
8211                                                  gen_rtx_POST_INC (Pmode,
8212                                                           operands[0]))));
8213   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
8214 }")
8215
8216 (define_split
8217   [(set (reg:PSI FPSCR_REG)
8218         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
8219   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8220   [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))]
8221   "
8222 {
8223   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
8224                                         gen_rtx_MEM (PSImode,
8225                                                  gen_rtx_POST_INC (Pmode,
8226                                                           operands[0]))));
8227   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
8228 }")
8229
8230 ;; ??? This uses the fp unit, but has no type indicating that.
8231 ;; If we did that, this would either give a bogus latency or introduce
8232 ;; a bogus FIFO constraint.
8233 ;; Since this insn is currently only used for prologues/epilogues,
8234 ;; it is probably best to claim no function unit, which matches the
8235 ;; current setting.
8236 (define_insn "toggle_sz"
8237   [(set (reg:PSI FPSCR_REG)
8238         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
8239   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8240   "fschg"
8241   [(set_attr "type" "fp") (set_attr "fp_set" "unknown")])
8242
8243 ;; There's no way we can use it today, since optimize mode switching
8244 ;; doesn't enable us to know from which mode we're switching to the
8245 ;; mode it requests, to tell whether we can use a relative mode switch
8246 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
8247 ;; memory).
8248 (define_insn "toggle_pr"
8249   [(set (reg:PSI FPSCR_REG)
8250         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
8251   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
8252   "fpchg"
8253   [(set_attr "type" "fp")])
8254
8255 (define_expand "addsf3"
8256   [(set (match_operand:SF 0 "arith_reg_operand" "")
8257         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
8258                  (match_operand:SF 2 "arith_reg_operand" "")))]
8259   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8260   "
8261 {
8262   if (TARGET_SH2E)
8263     {
8264       expand_sf_binop (&gen_addsf3_i, operands);
8265       DONE;
8266     }
8267 }")
8268
8269 (define_insn "*addsf3_media"
8270   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8271         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8272                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8273   "TARGET_SHMEDIA_FPU"
8274   "fadd.s       %1, %2, %0"
8275   [(set_attr "type" "fparith_media")])
8276
8277 (define_insn_and_split "unary_sf_op"
8278   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8279         (vec_select:V2SF
8280          (vec_concat:V2SF
8281           (vec_select:SF
8282            (match_dup 0)
8283            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
8284           (match_operator:SF 2 "unary_float_operator"
8285             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
8286                             (parallel [(match_operand 4
8287                                         "const_int_operand" "n")]))]))
8288          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
8289   "TARGET_SHMEDIA_FPU"
8290   "#"
8291   "TARGET_SHMEDIA_FPU && reload_completed"
8292   [(set (match_dup 5) (match_dup 6))]
8293   "
8294 {
8295   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
8296   rtx op1 = gen_rtx_REG (SFmode,
8297                          (true_regnum (operands[1])
8298                           + (INTVAL (operands[4]) ^ endian)));
8299
8300   operands[7] = gen_rtx_REG (SFmode,
8301                              (true_regnum (operands[0])
8302                               + (INTVAL (operands[3]) ^ endian)));
8303   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
8304 }"
8305   [(set_attr "type" "fparith_media")])
8306
8307 (define_insn_and_split "binary_sf_op"
8308   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8309         (vec_select:V2SF
8310          (vec_concat:V2SF
8311           (vec_select:SF
8312            (match_dup 0)
8313            (parallel [(match_operand 7 "const_int_operand" "n")]))
8314           (match_operator:SF 3 "binary_float_operator"
8315             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
8316                             (parallel [(match_operand 5
8317                                         "const_int_operand" "n")]))
8318              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
8319                             (parallel [(match_operand 6
8320                                         "const_int_operand" "n")]))]))
8321          (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
8322   "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
8323   "#"
8324   "&& reload_completed"
8325   [(set (match_dup 8) (match_dup 9))]
8326   "
8327 {
8328   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
8329   rtx op1 = gen_rtx_REG (SFmode,
8330                          (true_regnum (operands[1])
8331                           + (INTVAL (operands[5]) ^ endian)));
8332   rtx op2 = gen_rtx_REG (SFmode,
8333                          (true_regnum (operands[2])
8334                           + (INTVAL (operands[6]) ^ endian)));
8335
8336   operands[8] = gen_rtx_REG (SFmode,
8337                              (true_regnum (operands[0])
8338                               + (INTVAL (operands[4]) ^ endian)));
8339   operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
8340 }"
8341   [(set_attr "type" "fparith_media")])
8342
8343 (define_insn "addsf3_i"
8344   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8345         (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
8346                  (match_operand:SF 2 "arith_reg_operand" "f")))
8347    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8348   "TARGET_SH2E"
8349   "fadd %2,%0"
8350   [(set_attr "type" "fp")
8351    (set_attr "fp_mode" "single")])
8352
8353 (define_expand "subsf3"
8354   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8355         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8356                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8357   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8358   "
8359 {
8360   if (TARGET_SH2E)
8361     {
8362       expand_sf_binop (&gen_subsf3_i, operands);
8363       DONE;
8364     }
8365 }")
8366
8367 (define_insn "*subsf3_media"
8368   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8369         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8370                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8371   "TARGET_SHMEDIA_FPU"
8372   "fsub.s       %1, %2, %0"
8373   [(set_attr "type" "fparith_media")])
8374
8375 (define_insn "subsf3_i"
8376   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8377         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
8378                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8379    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8380   "TARGET_SH2E"
8381   "fsub %2,%0"
8382   [(set_attr "type" "fp")
8383    (set_attr "fp_mode" "single")])
8384
8385 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
8386 ;; register in feeding fp instructions.  Thus, we cannot generate fmac for
8387 ;; mixed-precision SH4 targets.  To allow it to be still generated for the
8388 ;; SH3E, we use a separate insn for SH3E mulsf3.
8389
8390 (define_expand "mulsf3"
8391   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8392         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8393                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8394   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8395   "
8396 {
8397   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
8398     expand_sf_binop (&gen_mulsf3_i4, operands);
8399   else if (TARGET_SH2E)
8400     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
8401   if (! TARGET_SHMEDIA)
8402     DONE;
8403 }")
8404
8405 (define_insn "*mulsf3_media"
8406   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8407         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8408                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8409   "TARGET_SHMEDIA_FPU"
8410   "fmul.s       %1, %2, %0"
8411   [(set_attr "type" "fparith_media")])
8412
8413 (define_insn "mulsf3_i4"
8414   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8415         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8416                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8417    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8418   "TARGET_SH2E"
8419   "fmul %2,%0"
8420   [(set_attr "type" "fp")
8421    (set_attr "fp_mode" "single")])
8422
8423 (define_insn "mulsf3_ie"
8424   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8425         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8426                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8427   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8428   "fmul %2,%0"
8429   [(set_attr "type" "fp")])
8430
8431 (define_insn "*mac_media"
8432   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8433         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8434                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8435                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
8436   "TARGET_SHMEDIA_FPU"
8437   "fmac.s %1, %2, %0"
8438   [(set_attr "type" "fparith_media")])
8439
8440 (define_insn "*macsf3"
8441   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8442         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
8443                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8444                  (match_operand:SF 3 "arith_reg_operand" "0")))
8445    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
8446   "TARGET_SH2E && ! TARGET_SH4"
8447   "fmac fr0,%2,%0"
8448   [(set_attr "type" "fp")
8449    (set_attr "fp_mode" "single")])
8450
8451 (define_expand "divsf3"
8452   [(set (match_operand:SF 0 "arith_reg_operand" "")
8453         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
8454                 (match_operand:SF 2 "arith_reg_operand" "")))]
8455   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8456   "
8457 {
8458   if (TARGET_SH2E)
8459     {
8460       expand_sf_binop (&gen_divsf3_i, operands);
8461       DONE;
8462     }
8463 }")
8464
8465 (define_insn "*divsf3_media"
8466   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8467         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8468                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8469   "TARGET_SHMEDIA_FPU"
8470   "fdiv.s       %1, %2, %0"
8471   [(set_attr "type" "fdiv_media")])
8472
8473 (define_insn "divsf3_i"
8474   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8475         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
8476                  (match_operand:SF 2 "arith_reg_operand" "f")))
8477    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8478   "TARGET_SH2E"
8479   "fdiv %2,%0"
8480   [(set_attr "type" "fdiv")
8481    (set_attr "fp_mode" "single")])
8482
8483 (define_insn "floatdisf2"
8484   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8485         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8486   "TARGET_SHMEDIA_FPU"
8487   "float.qs %1, %0"
8488   [(set_attr "type" "fpconv_media")])
8489
8490 (define_expand "floatsisf2"
8491   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8492         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
8493   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8494   "
8495 {
8496   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
8497     {
8498       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8499       DONE;
8500     }
8501 }")
8502
8503 (define_insn "*floatsisf2_media"
8504   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8505         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8506   "TARGET_SHMEDIA_FPU"
8507   "float.ls     %1, %0"
8508   [(set_attr "type" "fpconv_media")])
8509
8510 (define_insn "floatsisf2_i4"
8511   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8512         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
8513    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8514   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8515   "float        %1,%0"
8516   [(set_attr "type" "fp")
8517    (set_attr "fp_mode" "single")])
8518
8519 (define_insn "*floatsisf2_ie"
8520   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8521         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
8522   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8523   "float        %1,%0"
8524   [(set_attr "type" "fp")])
8525
8526 (define_insn "fix_truncsfdi2"
8527   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8528         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8529   "TARGET_SHMEDIA_FPU"
8530   "ftrc.sq %1, %0"
8531   [(set_attr "type" "fpconv_media")])
8532
8533 (define_expand "fix_truncsfsi2"
8534   [(set (match_operand:SI 0 "fpul_operand" "=y")
8535         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8536   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8537   "
8538 {
8539   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
8540     {
8541       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8542       DONE;
8543     }
8544 }")
8545
8546 (define_insn "*fix_truncsfsi2_media"
8547   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8548         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8549   "TARGET_SHMEDIA_FPU"
8550   "ftrc.sl      %1, %0"
8551   [(set_attr "type" "fpconv_media")])
8552
8553 (define_insn "fix_truncsfsi2_i4"
8554   [(set (match_operand:SI 0 "fpul_operand" "=y")
8555         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8556    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8557   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8558   "ftrc %1,%0"
8559   [(set_attr "type" "ftrc_s")
8560    (set_attr "fp_mode" "single")])
8561
8562 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
8563 ;; fix_truncsfsi2_i4.
8564 ;; (define_insn "fix_truncsfsi2_i4_2"
8565 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8566 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8567 ;;   (use (reg:PSI FPSCR_REG))
8568 ;;   (clobber (reg:SI FPUL_REG))]
8569 ;;  "TARGET_SH4"
8570 ;;  "#"
8571 ;;  [(set_attr "length" "4")
8572 ;;   (set_attr "fp_mode" "single")])
8573
8574 ;;(define_split
8575 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8576 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8577 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
8578 ;;   (clobber (reg:SI FPUL_REG))]
8579 ;;  "TARGET_SH4"
8580 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8581 ;;            (use (match_dup 2))])
8582 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
8583
8584 (define_insn "*fixsfsi"
8585   [(set (match_operand:SI 0 "fpul_operand" "=y")
8586         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8587   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8588   "ftrc %1,%0"
8589   [(set_attr "type" "fp")])
8590
8591 (define_insn "cmpgtsf_t"
8592   [(set (reg:SI T_REG)
8593         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8594                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8595   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8596   "fcmp/gt      %1,%0"
8597   [(set_attr "type" "fp")
8598    (set_attr "fp_mode" "single")])
8599
8600 (define_insn "cmpeqsf_t"
8601   [(set (reg:SI T_REG)
8602         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8603                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8604   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8605   "fcmp/eq      %1,%0"
8606   [(set_attr "type" "fp")
8607    (set_attr "fp_mode" "single")])
8608
8609 (define_insn "ieee_ccmpeqsf_t"
8610   [(set (reg:SI T_REG)
8611         (ior:SI (reg:SI T_REG)
8612                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8613                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
8614   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8615   "* return output_ieee_ccmpeq (insn, operands);"
8616   [(set_attr "length" "4")])
8617
8618
8619 (define_insn "cmpgtsf_t_i4"
8620   [(set (reg:SI T_REG)
8621         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8622                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8623    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8624   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8625   "fcmp/gt      %1,%0"
8626   [(set_attr "type" "fp")
8627    (set_attr "fp_mode" "single")])
8628
8629 (define_insn "cmpeqsf_t_i4"
8630   [(set (reg:SI T_REG)
8631         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8632                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8633    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8634   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
8635   "fcmp/eq      %1,%0"
8636   [(set_attr "type" "fp")
8637    (set_attr "fp_mode" "single")])
8638
8639 (define_insn "*ieee_ccmpeqsf_t_4"
8640   [(set (reg:SI T_REG)
8641         (ior:SI (reg:SI T_REG)
8642                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8643                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
8644    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8645   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
8646   "* return output_ieee_ccmpeq (insn, operands);"
8647   [(set_attr "length" "4")
8648    (set_attr "fp_mode" "single")])
8649
8650 (define_insn "cmpeqsf_media"
8651   [(set (match_operand:DI 0 "register_operand" "=r")
8652         (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8653                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8654   "TARGET_SHMEDIA_FPU"
8655   "fcmpeq.s     %1, %2, %0"
8656   [(set_attr "type" "fcmp_media")])
8657
8658 (define_insn "cmpgtsf_media"
8659   [(set (match_operand:DI 0 "register_operand" "=r")
8660         (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8661                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8662   "TARGET_SHMEDIA_FPU"
8663   "fcmpgt.s     %1, %2, %0"
8664   [(set_attr "type" "fcmp_media")])
8665
8666 (define_insn "cmpgesf_media"
8667   [(set (match_operand:DI 0 "register_operand" "=r")
8668         (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8669                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8670   "TARGET_SHMEDIA_FPU"
8671   "fcmpge.s     %1, %2, %0"
8672   [(set_attr "type" "fcmp_media")])
8673
8674 (define_insn "cmpunsf_media"
8675   [(set (match_operand:DI 0 "register_operand" "=r")
8676         (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8677                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8678   "TARGET_SHMEDIA_FPU"
8679   "fcmpun.s     %1, %2, %0"
8680   [(set_attr "type" "fcmp_media")])
8681
8682 (define_expand "cmpsf"
8683   [(set (reg:SI T_REG)
8684         (compare (match_operand:SF 0 "arith_operand" "")
8685                  (match_operand:SF 1 "arith_operand" "")))]
8686   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8687   "
8688 {
8689   sh_compare_op0 = operands[0];
8690   sh_compare_op1 = operands[1];
8691   DONE;
8692 }")
8693
8694 (define_expand "negsf2"
8695   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8696         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8697   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8698   "
8699 {
8700   if (TARGET_SH2E)
8701     {
8702       expand_sf_unop (&gen_negsf2_i, operands);
8703       DONE;
8704     }
8705 }")
8706
8707 (define_insn "*negsf2_media"
8708   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8709         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8710   "TARGET_SHMEDIA_FPU"
8711   "fneg.s       %1, %0"
8712   [(set_attr "type" "fmove_media")])
8713
8714 (define_insn "negsf2_i"
8715   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8716         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8717    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8718   "TARGET_SH2E"
8719   "fneg %0"
8720   [(set_attr "type" "fmove")
8721    (set_attr "fp_mode" "single")])
8722
8723 (define_expand "sqrtsf2"
8724   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8725         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8726   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8727   "
8728 {
8729   if (TARGET_SH3E)
8730     {
8731       expand_sf_unop (&gen_sqrtsf2_i, operands);
8732       DONE;
8733     }
8734 }")
8735
8736 (define_insn "*sqrtsf2_media"
8737   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8738         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8739   "TARGET_SHMEDIA_FPU"
8740   "fsqrt.s      %1, %0"
8741   [(set_attr "type" "fdiv_media")])
8742
8743 (define_insn "sqrtsf2_i"
8744   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8745         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8746    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8747   "TARGET_SH3E"
8748   "fsqrt        %0"
8749   [(set_attr "type" "fdiv")
8750    (set_attr "fp_mode" "single")])
8751
8752 (define_insn "rsqrtsf2"
8753   [(set (match_operand:SF 0 "register_operand" "=f")
8754         (div:SF (match_operand:SF 1 "immediate_operand" "i")
8755                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
8756    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8757   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
8758    && operands[1] == CONST1_RTX (SFmode)"
8759   "fsrra        %0"
8760   [(set_attr "type" "fsrra")
8761    (set_attr "fp_mode" "single")])
8762
8763 (define_insn "fsca"
8764   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8765         (vec_concat:V2SF
8766          (unspec:SF [(mult:SF
8767                       (float:SF (match_operand:SI 1 "fpul_operand" "y"))
8768                       (match_operand:SF 2 "immediate_operand" "i"))
8769                     ] UNSPEC_FSINA)
8770          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
8771                     ] UNSPEC_FCOSA)))
8772    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8773   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
8774    && operands[2] == sh_fsca_int2sf ()"
8775   "fsca fpul,%d0"
8776   [(set_attr "type" "fsca")
8777    (set_attr "fp_mode" "single")])
8778
8779 (define_expand "sinsf2"
8780   [(set (match_operand:SF 0 "nonimmediate_operand" "")
8781         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
8782                    UNSPEC_FSINA))]
8783   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
8784   "
8785 {
8786   rtx scaled = gen_reg_rtx (SFmode);
8787   rtx truncated = gen_reg_rtx (SImode);
8788   rtx fsca = gen_reg_rtx (V2SFmode);
8789   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
8790
8791   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
8792   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
8793   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8794                           get_fpscr_rtx ()));
8795   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
8796   DONE;
8797 }")
8798
8799 (define_expand "cossf2"
8800   [(set (match_operand:SF 0 "nonimmediate_operand" "")
8801         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
8802                    UNSPEC_FCOSA))]
8803   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
8804   "
8805 {
8806   rtx scaled = gen_reg_rtx (SFmode);
8807   rtx truncated = gen_reg_rtx (SImode);
8808   rtx fsca = gen_reg_rtx (V2SFmode);
8809   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
8810
8811   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
8812   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
8813   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8814                           get_fpscr_rtx ()));
8815   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
8816   DONE;
8817 }")
8818
8819 (define_expand "sindf2"
8820   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8821         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
8822                    UNSPEC_FSINA))]
8823   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
8824   "
8825 {
8826   rtx scaled = gen_reg_rtx (DFmode);
8827   rtx truncated = gen_reg_rtx (SImode);
8828   rtx fsca = gen_reg_rtx (V2SFmode);
8829   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
8830   rtx sfresult = gen_reg_rtx (SFmode);
8831
8832   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
8833   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
8834   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8835                           get_fpscr_rtx ()));
8836   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
8837   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
8838   DONE;
8839 }")
8840
8841 (define_expand "cosdf2"
8842   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8843         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
8844                    UNSPEC_FCOSA))]
8845   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
8846   "
8847 {
8848   rtx scaled = gen_reg_rtx (DFmode);
8849   rtx truncated = gen_reg_rtx (SImode);
8850   rtx fsca = gen_reg_rtx (V2SFmode);
8851   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
8852   rtx sfresult = gen_reg_rtx (SFmode);
8853
8854   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
8855   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
8856   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
8857                           get_fpscr_rtx ()));
8858   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
8859   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
8860   DONE;
8861 }")
8862
8863 (define_expand "abssf2"
8864   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8865         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8866   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
8867   "
8868 {
8869   if (TARGET_SH2E)
8870     {
8871       expand_sf_unop (&gen_abssf2_i, operands);
8872       DONE;
8873     }
8874 }")
8875
8876 (define_insn "*abssf2_media"
8877   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8878         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8879   "TARGET_SHMEDIA_FPU"
8880   "fabs.s       %1, %0"
8881   [(set_attr "type" "fmove_media")])
8882
8883 (define_insn "abssf2_i"
8884   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8885         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8886    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8887   "TARGET_SH2E"
8888   "fabs %0"
8889   [(set_attr "type" "fmove")
8890    (set_attr "fp_mode" "single")])
8891
8892 (define_expand "adddf3"
8893   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8894         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8895                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8896   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
8897   "
8898 {
8899   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8900     {
8901       expand_df_binop (&gen_adddf3_i, operands);
8902       DONE;
8903     }
8904 }")
8905
8906 (define_insn "*adddf3_media"
8907   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8908         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8909                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8910   "TARGET_SHMEDIA_FPU"
8911   "fadd.d       %1, %2, %0"
8912   [(set_attr "type" "dfparith_media")])
8913
8914 (define_insn "adddf3_i"
8915   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8916         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8917                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8918    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8919   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8920   "fadd %2,%0"
8921   [(set_attr "type" "dfp_arith")
8922    (set_attr "fp_mode" "double")])
8923
8924 (define_expand "subdf3"
8925   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8926         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8927                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8928   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
8929   "
8930 {
8931   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8932     {
8933       expand_df_binop (&gen_subdf3_i, operands);
8934       DONE;
8935     }
8936 }")
8937
8938 (define_insn "*subdf3_media"
8939   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8940         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8941                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8942   "TARGET_SHMEDIA_FPU"
8943   "fsub.d       %1, %2, %0"
8944   [(set_attr "type" "dfparith_media")])
8945
8946 (define_insn "subdf3_i"
8947   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8948         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8949                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8950    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8951   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8952   "fsub %2,%0"
8953   [(set_attr "type" "dfp_arith")
8954    (set_attr "fp_mode" "double")])
8955
8956 (define_expand "muldf3"
8957   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8958         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8959                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8960   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
8961   "
8962 {
8963   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8964     {
8965       expand_df_binop (&gen_muldf3_i, operands);
8966       DONE;
8967     }
8968 }")
8969
8970 (define_insn "*muldf3_media"
8971   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8972         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8973                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8974   "TARGET_SHMEDIA_FPU"
8975   "fmul.d       %1, %2, %0"
8976   [(set_attr "type" "dfmul_media")])
8977
8978 (define_insn "muldf3_i"
8979   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8980         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8981                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8982    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8983   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
8984   "fmul %2,%0"
8985   [(set_attr "type" "dfp_arith")
8986    (set_attr "fp_mode" "double")])
8987
8988 (define_expand "divdf3"
8989   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8990         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8991                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8992   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
8993   "
8994 {
8995   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8996     {
8997       expand_df_binop (&gen_divdf3_i, operands);
8998       DONE;
8999     }
9000 }")
9001
9002 (define_insn "*divdf3_media"
9003   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9004         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
9005                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9006   "TARGET_SHMEDIA_FPU"
9007   "fdiv.d       %1, %2, %0"
9008   [(set_attr "type" "dfdiv_media")])
9009
9010 (define_insn "divdf3_i"
9011   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9012         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
9013                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
9014    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9015   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9016   "fdiv %2,%0"
9017   [(set_attr "type" "dfdiv")
9018    (set_attr "fp_mode" "double")])
9019
9020 (define_insn "floatdidf2"
9021   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9022         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
9023   "TARGET_SHMEDIA_FPU"
9024   "float.qd     %1, %0"
9025   [(set_attr "type" "dfpconv_media")])
9026
9027 (define_expand "floatsidf2"
9028   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
9029         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
9030   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9031   "
9032 {
9033   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9034     {
9035       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
9036                                       get_fpscr_rtx ()));
9037       DONE;
9038     }
9039 }")
9040
9041 (define_insn "*floatsidf2_media"
9042   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9043         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
9044   "TARGET_SHMEDIA_FPU"
9045   "float.ld     %1, %0"
9046   [(set_attr "type" "dfpconv_media")])
9047
9048 (define_insn "floatsidf2_i"
9049   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9050         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
9051    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9052   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9053   "float        %1,%0"
9054   [(set_attr "type" "dfp_conv")
9055    (set_attr "fp_mode" "double")])
9056
9057 (define_insn "fix_truncdfdi2"
9058   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
9059         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9060   "TARGET_SHMEDIA_FPU"
9061   "ftrc.dq      %1, %0"
9062   [(set_attr "type" "dfpconv_media")])
9063
9064 (define_expand "fix_truncdfsi2"
9065   [(set (match_operand:SI 0 "fpul_operand" "")
9066         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
9067   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9068   "
9069 {
9070   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9071     {
9072       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
9073                                           get_fpscr_rtx ()));
9074       DONE;
9075     }
9076 }")
9077
9078 (define_insn "*fix_truncdfsi2_media"
9079   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
9080         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9081   "TARGET_SHMEDIA_FPU"
9082   "ftrc.dl      %1, %0"
9083   [(set_attr "type" "dfpconv_media")])
9084
9085 (define_insn "fix_truncdfsi2_i"
9086   [(set (match_operand:SI 0 "fpul_operand" "=y")
9087         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
9088    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9089   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9090   "ftrc %1,%0"
9091   [(set_attr "type" "dfp_conv")
9092    (set_attr "dfp_comp" "no")
9093    (set_attr "fp_mode" "double")])
9094
9095 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
9096 ;; fix_truncdfsi2_i.
9097 ;; (define_insn "fix_truncdfsi2_i4"
9098 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9099 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
9100 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
9101 ;;    (clobber (reg:SI FPUL_REG))]
9102 ;;   "TARGET_SH4"
9103 ;;   "#"
9104 ;;   [(set_attr "length" "4")
9105 ;;    (set_attr "fp_mode" "double")])
9106 ;;
9107 ;; (define_split
9108 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9109 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
9110 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
9111 ;;    (clobber (reg:SI FPUL_REG))]
9112 ;;   "TARGET_SH4"
9113 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
9114 ;;            (use (match_dup 2))])
9115 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
9116
9117 (define_insn "cmpgtdf_t"
9118   [(set (reg:SI T_REG)
9119         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
9120                (match_operand:DF 1 "arith_reg_operand" "f")))
9121    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9122   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9123   "fcmp/gt      %1,%0"
9124   [(set_attr "type" "dfp_cmp")
9125    (set_attr "fp_mode" "double")])
9126
9127 (define_insn "cmpeqdf_t"
9128   [(set (reg:SI T_REG)
9129         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
9130                (match_operand:DF 1 "arith_reg_operand" "f")))
9131    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9132   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9133   "fcmp/eq      %1,%0"
9134   [(set_attr "type" "dfp_cmp")
9135    (set_attr "fp_mode" "double")])
9136
9137 (define_insn "*ieee_ccmpeqdf_t"
9138   [(set (reg:SI T_REG)
9139         (ior:SI (reg:SI T_REG)
9140                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
9141                        (match_operand:DF 1 "arith_reg_operand" "f"))))
9142    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9143   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9144   "* return output_ieee_ccmpeq (insn, operands);"
9145   [(set_attr "length" "4")
9146    (set_attr "fp_mode" "double")])
9147
9148 (define_insn "cmpeqdf_media"
9149   [(set (match_operand:DI 0 "register_operand" "=r")
9150         (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9151                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9152   "TARGET_SHMEDIA_FPU"
9153   "fcmpeq.d     %1,%2,%0"
9154   [(set_attr "type" "fcmp_media")])
9155
9156 (define_insn "cmpgtdf_media"
9157   [(set (match_operand:DI 0 "register_operand" "=r")
9158         (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9159                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9160   "TARGET_SHMEDIA_FPU"
9161   "fcmpgt.d     %1,%2,%0"
9162   [(set_attr "type" "fcmp_media")])
9163
9164 (define_insn "cmpgedf_media"
9165   [(set (match_operand:DI 0 "register_operand" "=r")
9166         (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9167                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9168   "TARGET_SHMEDIA_FPU"
9169   "fcmpge.d     %1,%2,%0"
9170   [(set_attr "type" "fcmp_media")])
9171
9172 (define_insn "cmpundf_media"
9173   [(set (match_operand:DI 0 "register_operand" "=r")
9174         (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
9175                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
9176   "TARGET_SHMEDIA_FPU"
9177   "fcmpun.d     %1,%2,%0"
9178   [(set_attr "type" "fcmp_media")])
9179
9180 (define_expand "cmpdf"
9181   [(set (reg:SI T_REG)
9182         (compare (match_operand:DF 0 "arith_operand" "")
9183                  (match_operand:DF 1 "arith_operand" "")))]
9184   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9185   "
9186 {
9187   sh_compare_op0 = operands[0];
9188   sh_compare_op1 = operands[1];
9189   DONE;
9190 }")
9191
9192 (define_expand "negdf2"
9193   [(set (match_operand:DF 0 "arith_reg_operand" "")
9194         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
9195   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9196   "
9197 {
9198   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9199     {
9200       expand_df_unop (&gen_negdf2_i, operands);
9201       DONE;
9202     }
9203 }")
9204
9205 (define_insn "*negdf2_media"
9206   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9207         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9208   "TARGET_SHMEDIA_FPU"
9209   "fneg.d       %1, %0"
9210   [(set_attr "type" "fmove_media")])
9211
9212 (define_insn "negdf2_i"
9213   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
9214         (neg:DF (match_operand:DF 1 "arith_reg_operand" "0")))
9215    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9216   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9217   "fneg %0"
9218   [(set_attr "type" "fmove")
9219    (set_attr "fp_mode" "double")])
9220
9221 (define_expand "sqrtdf2"
9222   [(set (match_operand:DF 0 "arith_reg_operand" "")
9223         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
9224   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9225   "
9226 {
9227   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9228     {
9229       expand_df_unop (&gen_sqrtdf2_i, operands);
9230       DONE;
9231     }
9232 }")
9233
9234 (define_insn "*sqrtdf2_media"
9235   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9236         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9237   "TARGET_SHMEDIA_FPU"
9238   "fsqrt.d      %1, %0"
9239   [(set_attr "type" "dfdiv_media")])
9240
9241 (define_insn "sqrtdf2_i"
9242   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
9243         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0")))
9244    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9245   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9246   "fsqrt        %0"
9247   [(set_attr "type" "dfdiv")
9248    (set_attr "fp_mode" "double")])
9249
9250 (define_expand "absdf2"
9251   [(set (match_operand:DF 0 "arith_reg_operand" "")
9252         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
9253   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9254   "
9255 {
9256   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9257     {
9258       expand_df_unop (&gen_absdf2_i, operands);
9259       DONE;
9260     }
9261 }")
9262
9263 (define_insn "*absdf2_media"
9264   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9265         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9266   "TARGET_SHMEDIA_FPU"
9267   "fabs.d       %1, %0"
9268   [(set_attr "type" "fmove_media")])
9269
9270 (define_insn "absdf2_i"
9271   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
9272         (abs:DF (match_operand:DF 1 "arith_reg_operand" "0")))
9273    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9274   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9275   "fabs %0"
9276   [(set_attr "type" "fmove")
9277    (set_attr "fp_mode" "double")])
9278
9279 (define_expand "extendsfdf2"
9280   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
9281         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
9282   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9283   "
9284 {
9285   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9286     {
9287       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
9288                                         get_fpscr_rtx ()));
9289       DONE;
9290     }
9291 }")
9292
9293 (define_insn "*extendsfdf2_media"
9294   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9295         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
9296   "TARGET_SHMEDIA_FPU"
9297   "fcnv.sd      %1, %0"
9298   [(set_attr "type" "dfpconv_media")])
9299
9300 (define_insn "extendsfdf2_i4"
9301   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
9302         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
9303    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9304   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9305   "fcnvsd  %1,%0"
9306   [(set_attr "type" "fp")
9307    (set_attr "fp_mode" "double")])
9308
9309 (define_expand "truncdfsf2"
9310   [(set (match_operand:SF 0 "fpul_operand" "")
9311         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
9312   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9313   "
9314 {
9315   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
9316     {
9317       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
9318                                        get_fpscr_rtx ()));
9319       DONE;
9320     }
9321 }")
9322
9323 (define_insn "*truncdfsf2_media"
9324   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9325         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
9326   "TARGET_SHMEDIA_FPU"
9327   "fcnv.ds      %1, %0"
9328   [(set_attr "type" "dfpconv_media")])
9329
9330 (define_insn "truncdfsf2_i4"
9331   [(set (match_operand:SF 0 "fpul_operand" "=y")
9332         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
9333    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
9334   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9335   "fcnvds  %1,%0"
9336   [(set_attr "type" "fp")
9337    (set_attr "fp_mode" "double")])
9338 \f
9339 ;; Bit field extract patterns.  These give better code for packed bitfields,
9340 ;; because they allow auto-increment addresses to be generated.
9341
9342 (define_expand "insv"
9343   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
9344                          (match_operand:SI 1 "immediate_operand" "")
9345                          (match_operand:SI 2 "immediate_operand" ""))
9346         (match_operand:SI 3 "general_operand" ""))]
9347   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
9348   "
9349 {
9350   rtx addr_target, orig_address, shift_reg, qi_val;
9351   HOST_WIDE_INT bitsize, size, v = 0;
9352   rtx x = operands[3];
9353
9354   /* ??? expmed doesn't care for non-register predicates.  */
9355   if (! memory_operand (operands[0], VOIDmode)
9356       || ! immediate_operand (operands[1], VOIDmode)
9357       || ! immediate_operand (operands[2], VOIDmode)
9358       || ! general_operand (x, VOIDmode))
9359     FAIL;
9360   /* If this isn't a 16 / 24 / 32 bit field, or if
9361      it doesn't start on a byte boundary, then fail.  */
9362   bitsize = INTVAL (operands[1]);
9363   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
9364       || (INTVAL (operands[2]) % 8) != 0)
9365     FAIL;
9366
9367   size = bitsize / 8;
9368   orig_address = XEXP (operands[0], 0);
9369   shift_reg = gen_reg_rtx (SImode);
9370   if (GET_CODE (x) == CONST_INT)
9371     {
9372       v = INTVAL (x);
9373       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
9374     }
9375   else
9376     {
9377       emit_insn (gen_movsi (shift_reg, operands[3]));
9378       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
9379     }
9380   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
9381
9382   operands[0] = replace_equiv_address (operands[0], addr_target);
9383   emit_insn (gen_movqi (operands[0], qi_val));
9384
9385   while (size -= 1)
9386     {
9387       if (GET_CODE (x) == CONST_INT)
9388         qi_val
9389           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
9390       else
9391         {
9392           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
9393           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
9394         }
9395       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
9396       emit_insn (gen_movqi (operands[0], qi_val));
9397     }
9398
9399   DONE;
9400 }")
9401
9402 (define_insn "movua"
9403   [(set (match_operand:SI 0 "register_operand" "=z")
9404         (sign_extract:SI (match_operand:SI 1 "unaligned_load_operand" "Sua>")
9405                          (const_int 32) (const_int 0)))]
9406   "TARGET_SH4A_ARCH"
9407   "movua.l      %1,%0"
9408   [(set_attr "type" "movua")])
9409
9410 ;; We shouldn't need this, but cse replaces increments with references
9411 ;; to other regs before flow has a chance to create post_inc
9412 ;; addressing modes, and only postreload's cse_move2add brings the
9413 ;; increments back to a usable form.
9414 (define_peephole2
9415   [(set (match_operand:SI 0 "register_operand" "")
9416         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
9417                          (const_int 32) (const_int 0)))
9418    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
9419   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
9420   [(set (match_operand:SI 0 "register_operand" "")
9421         (sign_extract:SI (mem:SI (post_inc:SI
9422                                   (match_operand:SI 1 "register_operand" "")))
9423                          (const_int 32) (const_int 0)))]
9424   "")
9425
9426 (define_expand "extv"
9427   [(set (match_operand:SI 0 "register_operand" "")
9428         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
9429                          (match_operand 2 "const_int_operand" "")
9430                          (match_operand 3 "const_int_operand" "")))]
9431   ""
9432 {
9433   if (TARGET_SH4A_ARCH
9434       && INTVAL (operands[2]) == 32
9435       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
9436       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
9437     {
9438       emit_insn (gen_movua (operands[0],
9439                             adjust_address (operands[1], SImode, 0)));
9440       DONE;
9441     }
9442
9443   FAIL;
9444 })
9445
9446 (define_expand "extzv"
9447   [(set (match_operand:SI 0 "register_operand" "")
9448         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
9449                          (match_operand 2 "const_int_operand" "")
9450                          (match_operand 3 "const_int_operand" "")))]
9451   ""
9452 {
9453   if (TARGET_SH4A_ARCH
9454       && INTVAL (operands[2]) == 32
9455       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
9456       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
9457     {
9458       emit_insn (gen_movua (operands[0],
9459                             adjust_address (operands[1], SImode, 0)));
9460       DONE;
9461     }
9462
9463   FAIL;
9464 })
9465
9466 \f
9467 ;; -------------------------------------------------------------------------
9468 ;; Peepholes
9469 ;; -------------------------------------------------------------------------
9470
9471 ;; This matches cases where a stack pointer increment at the start of the
9472 ;; epilogue combines with a stack slot read loading the return value.
9473
9474 (define_peephole
9475   [(set (match_operand:SI 0 "arith_reg_operand" "")
9476         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
9477    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
9478   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
9479   "mov.l        @%1+,%0")
9480
9481 ;; See the comment on the dt combiner pattern above.
9482
9483 (define_peephole
9484   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9485         (plus:SI (match_dup 0)
9486                  (const_int -1)))
9487    (set (reg:SI T_REG)
9488         (eq:SI (match_dup 0)
9489                (const_int 0)))]
9490   "TARGET_SH2"
9491   "dt   %0")
9492
9493 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
9494 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
9495 ;; reload when the constant is too large for a reg+offset address.
9496
9497 ;; ??? We would get much better code if this was done in reload.  This would
9498 ;; require modifying find_reloads_address to recognize that if the constant
9499 ;; is out-of-range for an immediate add, then we get better code by reloading
9500 ;; the constant into a register than by reloading the sum into a register,
9501 ;; since the former is one instruction shorter if the address does not need
9502 ;; to be offsettable.  Unfortunately this does not work, because there is
9503 ;; only one register, r0, that can be used as an index register.  This register
9504 ;; is also the function return value register.  So, if we try to force reload
9505 ;; to use double-reg addresses, then we end up with some instructions that
9506 ;; need to use r0 twice.  The only way to fix this is to change the calling
9507 ;; convention so that r0 is not used to return values.
9508
9509 (define_peephole
9510   [(set (match_operand:SI 0 "register_operand" "=r")
9511         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9512    (set (mem:SI (match_dup 0))
9513         (match_operand:SI 2 "general_movsrc_operand" ""))]
9514   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9515   "mov.l        %2,@(%0,%1)")
9516
9517 (define_peephole
9518   [(set (match_operand:SI 0 "register_operand" "=r")
9519         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9520    (set (match_operand:SI 2 "general_movdst_operand" "")
9521         (mem:SI (match_dup 0)))]
9522   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9523   "mov.l        @(%0,%1),%2")
9524
9525 (define_peephole
9526   [(set (match_operand:SI 0 "register_operand" "=r")
9527         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9528    (set (mem:HI (match_dup 0))
9529         (match_operand:HI 2 "general_movsrc_operand" ""))]
9530   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9531   "mov.w        %2,@(%0,%1)")
9532
9533 (define_peephole
9534   [(set (match_operand:SI 0 "register_operand" "=r")
9535         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9536    (set (match_operand:HI 2 "general_movdst_operand" "")
9537         (mem:HI (match_dup 0)))]
9538   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9539   "mov.w        @(%0,%1),%2")
9540
9541 (define_peephole
9542   [(set (match_operand:SI 0 "register_operand" "=r")
9543         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9544    (set (mem:QI (match_dup 0))
9545         (match_operand:QI 2 "general_movsrc_operand" ""))]
9546   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9547   "mov.b        %2,@(%0,%1)")
9548
9549 (define_peephole
9550   [(set (match_operand:SI 0 "register_operand" "=r")
9551         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9552    (set (match_operand:QI 2 "general_movdst_operand" "")
9553         (mem:QI (match_dup 0)))]
9554   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9555   "mov.b        @(%0,%1),%2")
9556
9557 (define_peephole
9558   [(set (match_operand:SI 0 "register_operand" "=r")
9559         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9560    (set (mem:SF (match_dup 0))
9561         (match_operand:SF 2 "general_movsrc_operand" ""))]
9562   "TARGET_SH1 && REGNO (operands[0]) == 0
9563    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9564        || (GET_CODE (operands[2]) == SUBREG
9565            && REGNO (SUBREG_REG (operands[2])) < 16))
9566    && reg_unused_after (operands[0], insn)"
9567   "mov.l        %2,@(%0,%1)")
9568
9569 (define_peephole
9570   [(set (match_operand:SI 0 "register_operand" "=r")
9571         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9572    (set (match_operand:SF 2 "general_movdst_operand" "")
9573
9574         (mem:SF (match_dup 0)))]
9575   "TARGET_SH1 && REGNO (operands[0]) == 0
9576    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9577        || (GET_CODE (operands[2]) == SUBREG
9578            && REGNO (SUBREG_REG (operands[2])) < 16))
9579    && reg_unused_after (operands[0], insn)"
9580   "mov.l        @(%0,%1),%2")
9581
9582 (define_peephole
9583   [(set (match_operand:SI 0 "register_operand" "=r")
9584         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9585    (set (mem:SF (match_dup 0))
9586         (match_operand:SF 2 "general_movsrc_operand" ""))]
9587   "TARGET_SH2E && REGNO (operands[0]) == 0
9588    && ((GET_CODE (operands[2]) == REG
9589         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9590        || (GET_CODE (operands[2]) == SUBREG
9591            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9592    && reg_unused_after (operands[0], insn)"
9593   "fmov{.s|}    %2,@(%0,%1)")
9594
9595 (define_peephole
9596   [(set (match_operand:SI 0 "register_operand" "=r")
9597         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9598    (set (match_operand:SF 2 "general_movdst_operand" "")
9599
9600         (mem:SF (match_dup 0)))]
9601   "TARGET_SH2E && REGNO (operands[0]) == 0
9602    && ((GET_CODE (operands[2]) == REG
9603         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9604        || (GET_CODE (operands[2]) == SUBREG
9605            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9606    && reg_unused_after (operands[0], insn)"
9607   "fmov{.s|}    @(%0,%1),%2")
9608
9609 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
9610 (define_insn "sp_switch_1"
9611   [(const_int 1)]
9612   "TARGET_SH1"
9613   "*
9614 {
9615   rtx xoperands[1];
9616
9617   xoperands[0] = sp_switch;
9618   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
9619   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
9620   return \"mov r0,r15\";
9621 }"
9622   [(set_attr "length" "10")])
9623
9624 ;; Switch back to the original stack for interrupt functions with the
9625 ;; sp_switch attribute.  */
9626 (define_insn "sp_switch_2"
9627   [(const_int 2)]
9628   "TARGET_SH1"
9629   "mov.l @r15+,r15\;mov.l @r15+,r0"
9630   [(set_attr "length" "4")])
9631
9632 ;; Integer vector moves
9633
9634 (define_expand "movv8qi"
9635   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
9636         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
9637   "TARGET_SHMEDIA"
9638   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
9639
9640 (define_insn "movv8qi_i"
9641   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
9642         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9643   "TARGET_SHMEDIA
9644    && (register_operand (operands[0], V8QImode)
9645        || sh_register_operand (operands[1], V8QImode))"
9646   "@
9647         add     %1, r63, %0
9648         movi    %1, %0
9649         #
9650         ld%M1.q %m1, %0
9651         st%M0.q %m0, %N1"
9652   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9653    (set_attr "length" "4,4,16,4,4")])
9654
9655 (define_split
9656   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
9657         (subreg:V8QI (const_int 0) 0))]
9658   "TARGET_SHMEDIA"
9659   [(set (match_dup 0)
9660         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
9661                             (const_int 0) (const_int 0) (const_int 0)
9662                             (const_int 0) (const_int 0)]))])
9663
9664 (define_split
9665   [(set (match_operand 0 "arith_reg_dest" "")
9666         (match_operand 1 "sh_rep_vec" ""))]
9667   "TARGET_SHMEDIA && reload_completed
9668    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9669    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
9670    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
9671    && (XVECEXP (operands[1], 0, 0) != const0_rtx
9672        || XVECEXP (operands[1], 0, 1) != const0_rtx)
9673    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
9674        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
9675   [(set (match_dup 0) (match_dup 1))
9676    (match_dup 2)]
9677   "
9678 {
9679   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
9680   rtx elt1 = XVECEXP (operands[1], 0, 1);
9681
9682   if (unit_size > 2)
9683     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
9684   else
9685     {
9686       if (unit_size < 2)
9687         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
9688       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
9689     }
9690   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
9691   operands[1] = XVECEXP (operands[1], 0, 0);
9692   if (unit_size < 2)
9693     {
9694       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
9695         operands[1]
9696           = GEN_INT (TARGET_LITTLE_ENDIAN
9697                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
9698                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
9699       else
9700         {
9701           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
9702           operands[1]
9703             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
9704         }
9705     }
9706 }")
9707
9708 (define_split
9709   [(set (match_operand 0 "arith_reg_dest" "")
9710         (match_operand 1 "sh_const_vec" ""))]
9711   "TARGET_SHMEDIA && reload_completed
9712    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9713    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
9714    && operands[1] != CONST0_RTX (GET_MODE (operands[1]))"
9715   [(set (match_dup 0) (match_dup 1))]
9716   "
9717 {
9718   rtx v = operands[1];
9719   enum machine_mode new_mode
9720     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
9721
9722   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
9723   operands[1]
9724     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
9725 }")
9726
9727 (define_expand "movv2hi"
9728   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
9729         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
9730   "TARGET_SHMEDIA"
9731   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
9732
9733 (define_insn "movv2hi_i"
9734   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9735         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9736   "TARGET_SHMEDIA
9737    && (register_operand (operands[0], V2HImode)
9738        || sh_register_operand (operands[1], V2HImode))"
9739   "@
9740         addz.l  %1, r63, %0
9741         movi    %1, %0
9742         #
9743         ld%M1.l %m1, %0
9744         st%M0.l %m0, %N1"
9745   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9746    (set_attr "length" "4,4,16,4,4")])
9747
9748 (define_expand "movv4hi"
9749   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
9750         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
9751   "TARGET_SHMEDIA"
9752   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
9753
9754 (define_insn "movv4hi_i"
9755   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9756         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9757   "TARGET_SHMEDIA
9758    && (register_operand (operands[0], V4HImode)
9759        || sh_register_operand (operands[1], V4HImode))"
9760   "@
9761         add     %1, r63, %0
9762         movi    %1, %0
9763         #
9764         ld%M1.q %m1, %0
9765         st%M0.q %m0, %N1"
9766   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9767    (set_attr "length" "4,4,16,4,4")])
9768
9769 (define_expand "movv2si"
9770   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
9771         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
9772   "TARGET_SHMEDIA"
9773   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
9774
9775 (define_insn "movv2si_i"
9776   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
9777         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16C16Z,nW,m,rlZ"))]
9778   "TARGET_SHMEDIA
9779    && (register_operand (operands[0], V2SImode)
9780        || sh_register_operand (operands[1], V2SImode))"
9781   "@
9782         add     %1, r63, %0
9783         #
9784         #
9785         ld%M1.q %m1, %0
9786         st%M0.q %m0, %N1"
9787   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9788    (set_attr "length" "4,4,16,4,4")])
9789
9790 ;; Multimedia Intrinsics
9791
9792 (define_insn "absv2si2"
9793   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9794         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
9795   "TARGET_SHMEDIA"
9796   "mabs.l       %1, %0"
9797   [(set_attr "type" "mcmp_media")])
9798
9799 (define_insn "absv4hi2"
9800   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9801         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
9802   "TARGET_SHMEDIA"
9803   "mabs.w       %1, %0"
9804   [(set_attr "type" "mcmp_media")])
9805
9806 (define_insn "addv2si3"
9807   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9808         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9809                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9810   "TARGET_SHMEDIA"
9811   "madd.l       %1, %2, %0"
9812   [(set_attr "type" "arith_media")])
9813
9814 (define_insn "addv4hi3"
9815   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9816         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9817                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9818   "TARGET_SHMEDIA"
9819   "madd.w       %1, %2, %0"
9820   [(set_attr "type" "arith_media")])
9821
9822 (define_insn "ssaddv2si3"
9823   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9824         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9825                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9826   "TARGET_SHMEDIA"
9827   "madds.l      %1, %2, %0"
9828   [(set_attr "type" "mcmp_media")])
9829
9830 (define_insn "usaddv8qi3"
9831   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9832         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
9833                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
9834   "TARGET_SHMEDIA"
9835   "madds.ub     %1, %2, %0"
9836   [(set_attr "type" "mcmp_media")])
9837
9838 (define_insn "ssaddv4hi3"
9839   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9840         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9841                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9842   "TARGET_SHMEDIA"
9843   "madds.w      %1, %2, %0"
9844   [(set_attr "type" "mcmp_media")])
9845
9846 (define_insn "negcmpeqv8qi"
9847   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9848         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
9849                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
9850   "TARGET_SHMEDIA"
9851   "mcmpeq.b     %N1, %N2, %0"
9852   [(set_attr "type" "mcmp_media")])
9853
9854 (define_insn "negcmpeqv2si"
9855   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9856         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
9857                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
9858   "TARGET_SHMEDIA"
9859   "mcmpeq.l     %N1, %N2, %0"
9860   [(set_attr "type" "mcmp_media")])
9861
9862 (define_insn "negcmpeqv4hi"
9863   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9864         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
9865                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9866   "TARGET_SHMEDIA"
9867   "mcmpeq.w     %N1, %N2, %0"
9868   [(set_attr "type" "mcmp_media")])
9869
9870 (define_insn "negcmpgtuv8qi"
9871   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9872         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
9873                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
9874   "TARGET_SHMEDIA"
9875   "mcmpgt.ub    %N1, %N2, %0"
9876   [(set_attr "type" "mcmp_media")])
9877
9878 (define_insn "negcmpgtv2si"
9879   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9880         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
9881                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
9882   "TARGET_SHMEDIA"
9883   "mcmpgt.l     %N1, %N2, %0"
9884   [(set_attr "type" "mcmp_media")])
9885
9886 (define_insn "negcmpgtv4hi"
9887   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9888         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
9889                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9890   "TARGET_SHMEDIA"
9891   "mcmpgt.w     %N1, %N2, %0"
9892   [(set_attr "type" "mcmp_media")])
9893
9894 (define_insn "mcmv"
9895   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9896         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9897                         (match_operand:DI 2 "arith_reg_operand" "r"))
9898                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
9899                         (not:DI (match_dup 2)))))]
9900   "TARGET_SHMEDIA"
9901   "mcmv %N1, %2, %0"
9902   [(set_attr "type" "arith_media")])
9903
9904 (define_insn "mcnvs_lw"
9905   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9906         (vec_concat:V4HI
9907          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
9908          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
9909   "TARGET_SHMEDIA"
9910   "mcnvs.lw     %N1, %N2, %0"
9911   [(set_attr "type" "mcmp_media")])
9912
9913 (define_insn "mcnvs_wb"
9914   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9915         (vec_concat:V8QI
9916          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
9917          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9918   "TARGET_SHMEDIA"
9919   "mcnvs.wb     %N1, %N2, %0"
9920   [(set_attr "type" "mcmp_media")])
9921
9922 (define_insn "mcnvs_wub"
9923   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9924         (vec_concat:V8QI
9925          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
9926          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
9927   "TARGET_SHMEDIA"
9928   "mcnvs.wub    %N1, %N2, %0"
9929   [(set_attr "type" "mcmp_media")])
9930
9931 (define_insn "mextr_rl"
9932   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9933         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9934                              (match_operand:HI 3 "mextr_bit_offset" "i"))
9935                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
9936                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9937   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9938   "*
9939 {
9940   static char templ[16];
9941
9942   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
9943            (int) INTVAL (operands[3]) >> 3);
9944   return templ;
9945 }"
9946   [(set_attr "type" "arith_media")])
9947
9948 (define_insn "*mextr_lr"
9949   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9950         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9951                            (match_operand:HI 3 "mextr_bit_offset" "i"))
9952                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
9953                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9954   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9955   "*
9956 {
9957   static char templ[16];
9958
9959   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
9960            (int) INTVAL (operands[4]) >> 3);
9961   return templ;
9962 }"
9963   [(set_attr "type" "arith_media")])
9964
9965 ; mextrN can be modelled with vec_select / vec_concat, but the selection
9966 ; vector then varies depending on endianness.
9967 (define_expand "mextr1"
9968   [(match_operand:DI 0 "arith_reg_dest" "")
9969    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9970    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
9971   "TARGET_SHMEDIA"
9972   "
9973 {
9974   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9975                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
9976   DONE;
9977 }")
9978
9979 (define_expand "mextr2"
9980   [(match_operand:DI 0 "arith_reg_dest" "")
9981    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9982    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
9983   "TARGET_SHMEDIA"
9984   "
9985 {
9986   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9987                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
9988   DONE;
9989 }")
9990
9991 (define_expand "mextr3"
9992   [(match_operand:DI 0 "arith_reg_dest" "")
9993    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
9994    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
9995   "TARGET_SHMEDIA"
9996   "
9997 {
9998   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9999                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
10000   DONE;
10001 }")
10002
10003 (define_expand "mextr4"
10004   [(match_operand:DI 0 "arith_reg_dest" "")
10005    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10006    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10007   "TARGET_SHMEDIA"
10008   "
10009 {
10010   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10011                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
10012   DONE;
10013 }")
10014
10015 (define_expand "mextr5"
10016   [(match_operand:DI 0 "arith_reg_dest" "")
10017    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10018    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10019   "TARGET_SHMEDIA"
10020   "
10021 {
10022   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10023                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
10024   DONE;
10025 }")
10026
10027 (define_expand "mextr6"
10028   [(match_operand:DI 0 "arith_reg_dest" "")
10029    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10030    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10031   "TARGET_SHMEDIA"
10032   "
10033 {
10034   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10035                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
10036   DONE;
10037 }")
10038
10039 (define_expand "mextr7"
10040   [(match_operand:DI 0 "arith_reg_dest" "")
10041    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10042    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
10043   "TARGET_SHMEDIA"
10044   "
10045 {
10046   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
10047                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
10048   DONE;
10049 }")
10050
10051 (define_expand "mmacfx_wl"
10052   [(match_operand:V2SI 0 "arith_reg_dest" "")
10053    (match_operand:V2HI 1 "extend_reg_operand" "")
10054    (match_operand:V2HI 2 "extend_reg_operand" "")
10055    (match_operand:V2SI 3 "arith_reg_operand" "")]
10056   "TARGET_SHMEDIA"
10057   "
10058 {
10059   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
10060                               operands[1], operands[2]));
10061   DONE;
10062 }")
10063
10064 (define_insn "mmacfx_wl_i"
10065   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10066         (ss_plus:V2SI
10067          (match_operand:V2SI 1 "arith_reg_operand" "0")
10068          (ss_truncate:V2SI
10069           (ashift:V2DI
10070            (sign_extend:V2DI
10071             (mult:V2SI
10072              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
10073              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
10074            (const_int 1)))))]
10075   "TARGET_SHMEDIA"
10076   "mmacfx.wl    %2, %3, %0"
10077   [(set_attr "type" "mac_media")])
10078
10079 (define_expand "mmacnfx_wl"
10080   [(match_operand:V2SI 0 "arith_reg_dest" "")
10081    (match_operand:V2HI 1 "extend_reg_operand" "")
10082    (match_operand:V2HI 2 "extend_reg_operand" "")
10083    (match_operand:V2SI 3 "arith_reg_operand" "")]
10084   "TARGET_SHMEDIA"
10085   "
10086 {
10087   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
10088                                operands[1], operands[2]));
10089   DONE;
10090 }")
10091
10092 (define_insn "mmacnfx_wl_i"
10093   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10094         (ss_minus:V2SI
10095          (match_operand:V2SI 1 "arith_reg_operand" "0")
10096          (ss_truncate:V2SI
10097           (ashift:V2DI
10098            (sign_extend:V2DI
10099             (mult:V2SI
10100              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
10101              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
10102            (const_int 1)))))]
10103   "TARGET_SHMEDIA"
10104   "mmacnfx.wl   %2, %3, %0"
10105   [(set_attr "type" "mac_media")])
10106
10107 (define_insn "mulv2si3"
10108   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10109         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10110                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10111   "TARGET_SHMEDIA"
10112   "mmul.l       %1, %2, %0"
10113   [(set_attr "type" "d2mpy_media")])
10114
10115 (define_insn "mulv4hi3"
10116   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10117         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10118                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10119   "TARGET_SHMEDIA"
10120   "mmul.w       %1, %2, %0"
10121   [(set_attr "type" "dmpy_media")])
10122
10123 (define_insn "mmulfx_l"
10124   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10125         (ss_truncate:V2SI
10126          (ashiftrt:V2DI
10127           (mult:V2DI
10128            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
10129            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
10130           (const_int 31))))]
10131   "TARGET_SHMEDIA"
10132   "mmulfx.l     %1, %2, %0"
10133   [(set_attr "type" "d2mpy_media")])
10134
10135 (define_insn "mmulfx_w"
10136   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10137         (ss_truncate:V4HI
10138          (ashiftrt:V4SI
10139           (mult:V4SI
10140            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10141            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10142           (const_int 15))))]
10143   "TARGET_SHMEDIA"
10144   "mmulfx.w     %1, %2, %0"
10145   [(set_attr "type" "dmpy_media")])
10146
10147 (define_insn "mmulfxrp_w"
10148   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10149         (ss_truncate:V4HI
10150          (ashiftrt:V4SI
10151           (plus:V4SI
10152            (mult:V4SI
10153             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10154             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10155            (const_int 16384))
10156           (const_int 15))))]
10157   "TARGET_SHMEDIA"
10158   "mmulfxrp.w   %1, %2, %0"
10159   [(set_attr "type" "dmpy_media")])
10160
10161 (define_expand "mmulhi_wl"
10162   [(match_operand:V2SI 0 "arith_reg_dest" "")
10163    (match_operand:V4HI 1 "arith_reg_operand" "")
10164    (match_operand:V4HI 2 "arith_reg_operand" "")]
10165   "TARGET_SHMEDIA"
10166   "
10167 {
10168   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
10169              (operands[0], operands[1], operands[2]));
10170   DONE;
10171 }")
10172
10173 (define_expand "mmullo_wl"
10174   [(match_operand:V2SI 0 "arith_reg_dest" "")
10175    (match_operand:V4HI 1 "arith_reg_operand" "")
10176    (match_operand:V4HI 2 "arith_reg_operand" "")]
10177   "TARGET_SHMEDIA"
10178   "
10179 {
10180   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
10181              (operands[0], operands[1], operands[2]));
10182   DONE;
10183 }")
10184
10185 (define_insn "mmul23_wl"
10186   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10187         (vec_select:V2SI
10188          (mult:V4SI
10189           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10190           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10191          (parallel [(const_int 2) (const_int 3)])))]
10192   "TARGET_SHMEDIA"
10193   "* return (TARGET_LITTLE_ENDIAN
10194              ? \"mmulhi.wl      %1, %2, %0\"
10195              : \"mmullo.wl      %1, %2, %0\");"
10196   [(set_attr "type" "dmpy_media")])
10197
10198 (define_insn "mmul01_wl"
10199   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10200         (vec_select:V2SI
10201          (mult:V4SI
10202           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10203           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
10204          (parallel [(const_int 0) (const_int 1)])))]
10205   "TARGET_SHMEDIA"
10206   "* return (TARGET_LITTLE_ENDIAN
10207              ? \"mmullo.wl      %1, %2, %0\"
10208              : \"mmulhi.wl      %1, %2, %0\");"
10209   [(set_attr "type" "dmpy_media")])
10210
10211 (define_expand "mmulsum_wq"
10212   [(match_operand:DI 0 "arith_reg_dest" "")
10213    (match_operand:V4HI 1 "arith_reg_operand" "")
10214    (match_operand:V4HI 2 "arith_reg_operand" "")
10215    (match_operand:DI 3 "arith_reg_operand" "")]
10216   "TARGET_SHMEDIA"
10217   "
10218 {
10219   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
10220                                operands[1], operands[2]));
10221   DONE;
10222 }")
10223
10224 (define_insn "mmulsum_wq_i"
10225   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10226         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
10227          (plus:DI
10228           (plus:DI
10229            (vec_select:DI
10230             (mult:V4DI
10231              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
10232              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
10233             (parallel [(const_int 0)]))
10234            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
10235                                      (sign_extend:V4DI (match_dup 3)))
10236                           (parallel [(const_int 1)])))
10237           (plus:DI
10238            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
10239                                      (sign_extend:V4DI (match_dup 3)))
10240                           (parallel [(const_int 2)]))
10241            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
10242                                      (sign_extend:V4DI (match_dup 3)))
10243                           (parallel [(const_int 3)]))))))]
10244   "TARGET_SHMEDIA"
10245   "mmulsum.wq   %2, %3, %0"
10246   [(set_attr "type" "mac_media")])
10247
10248 (define_expand "mperm_w"
10249   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
10250    (match_operand:V4HI 1 "arith_reg_operand" "r")
10251    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
10252   "TARGET_SHMEDIA"
10253   "
10254 {
10255   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
10256              (operands[0], operands[1], operands[2]));
10257   DONE;
10258 }")
10259
10260 ; This use of vec_select isn't exactly correct according to rtl.texi
10261 ; (because not constant), but it seems a straightforward extension.
10262 (define_insn "mperm_w_little"
10263   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10264         (vec_select:V4HI
10265          (match_operand:V4HI 1 "arith_reg_operand" "r")
10266          (parallel
10267           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
10268                             (const_int 2) (const_int 0))
10269            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
10270            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
10271            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
10272   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
10273   "mperm.w      %1, %N2, %0"
10274   [(set_attr "type" "arith_media")])
10275
10276 (define_insn "mperm_w_big"
10277   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10278         (vec_select:V4HI
10279          (match_operand:V4HI 1 "arith_reg_operand" "r")
10280          (parallel
10281           [(zero_extract:QI (not:QI (match_operand:QI 2
10282                                      "extend_reg_or_0_operand" "rZ"))
10283                             (const_int 2) (const_int 0))
10284            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
10285            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
10286            (zero_extract:QI (not:QI (match_dup 2))
10287                             (const_int 2) (const_int 6))])))]
10288   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
10289   "mperm.w      %1, %N2, %0"
10290   [(set_attr "type" "arith_media")])
10291
10292 (define_insn "mperm_w0"
10293   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10294         (vec_duplicate:V4HI (truncate:HI (match_operand 1
10295                                           "trunc_hi_operand" "r"))))]
10296   "TARGET_SHMEDIA"
10297   "mperm.w      %1, r63, %0"
10298   [(set_attr "type" "arith_media")])
10299
10300 (define_expand "msad_ubq"
10301   [(match_operand:DI 0 "arith_reg_dest" "")
10302    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
10303    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
10304    (match_operand:DI 3 "arith_reg_operand" "")]
10305   "TARGET_SHMEDIA"
10306   "
10307 {
10308   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
10309                              operands[1], operands[2]));
10310   DONE;
10311 }")
10312
10313 (define_insn "msad_ubq_i"
10314   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10315         (plus:DI
10316          (plus:DI
10317           (plus:DI
10318            (plus:DI
10319             (match_operand:DI 1 "arith_reg_operand" "0")
10320             (abs:DI (vec_select:DI
10321                      (minus:V8DI
10322                       (zero_extend:V8DI
10323                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
10324                       (zero_extend:V8DI
10325                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
10326                      (parallel [(const_int 0)]))))
10327            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10328                                               (zero_extend:V8DI (match_dup 3)))
10329                                   (parallel [(const_int 1)]))))
10330           (plus:DI
10331            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10332                                               (zero_extend:V8DI (match_dup 3)))
10333                                   (parallel [(const_int 2)])))
10334            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10335                                               (zero_extend:V8DI (match_dup 3)))
10336                                   (parallel [(const_int 3)])))))
10337          (plus:DI
10338           (plus:DI
10339            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10340                                               (zero_extend:V8DI (match_dup 3)))
10341                                   (parallel [(const_int 4)])))
10342            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10343                                               (zero_extend:V8DI (match_dup 3)))
10344                                   (parallel [(const_int 5)]))))
10345           (plus:DI
10346            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10347                                               (zero_extend:V8DI (match_dup 3)))
10348                                   (parallel [(const_int 6)])))
10349            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
10350                                               (zero_extend:V8DI (match_dup 3)))
10351                                   (parallel [(const_int 7)])))))))]
10352   "TARGET_SHMEDIA"
10353   "msad.ubq     %N2, %N3, %0"
10354   [(set_attr "type" "mac_media")])
10355
10356 (define_insn "mshalds_l"
10357   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10358         (ss_truncate:V2SI
10359          (ashift:V2DI
10360           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
10361           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
10362                   (const_int 31)))))]
10363   "TARGET_SHMEDIA"
10364   "mshalds.l    %1, %2, %0"
10365   [(set_attr "type" "mcmp_media")])
10366
10367 (define_insn "mshalds_w"
10368   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10369         (ss_truncate:V4HI
10370          (ashift:V4SI
10371           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
10372           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
10373                   (const_int 15)))))]
10374   "TARGET_SHMEDIA"
10375   "mshalds.w    %1, %2, %0"
10376   [(set_attr "type" "mcmp_media")])
10377
10378 (define_insn "ashrv2si3"
10379   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10380         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10381                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10382   "TARGET_SHMEDIA"
10383   "mshard.l     %1, %2, %0"
10384   [(set_attr "type" "arith_media")])
10385
10386 (define_insn "ashrv4hi3"
10387   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10388         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10389                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10390   "TARGET_SHMEDIA"
10391   "mshard.w     %1, %2, %0"
10392   [(set_attr "type" "arith_media")])
10393
10394 (define_insn "mshards_q"
10395   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
10396         (ss_truncate:HI
10397          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
10398                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
10399   "TARGET_SHMEDIA"
10400   "mshards.q    %1, %N2, %0"
10401   [(set_attr "type" "mcmp_media")])
10402
10403 (define_expand "mshfhi_b"
10404   [(match_operand:V8QI 0 "arith_reg_dest" "")
10405    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10406    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
10407   "TARGET_SHMEDIA"
10408   "
10409 {
10410   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
10411              (operands[0], operands[1], operands[2]));
10412   DONE;
10413 }")
10414
10415 (define_expand "mshflo_b"
10416   [(match_operand:V8QI 0 "arith_reg_dest" "")
10417    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10418    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
10419   "TARGET_SHMEDIA"
10420   "
10421 {
10422   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
10423              (operands[0], operands[1], operands[2]));
10424   DONE;
10425 }")
10426
10427 (define_insn "mshf4_b"
10428   [(set
10429     (match_operand:V8QI 0 "arith_reg_dest" "=r")
10430     (vec_select:V8QI
10431      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10432                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
10433      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
10434                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
10435   "TARGET_SHMEDIA"
10436   "* return (TARGET_LITTLE_ENDIAN
10437              ? \"mshfhi.b       %N1, %N2, %0\"
10438              : \"mshflo.b       %N1, %N2, %0\");"
10439   [(set_attr "type" "arith_media")])
10440
10441 (define_insn "mshf0_b"
10442   [(set
10443     (match_operand:V8QI 0 "arith_reg_dest" "=r")
10444     (vec_select:V8QI
10445      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
10446                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
10447      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
10448                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
10449   "TARGET_SHMEDIA"
10450   "* return (TARGET_LITTLE_ENDIAN
10451              ? \"mshflo.b       %N1, %N2, %0\"
10452              : \"mshfhi.b       %N1, %N2, %0\");"
10453   [(set_attr "type" "arith_media")])
10454
10455 (define_expand "mshfhi_l"
10456   [(match_operand:V2SI 0 "arith_reg_dest" "")
10457    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10458    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
10459   "TARGET_SHMEDIA"
10460   "
10461 {
10462   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
10463              (operands[0], operands[1], operands[2]));
10464   DONE;
10465 }")
10466
10467 (define_expand "mshflo_l"
10468   [(match_operand:V2SI 0 "arith_reg_dest" "")
10469    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10470    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
10471   "TARGET_SHMEDIA"
10472   "
10473 {
10474   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
10475              (operands[0], operands[1], operands[2]));
10476   DONE;
10477 }")
10478
10479 (define_insn "mshf4_l"
10480   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10481         (vec_select:V2SI
10482          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10483                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
10484          (parallel [(const_int 1) (const_int 3)])))]
10485   "TARGET_SHMEDIA"
10486   "* return (TARGET_LITTLE_ENDIAN
10487              ? \"mshfhi.l       %N1, %N2, %0\"
10488              : \"mshflo.l       %N1, %N2, %0\");"
10489   [(set_attr "type" "arith_media")])
10490
10491 (define_insn "mshf0_l"
10492   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10493         (vec_select:V2SI
10494          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10495                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
10496          (parallel [(const_int 0) (const_int 2)])))]
10497   "TARGET_SHMEDIA"
10498   "* return (TARGET_LITTLE_ENDIAN
10499              ? \"mshflo.l       %N1, %N2, %0\"
10500              : \"mshfhi.l       %N1, %N2, %0\");"
10501   [(set_attr "type" "arith_media")])
10502
10503 (define_expand "mshfhi_w"
10504   [(match_operand:V4HI 0 "arith_reg_dest" "")
10505    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10506    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
10507   "TARGET_SHMEDIA"
10508   "
10509 {
10510   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
10511              (operands[0], operands[1], operands[2]));
10512   DONE;
10513 }")
10514
10515 (define_expand "mshflo_w"
10516   [(match_operand:V4HI 0 "arith_reg_dest" "")
10517    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10518    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
10519   "TARGET_SHMEDIA"
10520   "
10521 {
10522   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
10523              (operands[0], operands[1], operands[2]));
10524   DONE;
10525 }")
10526
10527 (define_insn "mshf4_w"
10528   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10529         (vec_select:V4HI
10530          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10531                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
10532          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
10533   "TARGET_SHMEDIA"
10534   "* return (TARGET_LITTLE_ENDIAN
10535              ? \"mshfhi.w       %N1, %N2, %0\"
10536              : \"mshflo.w       %N1, %N2, %0\");"
10537   [(set_attr "type" "arith_media")])
10538
10539 (define_insn "mshf0_w"
10540   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10541         (vec_select:V4HI
10542          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10543                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
10544          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
10545   "TARGET_SHMEDIA"
10546   "* return (TARGET_LITTLE_ENDIAN
10547              ? \"mshflo.w       %N1, %N2, %0\"
10548              : \"mshfhi.w       %N1, %N2, %0\");"
10549   [(set_attr "type" "arith_media")])
10550
10551 (define_insn "mshflo_w_x"
10552   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10553         (vec_select:V4HI
10554          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
10555                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
10556          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
10557   "TARGET_SHMEDIA"
10558   "mshflo.w     %N1, %N2, %0"
10559   [(set_attr "type" "arith_media")])
10560
10561 /* These are useful to expand ANDs and as combiner patterns.  */
10562 (define_insn_and_split "mshfhi_l_di"
10563   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
10564         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
10565                              (const_int 32))
10566                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
10567                         (const_int -4294967296))))]
10568   "TARGET_SHMEDIA"
10569   "@
10570         mshfhi.l        %N1, %N2, %0
10571         #"
10572   "TARGET_SHMEDIA && reload_completed
10573    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10574   [(set (match_dup 3) (match_dup 4))
10575    (set (match_dup 5) (match_dup 6))]
10576   "
10577 {
10578   operands[3] = gen_lowpart (SImode, operands[0]);
10579   operands[4] = gen_highpart (SImode, operands[1]);
10580   operands[5] = gen_highpart (SImode, operands[0]);
10581   operands[6] = gen_highpart (SImode, operands[2]);
10582 }"
10583   [(set_attr "type" "arith_media")])
10584
10585 (define_insn "*mshfhi_l_di_rev"
10586   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10587         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10588                         (const_int -4294967296))
10589                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10590                              (const_int 32))))]
10591   "TARGET_SHMEDIA"
10592   "mshfhi.l     %N2, %N1, %0"
10593   [(set_attr "type" "arith_media")])
10594
10595 (define_split
10596   [(set (match_operand:DI 0 "arith_reg_dest" "")
10597         (ior:DI (zero_extend:DI (match_operand:SI 1
10598                                               "extend_reg_or_0_operand" ""))
10599                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
10600                         (const_int -4294967296))))
10601    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
10602   "TARGET_SHMEDIA"
10603   [(const_int 0)]
10604   "
10605 {
10606   emit_insn (gen_ashldi3_media (operands[3],
10607                                 simplify_gen_subreg (DImode, operands[1],
10608                                                      SImode, 0),
10609                                 GEN_INT (32)));
10610   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
10611   DONE;
10612 }")
10613
10614 (define_insn "mshflo_l_di"
10615   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10616         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10617                         (const_int 4294967295))
10618                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10619                            (const_int 32))))]
10620
10621   "TARGET_SHMEDIA"
10622   "mshflo.l     %N1, %N2, %0"
10623   [(set_attr "type" "arith_media")])
10624
10625 (define_insn "*mshflo_l_di_rev"
10626   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10627         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10628                            (const_int 32))
10629                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10630                         (const_int 4294967295))))]
10631
10632   "TARGET_SHMEDIA"
10633   "mshflo.l     %N2, %N1, %0"
10634   [(set_attr "type" "arith_media")])
10635
10636 ;; Combiner pattern for trampoline initialization.
10637 (define_insn_and_split "*double_shori"
10638   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10639         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
10640                            (const_int 32))
10641                 (match_operand:DI 2 "const_int_operand" "n")))]
10642   "TARGET_SHMEDIA
10643    && INTVAL (operands[2]) == trunc_int_for_mode (INTVAL (operands[2]), SImode)"
10644   "#"
10645   "rtx_equal_p (operands[0], operands[1])"
10646   [(const_int 0)]
10647   "
10648 {
10649   HOST_WIDE_INT v = INTVAL (operands[2]);
10650
10651   emit_insn (gen_shori_media (operands[0], operands[0],
10652              gen_int_mode (INTVAL (operands[2]) >> 16, HImode)));
10653   emit_insn (gen_shori_media (operands[0], operands[0],
10654                               gen_int_mode (v, HImode)));
10655   DONE;
10656 }")
10657
10658
10659 (define_insn "*mshflo_l_di_x"
10660   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10661         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
10662                                  "rZ"))
10663                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
10664                            (const_int 32))))]
10665
10666   "TARGET_SHMEDIA"
10667   "mshflo.l     %N1, %N2, %0"
10668   [(set_attr "type" "arith_media")])
10669
10670 (define_insn_and_split "concat_v2sf"
10671   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
10672 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
10673         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
10674                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
10675
10676   "TARGET_SHMEDIA"
10677   "@
10678         mshflo.l        %N1, %N2, %0
10679         #
10680         #"
10681   "TARGET_SHMEDIA && reload_completed
10682    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10683   [(set (match_dup 3) (match_dup 1))
10684    (set (match_dup 4) (match_dup 2))]
10685   "
10686 {
10687   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
10688   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
10689 }"
10690   [(set_attr "type" "arith_media")])
10691
10692 (define_insn "*mshflo_l_di_x_rev"
10693   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10694         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
10695                            (const_int 32))
10696                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
10697
10698   "TARGET_SHMEDIA"
10699   "mshflo.l     %N2, %N1, %0"
10700   [(set_attr "type" "arith_media")])
10701
10702 (define_insn "ashlv2si3"
10703   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10704         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10705                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10706   "TARGET_SHMEDIA"
10707   "mshlld.l     %1, %2, %0"
10708   [(set_attr "type" "arith_media")])
10709
10710 (define_insn "ashlv4hi3"
10711   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10712         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10713                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10714   "TARGET_SHMEDIA"
10715   "mshlld.w     %1, %2, %0"
10716   [(set_attr "type" "arith_media")])
10717
10718 (define_insn "lshrv2si3"
10719   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10720         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10721                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10722   "TARGET_SHMEDIA"
10723   "mshlrd.l     %1, %2, %0"
10724   [(set_attr "type" "arith_media")])
10725
10726 (define_insn "lshrv4hi3"
10727   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10728         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10729                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10730   "TARGET_SHMEDIA"
10731   "mshlrd.w     %1, %2, %0"
10732   [(set_attr "type" "arith_media")])
10733
10734 (define_insn "subv2si3"
10735   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10736         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10737                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10738   "TARGET_SHMEDIA"
10739   "msub.l       %N1, %2, %0"
10740   [(set_attr "type" "arith_media")])
10741
10742 (define_insn "subv4hi3"
10743   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10744         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10745                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10746   "TARGET_SHMEDIA"
10747   "msub.w       %N1, %2, %0"
10748   [(set_attr "type" "arith_media")])
10749
10750 (define_insn "sssubv2si3"
10751   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10752         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
10753                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10754   "TARGET_SHMEDIA"
10755   "msubs.l      %N1, %2, %0"
10756   [(set_attr "type" "mcmp_media")])
10757
10758 (define_insn "ussubv8qi3"
10759   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10760         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10761                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
10762   "TARGET_SHMEDIA"
10763   "msubs.ub     %1, %2, %0"
10764   [(set_attr "type" "mcmp_media")])
10765
10766 (define_insn "sssubv4hi3"
10767   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10768         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
10769                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10770   "TARGET_SHMEDIA"
10771   "msubs.w      %N1, %2, %0"
10772   [(set_attr "type" "mcmp_media")])
10773
10774 ;; Floating Point Intrinsics
10775
10776 (define_insn "fcosa_s"
10777   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10778         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10779                    UNSPEC_FCOSA))]
10780   "TARGET_SHMEDIA"
10781   "fcosa.s      %1, %0"
10782   [(set_attr "type" "atrans_media")])
10783
10784 (define_insn "fsina_s"
10785   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10786         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10787                    UNSPEC_FSINA))]
10788   "TARGET_SHMEDIA"
10789   "fsina.s      %1, %0"
10790   [(set_attr "type" "atrans_media")])
10791
10792 (define_insn "fipr"
10793   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10794         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
10795                                                     "fp_arith_reg_operand" "f")
10796                                                    (match_operand:V4SF 2
10797                                                     "fp_arith_reg_operand" "f"))
10798                                          (parallel [(const_int 0)]))
10799                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10800                                          (parallel [(const_int 1)])))
10801                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10802                                          (parallel [(const_int 2)]))
10803                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10804                                          (parallel [(const_int 3)])))))]
10805   "TARGET_SHMEDIA"
10806   "fipr.s       %1, %2, %0"
10807   [(set_attr "type" "fparith_media")])
10808
10809 (define_insn "fsrra_s"
10810   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10811         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
10812                    UNSPEC_FSRRA))]
10813   "TARGET_SHMEDIA"
10814   "fsrra.s      %1, %0"
10815   [(set_attr "type" "atrans_media")])
10816
10817 (define_insn "ftrv"
10818   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
10819         (plus:V4SF
10820          (plus:V4SF
10821           (mult:V4SF
10822            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
10823                             (parallel [(const_int 0) (const_int 5)
10824                                        (const_int 10) (const_int 15)]))
10825            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
10826           (mult:V4SF
10827            (vec_select:V4SF (match_dup 1)
10828                             (parallel [(const_int 4) (const_int 9)
10829                                        (const_int 14) (const_int 3)]))
10830            (vec_select:V4SF (match_dup 2)
10831                             (parallel [(const_int 1) (const_int 2)
10832                                        (const_int 3) (const_int 0)]))))
10833          (plus:V4SF
10834           (mult:V4SF
10835            (vec_select:V4SF (match_dup 1)
10836                             (parallel [(const_int 8) (const_int 13)
10837                                        (const_int 2) (const_int 7)]))
10838            (vec_select:V4SF (match_dup 2)
10839                             (parallel [(const_int 2) (const_int 3)
10840                                        (const_int 0) (const_int 1)])))
10841           (mult:V4SF
10842            (vec_select:V4SF (match_dup 1)
10843                             (parallel [(const_int 12) (const_int 1)
10844                                        (const_int 6) (const_int 11)]))
10845            (vec_select:V4SF (match_dup 2)
10846                             (parallel [(const_int 3) (const_int 0)
10847                                        (const_int 1) (const_int 2)]))))))]
10848   "TARGET_SHMEDIA"
10849   "ftrv.s %1, %2, %0"
10850   [(set_attr "type" "fparith_media")])
10851
10852 (define_insn "nsb"
10853   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
10854         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10855                    UNSPEC_NSB))]
10856   "TARGET_SHMEDIA"
10857   "nsb  %1, %0"
10858   [(set_attr "type" "arith_media")])
10859
10860 (define_insn "nsbsi"
10861   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
10862         (zero_extend:SI
10863          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10864                     UNSPEC_NSB)))]
10865   "TARGET_SHMEDIA"
10866   "nsb  %1, %0"
10867   [(set_attr "type" "arith_media")])
10868
10869 (define_insn "nsbdi"
10870   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10871         (zero_extend:DI
10872          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10873                     UNSPEC_NSB)))]
10874   "TARGET_SHMEDIA"
10875   "nsb  %1, %0"
10876   [(set_attr "type" "arith_media")])
10877
10878 (define_expand "ffsdi2"
10879   [(set (match_operand:DI 0 "arith_reg_dest" "")
10880         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
10881   "TARGET_SHMEDIA"
10882   "
10883 {
10884   rtx scratch = gen_reg_rtx (DImode);
10885   rtx last;
10886
10887   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
10888   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
10889   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
10890   emit_insn (gen_nsbdi (scratch, scratch));
10891   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
10892   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
10893   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
10894   REG_NOTES (last)
10895     = gen_rtx_EXPR_LIST (REG_EQUAL,
10896                          gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
10897   DONE;
10898 }")
10899
10900 (define_expand "ffssi2"
10901   [(set (match_operand:SI 0 "arith_reg_dest" "")
10902         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
10903   "TARGET_SHMEDIA"
10904   "
10905 {
10906   rtx scratch = gen_reg_rtx (SImode);
10907   rtx discratch = gen_reg_rtx (DImode);
10908   rtx last;
10909
10910   emit_insn (gen_adddi3 (discratch,
10911                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
10912                          constm1_rtx));
10913   emit_insn (gen_andcdi3 (discratch,
10914                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
10915                           discratch));
10916   emit_insn (gen_nsbsi (scratch, discratch));
10917   last = emit_insn (gen_subsi3 (operands[0],
10918                                 force_reg (SImode, GEN_INT (63)), scratch));
10919   REG_NOTES (last)
10920     = gen_rtx_EXPR_LIST (REG_EQUAL,
10921                          gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
10922   DONE;
10923 }")
10924
10925 (define_insn "byterev"
10926   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10927         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10928                          (parallel [(const_int 7) (const_int 6) (const_int 5)
10929                                     (const_int 4) (const_int 3) (const_int 2)
10930                                     (const_int 1) (const_int 0)])))]
10931   "TARGET_SHMEDIA"
10932   "byterev      %1, %0"
10933   [(set_attr "type" "arith_media")])
10934
10935 (define_insn "prefetch"
10936   [(prefetch (match_operand:QI 0 "address_operand" "p")
10937              (match_operand:SI 1 "const_int_operand" "n")
10938              (match_operand:SI 2 "const_int_operand" "n"))]
10939   "TARGET_SHMEDIA || TARGET_HARD_SH4"
10940   "*
10941 {
10942   if (TARGET_HARD_SH4)
10943     return \"pref @%0\";
10944   operands[0] = gen_rtx_MEM (QImode, operands[0]);
10945   output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
10946   return \"\";
10947 }"
10948   [(set_attr "type" "other")])
10949