OSDN Git Service

e6d80300cddf7e9aa34b3d5780265ebd55ff21be
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;;  2003, 2004, 2005, 2006 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, 51 Franklin Street, Fifth Floor,
22 ;; Boston, MA 02110-1301, 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   (UNSPEC_DIV_INV_M0    30)
147   (UNSPEC_DIV_INV_M1    31)
148   (UNSPEC_DIV_INV_M2    32)
149   (UNSPEC_DIV_INV_M3    33)
150   (UNSPEC_DIV_INV20     34)
151   (UNSPEC_DIV_INV_TABLE 37)
152   (UNSPEC_ASHIFTRT      35)
153   (UNSPEC_THUNK         36)
154   (UNSPEC_SP_SET        40)
155   (UNSPEC_SP_TEST       41)
156   (UNSPEC_MOVUA         42)
157
158   ;; These are used with unspec_volatile.
159   (UNSPECV_BLOCKAGE     0)
160   (UNSPECV_ALIGN        1)
161   (UNSPECV_CONST2       2)
162   (UNSPECV_CONST4       4)
163   (UNSPECV_CONST8       6)
164   (UNSPECV_WINDOW_END   10)
165   (UNSPECV_CONST_END    11)
166 ])
167
168 ;; -------------------------------------------------------------------------
169 ;; Attributes
170 ;; -------------------------------------------------------------------------
171
172 ;; Target CPU.
173
174 (define_attr "cpu"
175  "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
176   (const (symbol_ref "sh_cpu_attr")))
177
178 (define_attr "endian" "big,little"
179  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
180                       (const_string "little") (const_string "big"))))
181
182 ;; Indicate if the default fpu mode is single precision.
183 (define_attr "fpu_single" "yes,no"
184   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
185                          (const_string "yes") (const_string "no"))))
186
187 (define_attr "fmovd" "yes,no"
188   (const (if_then_else (symbol_ref "TARGET_FMOVD")
189                        (const_string "yes") (const_string "no"))))
190 ;; pipeline model
191 (define_attr "pipe_model" "sh1,sh4,sh5media"
192   (const
193    (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
194           (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
195          (const_string "sh1"))))
196
197 ;; cbranch      conditional branch instructions
198 ;; jump         unconditional jumps
199 ;; arith        ordinary arithmetic
200 ;; arith3       a compound insn that behaves similarly to a sequence of
201 ;;              three insns of type arith
202 ;; arith3b      like above, but might end with a redirected branch
203 ;; load         from memory
204 ;; load_si      Likewise, SImode variant for general register.
205 ;; fload        Likewise, but load to fp register.
206 ;; store        to memory
207 ;; fstore       floating point register to memory
208 ;; move         general purpose register to register
209 ;; movi8        8 bit immediate to general purpose register
210 ;; mt_group     other sh4 mt instructions
211 ;; fmove        register to register, floating point
212 ;; smpy         word precision integer multiply
213 ;; dmpy         longword or doublelongword precision integer multiply
214 ;; return       rts
215 ;; pload        load of pr reg, which can't be put into delay slot of rts
216 ;; prset        copy register to pr reg, ditto
217 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
218 ;; prget        copy pr to register, ditto
219 ;; pcload       pc relative load of constant value
220 ;; pcfload      Likewise, but load to fp register.
221 ;; pcload_si    Likewise, SImode variant for general register.
222 ;; rte          return from exception
223 ;; sfunc        special function call with known used registers
224 ;; call         function call
225 ;; fp           floating point
226 ;; fpscr_toggle toggle a bit in the fpscr
227 ;; fdiv         floating point divide (or square root)
228 ;; gp_fpul      move from general purpose register to fpul
229 ;; fpul_gp      move from fpul to general purpose register
230 ;; mac_gp       move from mac[lh] to general purpose register
231 ;; gp_mac       move from general purpose register to mac[lh]
232 ;; mac_mem      move from mac[lh] to memory
233 ;; mem_mac      move from memory to mac[lh]
234 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
235 ;; ftrc_s       fix_truncsfsi2_i4
236 ;; dfdiv        double precision floating point divide (or square root)
237 ;; cwb          ic_invalidate_line_i
238 ;; movua        SH4a unaligned load
239 ;; fsrra        square root reciprocal approximate
240 ;; fsca         sine and cosine approximate
241 ;; tls_load     load TLS related address
242 ;; arith_media  SHmedia arithmetic, logical, and shift instructions
243 ;; cbranch_media SHmedia conditional branch instructions
244 ;; cmp_media    SHmedia compare instructions
245 ;; dfdiv_media  SHmedia double precision divide and square root
246 ;; dfmul_media  SHmedia double precision multiply instruction
247 ;; dfparith_media SHmedia double precision floating point arithmetic
248 ;; dfpconv_media SHmedia double precision floating point conversions
249 ;; dmpy_media   SHmedia longword multiply
250 ;; fcmp_media   SHmedia floating point compare instructions
251 ;; fdiv_media   SHmedia single precision divide and square root
252 ;; fload_media  SHmedia floating point register load instructions
253 ;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
254 ;; fparith_media SHmedia single precision floating point arithmetic
255 ;; fpconv_media SHmedia single precision floating point conversions
256 ;; fstore_media SHmedia floating point register store instructions
257 ;; gettr_media  SHmedia gettr instruction
258 ;; invalidate_line_media SHmedia invalidate_line sequence
259 ;; jump_media   SHmedia unconditional branch instructions
260 ;; load_media   SHmedia general register load instructions
261 ;; pt_media     SHmedia pt instruction (expanded by assembler)
262 ;; ptabs_media  SHmedia ptabs instruction
263 ;; store_media  SHmedia general register store instructions
264 ;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
265 ;; mac_media    SHmedia mac-style fixed point operations
266 ;; d2mpy_media  SHmedia: two 32 bit integer multiplies
267 ;; atrans_media SHmedia approximate transcendental functions
268 ;; ustore_media SHmedia unaligned stores
269 ;; nil          no-op move, will be deleted.
270
271 (define_attr "type"
272  "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,gp_mac,mac_mem,mem_mac,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"
273   (const_string "other"))
274
275 ;; We define a new attribute namely "insn_class".We use
276 ;; this for the DFA based pipeline description.
277 ;;
278 ;; mt_group      SH4 "mt" group instructions.
279 ;;
280 ;; ex_group      SH4 "ex" group instructions.
281 ;;
282 ;; ls_group      SH4 "ls" group instructions.
283 ;;
284
285 (define_attr "insn_class"
286   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
287   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
288          (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
289          (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
290          (eq_attr "type" "cbranch,jump") (const_string "br_group")
291          (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
292            (const_string "fe_group")
293          (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,gp_mac,mac_mem,mem_mac") (const_string "co_group")]
294         (const_string "none")))
295 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
296 ;; so these do not belong in an insn group, although they are modeled
297 ;; with their own define_insn_reservations.
298
299 ;; Indicate what precision must be selected in fpscr for this insn, if any.
300
301 (define_attr "fp_mode" "single,double,none" (const_string "none"))
302
303 ;; Indicate if the fpu mode is set by this instruction
304 ;; "unknown" must have the value as "none" in fp_mode, and means
305 ;; that the instruction/abi has left the processor in an unknown
306 ;; state.
307 ;; "none" means that nothing has changed and no mode is set.
308 ;; This attribute is only used for the Renesas ABI.
309 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
310
311 ; If a conditional branch destination is within -252..258 bytes away
312 ; from the instruction it can be 2 bytes long.  Something in the
313 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
314 ; branches are initially assumed to be 16 bytes long.
315 ; In machine_dependent_reorg, we split all branches that are longer than
316 ; 2 bytes.
317
318 ;; The maximum range used for SImode constant pool entries is 1018.  A final
319 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
320 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
321 ;; instruction around the pool table, 2 bytes of alignment before the table,
322 ;; and 30 bytes of alignment after the table.  That gives a maximum total
323 ;; pool size of 1058 bytes.
324 ;; Worst case code/pool content size ratio is 1:2 (using asms).
325 ;; Thus, in the worst case, there is one instruction in front of a maximum
326 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
327 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
328 ;; If we have a forward branch, the initial table will be put after the
329 ;; unconditional branch.
330 ;;
331 ;; ??? We could do much better by keeping track of the actual pcloads within
332 ;; the branch range and in the pcload range in front of the branch range.
333
334 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
335 ;; inside an le.
336 (define_attr "short_cbranch_p" "no,yes"
337   (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
338          (const_string "no")
339          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
340          (const_string "yes")
341          (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
342          (const_string "no")
343          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
344          (const_string "yes")
345          ] (const_string "no")))
346
347 (define_attr "med_branch_p" "no,yes"
348   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
349               (const_int 1988))
350          (const_string "yes")
351          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
352          (const_string "no")
353          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
354               (const_int 8186))
355          (const_string "yes")
356          ] (const_string "no")))
357
358 (define_attr "med_cbranch_p" "no,yes"
359   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
360               (const_int 1986))
361          (const_string "yes")
362          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
363          (const_string "no")
364          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
365                (const_int 8184))
366          (const_string "yes")
367          ] (const_string "no")))
368
369 (define_attr "braf_branch_p" "no,yes"
370   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
371          (const_string "no")
372          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
373               (const_int 20660))
374          (const_string "yes")
375          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
376          (const_string "no")
377          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
378               (const_int 65530))
379          (const_string "yes")
380          ] (const_string "no")))
381
382 (define_attr "braf_cbranch_p" "no,yes"
383   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
384          (const_string "no")
385          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
386               (const_int 20658))
387          (const_string "yes")
388          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
389          (const_string "no")
390          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
391               (const_int 65528))
392          (const_string "yes")
393          ] (const_string "no")))
394
395 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
396 ; For wider ranges, we need a combination of a code and a data part.
397 ; If we can get a scratch register for a long range jump, the code
398 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
399 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
400 ; long; otherwise, it must be 6 bytes long.
401
402 ; All other instructions are two bytes long by default.
403
404 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
405 ;; but getattrtab doesn't understand this.
406 (define_attr "length" ""
407   (cond [(eq_attr "type" "cbranch")
408          (cond [(eq_attr "short_cbranch_p" "yes")
409                 (const_int 2)
410                 (eq_attr "med_cbranch_p" "yes")
411                 (const_int 6)
412                 (eq_attr "braf_cbranch_p" "yes")
413                 (const_int 12)
414 ;; ??? using pc is not computed transitively.
415                 (ne (match_dup 0) (match_dup 0))
416                 (const_int 14)
417                 (ne (symbol_ref ("flag_pic")) (const_int 0))
418                 (const_int 24)
419                 ] (const_int 16))
420          (eq_attr "type" "jump")
421          (cond [(eq_attr "med_branch_p" "yes")
422                 (const_int 2)
423                 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
424                          (symbol_ref "INSN"))
425                      (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
426                          (symbol_ref "code_for_indirect_jump_scratch")))
427                 (cond [(eq_attr "braf_branch_p" "yes")
428                        (const_int 6)
429                        (eq (symbol_ref "flag_pic") (const_int 0))
430                        (const_int 10)
431                        (ne (symbol_ref "TARGET_SH2") (const_int 0))
432                        (const_int 10)] (const_int 18))
433                 (eq_attr "braf_branch_p" "yes")
434                 (const_int 10)
435 ;; ??? using pc is not computed transitively.
436                 (ne (match_dup 0) (match_dup 0))
437                 (const_int 12)
438                 (ne (symbol_ref ("flag_pic")) (const_int 0))
439                 (const_int 22)
440                 ] (const_int 14))
441          (eq_attr "type" "pt_media")
442          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
443                        (const_int 20) (const_int 12))
444          (and (eq_attr "type" "jump_media")
445               (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
446          (const_int 8)
447          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
448                          (const_int 4)
449                          (const_int 2))))
450
451 ;; DFA descriptions for the pipelines
452
453 (include "sh1.md")
454 (include "shmedia.md")
455 (include "sh4.md")
456
457 (include "predicates.md")
458
459 ;; Definitions for filling delay slots
460
461 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
462
463 ;; ??? This should be (nil) instead of (const_int 0)
464 (define_attr "hit_stack" "yes,no"
465         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
466                    (const_int 0))
467                (const_string "no")]
468               (const_string "yes")))
469
470 (define_attr "interrupt_function" "no,yes"
471   (const (symbol_ref "current_function_interrupt")))
472
473 (define_attr "in_delay_slot" "yes,no"
474   (cond [(eq_attr "type" "cbranch") (const_string "no")
475          (eq_attr "type" "pcload,pcload_si") (const_string "no")
476          (eq_attr "needs_delay_slot" "yes") (const_string "no")
477          (eq_attr "length" "2") (const_string "yes")
478          ] (const_string "no")))
479
480 (define_attr "cond_delay_slot" "yes,no"
481   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
482          ] (const_string "no")))
483
484 (define_attr "is_sfunc" ""
485   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
486
487 (define_attr "is_mac_media" ""
488   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
489
490 (define_attr "branch_zero" "yes,no"
491   (cond [(eq_attr "type" "!cbranch") (const_string "no")
492          (ne (symbol_ref "(next_active_insn (insn)\
493                            == (prev_active_insn\
494                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
495                           && get_attr_length (next_active_insn (insn)) == 2")
496              (const_int 0))
497          (const_string "yes")]
498         (const_string "no")))
499
500 ;; SH4 Double-precision computation with double-precision result -
501 ;; the two halves are ready at different times.
502 (define_attr "dfp_comp" "yes,no"
503   (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
504         (const_string "no")))
505
506 ;; Insns for which the latency of a preceding fp insn is decreased by one.
507 (define_attr "late_fp_use" "yes,no" (const_string "no"))
508 ;; And feeding insns for which this relevant.
509 (define_attr "any_fp_comp" "yes,no"
510   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
511          (const_string "yes")]
512         (const_string "no")))
513
514 (define_attr "any_int_load" "yes,no"
515   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
516          (const_string "yes")]
517         (const_string "no")))
518
519 (define_attr "highpart" "user, ignore, extend, depend, must_split"
520   (const_string "user"))
521
522 (define_delay
523   (eq_attr "needs_delay_slot" "yes")
524   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
525
526 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
527 ;; and thus we can't put a pop instruction in its delay slot.
528 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
529 ;; instruction can go in the delay slot.
530
531 ;; Since a normal return (rts) implicitly uses the PR register,
532 ;; we can't allow PR register loads in an rts delay slot.
533
534 (define_delay
535   (eq_attr "type" "return")
536   [(and (eq_attr "in_delay_slot" "yes")
537         (ior (and (eq_attr "interrupt_function" "no")
538                   (eq_attr "type" "!pload,prset"))
539              (and (eq_attr "interrupt_function" "yes")
540                   (ior
541                    (ne (symbol_ref "TARGET_SH3") (const_int 0))
542                    (eq_attr "hit_stack" "no"))))) (nil) (nil)])
543
544 ;; Since a call implicitly uses the PR register, we can't allow
545 ;; a PR register store in a jsr delay slot.
546
547 (define_delay
548   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
549   [(and (eq_attr "in_delay_slot" "yes")
550         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
551
552 ;; Say that we have annulled true branches, since this gives smaller and
553 ;; faster code when branches are predicted as not taken.
554
555 ;; ??? The non-annulled condition should really be "in_delay_slot",
556 ;; but insns that can be filled in non-annulled get priority over insns
557 ;; that can only be filled in anulled.
558
559 (define_delay
560   (and (eq_attr "type" "cbranch")
561        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
562   ;; SH2e has a hardware bug that pretty much prohibits the use of
563   ;; annuled delay slots.
564   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
565                                           (not (eq_attr "cpu" "sh2e"))) (nil)])
566 \f
567 ;; -------------------------------------------------------------------------
568 ;; SImode signed integer comparisons
569 ;; -------------------------------------------------------------------------
570
571 (define_insn ""
572   [(set (reg:SI T_REG)
573         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
574                        (match_operand:SI 1 "arith_operand" "K08,r"))
575                (const_int 0)))]
576   "TARGET_SH1"
577   "tst  %1,%0"
578   [(set_attr "type" "mt_group")])
579
580 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
581 ;; That would still allow reload to create cmpi instructions, but would
582 ;; perhaps allow forcing the constant into a register when that is better.
583 ;; Probably should use r0 for mem/imm compares, but force constant into a
584 ;; register for pseudo/imm compares.
585
586 (define_insn "cmpeqsi_t"
587   [(set (reg:SI T_REG)
588         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
589                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
590   "TARGET_SH1"
591   "@
592         tst     %0,%0
593         cmp/eq  %1,%0
594         cmp/eq  %1,%0"
595    [(set_attr "type" "mt_group")])
596
597 (define_insn "cmpgtsi_t"
598   [(set (reg:SI T_REG)
599         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
600                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
601   "TARGET_SH1"
602   "@
603         cmp/gt  %1,%0
604         cmp/pl  %0"
605    [(set_attr "type" "mt_group")])
606
607 (define_insn "cmpgesi_t"
608   [(set (reg:SI T_REG)
609         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
610                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
611   "TARGET_SH1"
612   "@
613         cmp/ge  %1,%0
614         cmp/pz  %0"
615    [(set_attr "type" "mt_group")])
616
617 ;; -------------------------------------------------------------------------
618 ;; SImode compare and branch
619 ;; -------------------------------------------------------------------------
620
621 (define_expand "cbranchsi4"
622   [(set (pc)
623         (if_then_else (match_operator 0 "comparison_operator"
624                         [(match_operand:SI 1 "arith_operand" "")
625                          (match_operand:SI 2 "arith_operand" "")])
626                       (label_ref (match_operand 3 "" ""))
627                       (pc)))
628    (clobber (reg:SI T_REG))]
629   "TARGET_CBRANCHDI4"
630   "expand_cbranchsi4 (operands, CODE_FOR_nothing, -1); DONE;")
631
632 ;; -------------------------------------------------------------------------
633 ;; SImode unsigned integer comparisons
634 ;; -------------------------------------------------------------------------
635
636 (define_insn_and_split "cmpgeusi_t"
637   [(set (reg:SI T_REG)
638         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
639                 (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
640   "TARGET_SH1"
641   "cmp/hs       %1,%0"
642   "&& operands[0] == CONST0_RTX (SImode)"
643   [(pc)]
644   "
645 {
646   emit_insn (gen_sett ());
647   DONE;
648 }"
649    [(set_attr "type" "mt_group")])
650
651 (define_insn "cmpgtusi_t"
652   [(set (reg:SI T_REG)
653         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
654                 (match_operand:SI 1 "arith_reg_operand" "r")))]
655   "TARGET_SH1"
656   "cmp/hi       %1,%0"
657    [(set_attr "type" "mt_group")])
658
659 ;; We save the compare operands in the cmpxx patterns and use them when
660 ;; we generate the branch.
661
662 (define_expand "cmpsi"
663   [(set (reg:SI T_REG)
664         (compare (match_operand:SI 0 "cmpsi_operand" "")
665                  (match_operand:SI 1 "arith_operand" "")))]
666   "TARGET_SH1 || TARGET_SHMEDIA"
667   "
668 {
669   if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
670       && GET_CODE (operands[1]) != CONST_INT)
671     operands[0] = copy_to_mode_reg (SImode, operands[0]);
672   sh_compare_op0 = operands[0];
673   sh_compare_op1 = operands[1];
674   DONE;
675 }")
676 \f
677 ;; -------------------------------------------------------------------------
678 ;; DImode compare and branch
679 ;; -------------------------------------------------------------------------
680
681
682 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
683 ;; Therefore, we aim to have a set of three branches that go straight to the
684 ;; destination, i.e. only one of them is taken at any one time.
685 ;; This mechanism should also be slightly better for the sh4-200.
686
687 (define_expand "cbranchdi4"
688   [(set (pc)
689         (if_then_else (match_operator 0 "comparison_operator"
690                         [(match_operand:DI 1 "arith_operand" "")
691                          (match_operand:DI 2 "arith_operand" "")])
692                       (label_ref (match_operand 3 "" ""))
693                       (pc)))
694    (clobber (match_dup 4))
695    (clobber (reg:SI T_REG))]
696   "TARGET_CBRANCHDI4"
697   "
698 {
699   enum rtx_code comparison;
700
701   if (TARGET_EXPAND_CBRANCHDI4)
702     {
703       if (expand_cbranchdi4 (operands, CODE_FOR_nothing))
704         DONE;
705     }
706   comparison = prepare_cbranch_operands (operands, DImode, CODE_FOR_nothing);
707   if (comparison != GET_CODE (operands[0]))
708     operands[0]
709       = gen_rtx_fmt_ee (VOIDmode, comparison, operands[1], operands[2]);
710    operands[4] = gen_rtx_SCRATCH (SImode);
711 }")
712
713 (define_insn_and_split "cbranchdi4_i"
714   [(set (pc)
715         (if_then_else (match_operator 0 "comparison_operator"
716                         [(match_operand:DI 1 "arith_operand" "r,r")
717                          (match_operand:DI 2 "arith_operand" "rN,i")])
718                       (label_ref (match_operand 3 "" ""))
719                       (pc)))
720    (clobber (match_scratch:SI 4 "=X,&r"))
721    (clobber (reg:SI T_REG))]
722   "TARGET_CBRANCHDI4"
723   "#"
724   "&& reload_completed"
725   [(pc)]
726   "
727 {
728   if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
729     FAIL;
730   DONE;
731 }")
732
733 ;; -------------------------------------------------------------------------
734 ;; DImode signed integer comparisons
735 ;; -------------------------------------------------------------------------
736
737 (define_insn ""
738   [(set (reg:SI T_REG)
739         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
740                        (match_operand:DI 1 "arith_operand" "r"))
741                (const_int 0)))]
742   "TARGET_SH1"
743   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
744                                  insn, operands);"
745   [(set_attr "length" "6")
746    (set_attr "type" "arith3b")])
747
748 (define_insn "cmpeqdi_t"
749   [(set (reg:SI T_REG)
750         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
751                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
752   "TARGET_SH1"
753   "@
754         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
755         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
756   [(set_attr "length" "6")
757    (set_attr "type" "arith3b")])
758
759 (define_split
760   [(set (reg:SI T_REG)
761         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
762                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
763 ;; If we applied this split when not optimizing, it would only be
764 ;; applied during the machine-dependent reorg, when no new basic blocks
765 ;; may be created.
766   "TARGET_SH1 && reload_completed && optimize"
767   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
768    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
769                            (label_ref (match_dup 6))
770                            (pc)))
771    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
772    (match_dup 6)]
773   "
774 {
775   operands[2]
776     = gen_rtx_REG (SImode,
777                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
778   operands[3]
779     = (operands[1] == const0_rtx
780        ? const0_rtx
781        : gen_rtx_REG (SImode,
782                       true_regnum (operands[1])
783                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
784   operands[4] = gen_lowpart (SImode, operands[0]);
785   operands[5] = gen_lowpart (SImode, operands[1]);
786   operands[6] = gen_label_rtx ();
787 }")
788
789 (define_insn "cmpgtdi_t"
790   [(set (reg:SI T_REG)
791         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
792                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
793   "TARGET_SH2"
794   "@
795         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
796         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
797   [(set_attr "length" "8")
798    (set_attr "type" "arith3")])
799
800 (define_insn "cmpgedi_t"
801   [(set (reg:SI T_REG)
802         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
803                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
804   "TARGET_SH2"
805   "@
806         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
807         cmp/pz\\t%S0"
808   [(set_attr "length" "8,2")
809    (set_attr "type" "arith3,mt_group")])
810 \f
811 ;; -------------------------------------------------------------------------
812 ;; DImode unsigned integer comparisons
813 ;; -------------------------------------------------------------------------
814
815 (define_insn "cmpgeudi_t"
816   [(set (reg:SI T_REG)
817         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
818                 (match_operand:DI 1 "arith_reg_operand" "r")))]
819   "TARGET_SH2"
820   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
821   [(set_attr "length" "8")
822    (set_attr "type" "arith3")])
823
824 (define_insn "cmpgtudi_t"
825   [(set (reg:SI T_REG)
826         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
827                 (match_operand:DI 1 "arith_reg_operand" "r")))]
828   "TARGET_SH2"
829   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
830   [(set_attr "length" "8")
831    (set_attr "type" "arith3")])
832
833 (define_insn "cmpeqsi_media"
834   [(set (match_operand:SI 0 "register_operand" "=r")
835         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
836                (match_operand:SI 2 "cmp_operand" "Nr")))]
837   "TARGET_SHMEDIA"
838   "cmpeq        %1, %N2, %0"
839   [(set_attr "type" "cmp_media")])
840
841 (define_insn "cmpeqdi_media"
842   [(set (match_operand:SI 0 "register_operand" "=r")
843         (eq:SI (match_operand:DI 1 "register_operand" "%r")
844                (match_operand:DI 2 "cmp_operand" "Nr")))]
845   "TARGET_SHMEDIA"
846   "cmpeq        %1, %N2, %0"
847   [(set_attr "type" "cmp_media")])
848
849 (define_insn "cmpgtsi_media"
850   [(set (match_operand:SI 0 "register_operand" "=r")
851         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
852                (match_operand:SI 2 "cmp_operand" "rN")))]
853   "TARGET_SHMEDIA"
854   "cmpgt        %N1, %N2, %0"
855   [(set_attr "type" "cmp_media")])
856
857 (define_insn "cmpgtdi_media"
858   [(set (match_operand:SI 0 "register_operand" "=r")
859         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
860                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
861   "TARGET_SHMEDIA"
862   "cmpgt        %N1, %N2, %0"
863   [(set_attr "type" "cmp_media")])
864
865 (define_insn "cmpgtusi_media"
866   [(set (match_operand:SI 0 "register_operand" "=r")
867         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
868                 (match_operand:SI 2 "cmp_operand" "rN")))]
869   "TARGET_SHMEDIA"
870   "cmpgtu       %N1, %N2, %0"
871   [(set_attr "type" "cmp_media")])
872
873 (define_insn "cmpgtudi_media"
874   [(set (match_operand:SI 0 "register_operand" "=r")
875         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
876                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
877   "TARGET_SHMEDIA"
878   "cmpgtu       %N1, %N2, %0"
879   [(set_attr "type" "cmp_media")])
880
881 ; These two patterns are for combine.
882 (define_insn "*cmpne0sisi_media"
883   [(set (match_operand:SI 0 "register_operand" "=r")
884         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
885   "TARGET_SHMEDIA"
886   "cmpgtu       %1,r63,%0"
887   [(set_attr "type" "cmp_media")])
888
889 ;; We save the compare operands in the cmpxx patterns and use them when
890 ;; we generate the branch.
891
892 (define_expand "cmpdi"
893   [(set (reg:SI T_REG)
894         (compare (match_operand:DI 0 "arith_operand" "")
895                  (match_operand:DI 1 "arith_operand" "")))]
896   "TARGET_SH2 || TARGET_SHMEDIA"
897   "
898 {
899   sh_compare_op0 = operands[0];
900   sh_compare_op1 = operands[1];
901   DONE;
902 }")
903 ;; -------------------------------------------------------------------------
904 ;; Conditional move instructions
905 ;; -------------------------------------------------------------------------
906
907 ;; The insn names may seem reversed, but note that cmveq performs the move
908 ;; if op1 == 0, and cmvne does it if op1 != 0.
909
910 (define_insn "movdicc_false"
911   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
912         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
913                              (const_int 0))
914          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
915          (match_operand:DI 3 "arith_reg_operand" "0")))]
916   "TARGET_SHMEDIA"
917   "cmveq        %1, %N2, %0"
918   [(set_attr "type" "arith_media")])
919
920 (define_insn "movdicc_true"
921   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
922         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
923                              (const_int 0))
924          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
925          (match_operand:DI 3 "arith_reg_operand" "0")))]
926   "TARGET_SHMEDIA"
927   "cmvne        %1, %N2, %0"
928   [(set_attr "type" "arith_media")])
929
930 (define_peephole2
931   [(set (match_operand:DI 0 "arith_reg_dest" "")
932         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
933                            [(match_operand:DI 1 "arith_reg_operand" "")
934                             (const_int 0)])
935          (match_operand:DI 2 "arith_reg_dest" "")
936          (match_dup 0)))
937    (set (match_dup 2) (match_dup 0))]
938   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
939   [(set (match_dup 2)
940         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
941   "
942 {
943   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
944                                 VOIDmode, operands[1], CONST0_RTX (DImode));
945 }")
946
947 (define_peephole2
948   [(set (match_operand:DI 0 "general_movdst_operand" "")
949         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
950    (set (match_operand:DI 2 "arith_reg_dest" "")
951         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
952                            [(match_operand:DI 3 "arith_reg_operand" "")
953                             (const_int 0)])
954          (match_dup 0)
955          (match_dup 2)))]
956   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
957   [(set (match_dup 2)
958         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
959   "")
960
961 (define_expand "movdicc"
962   [(set (match_operand:DI 0 "register_operand" "")
963         (if_then_else:DI (match_operand 1 "comparison_operator" "")
964                          (match_operand:DI 2 "register_operand" "")
965                          (match_operand:DI 3 "register_operand" "")))]
966   "TARGET_SHMEDIA"
967   "
968 {
969   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
970       && GET_MODE (sh_compare_op0) == DImode
971       && sh_compare_op1 == const0_rtx)
972     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
973                                   sh_compare_op0, sh_compare_op1);
974   else
975     {
976       rtx tmp;
977
978       if (no_new_pseudos)
979         FAIL;
980
981       tmp = gen_reg_rtx (DImode);
982
983       switch (GET_CODE (operands[1]))
984         {
985         case EQ:
986           emit_insn (gen_seq (tmp));
987           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
988           break;
989
990         case NE:
991           emit_insn (gen_seq (tmp));
992           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
993           break;
994
995         case GT:
996           emit_insn (gen_sgt (tmp));
997           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
998           break;
999
1000         case LT:
1001           emit_insn (gen_slt (tmp));
1002           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1003           break;
1004
1005         case GE:
1006           emit_insn (gen_slt (tmp));
1007           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1008           break;
1009
1010         case LE:
1011           emit_insn (gen_sgt (tmp));
1012           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1013           break;
1014
1015         case GTU:
1016           emit_insn (gen_sgtu (tmp));
1017           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1018           break;
1019
1020         case LTU:
1021           emit_insn (gen_sltu (tmp));
1022           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1023           break;
1024
1025         case GEU:
1026           emit_insn (gen_sltu (tmp));
1027           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1028           break;
1029
1030         case LEU:
1031           emit_insn (gen_sgtu (tmp));
1032           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1033           break;
1034
1035         case UNORDERED:
1036           emit_insn (gen_sunordered (tmp));
1037           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1038           break;
1039
1040         case ORDERED:
1041           emit_insn (gen_sunordered (tmp));
1042           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1043           break;
1044
1045         case UNEQ:
1046         case UNGE:
1047         case UNGT:
1048         case UNLE:
1049         case UNLT:
1050         case LTGT:
1051           FAIL;
1052
1053         default:
1054           gcc_unreachable ();
1055         }
1056     }
1057 }")
1058
1059 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1060 ;; SImode to DImode.
1061 (define_insn "movsicc_false"
1062   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1063         (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1064                           (const_int 0))
1065          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1066          (match_operand:SI 3 "arith_reg_operand" "0")))]
1067   "TARGET_SHMEDIA"
1068   "cmveq        %1, %N2, %0"
1069   [(set_attr "type" "arith_media")])
1070
1071 (define_insn "movsicc_true"
1072   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1073         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1074                           (const_int 0))
1075          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1076          (match_operand:SI 3 "arith_reg_operand" "0")))]
1077   "TARGET_SHMEDIA"
1078   "cmvne        %1, %N2, %0"
1079   [(set_attr "type" "arith_media")])
1080
1081 (define_peephole2
1082   [(set (match_operand:SI 0 "arith_reg_dest" "")
1083         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1084                            [(match_operand:SI 1 "arith_reg_operand" "")
1085                             (const_int 0)])
1086          (match_operand:SI 2 "arith_reg_dest" "")
1087          (match_dup 0)))
1088    (set (match_dup 2) (match_dup 0))]
1089   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1090   [(set (match_dup 2)
1091         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1092   "
1093 {
1094   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1095                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1096 }")
1097
1098 (define_peephole2
1099   [(set (match_operand:SI 0 "general_movdst_operand" "")
1100         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1101    (set (match_operand:SI 2 "arith_reg_dest" "")
1102         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1103                            [(match_operand:SI 3 "arith_reg_operand" "")
1104                             (const_int 0)])
1105          (match_dup 0)
1106          (match_dup 2)))]
1107   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1108    && (GET_CODE (operands[1]) != REG || GENERAL_REGISTER_P (REGNO (operands[1])))"
1109   [(set (match_dup 2)
1110         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1111   "
1112 {
1113   replace_rtx (operands[4], operands[0], operands[1]);
1114 }")
1115
1116 (define_peephole2
1117   [(set (match_operand 0 "any_register_operand" "")
1118         (match_operand 1 "any_register_operand" ""))
1119    (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1120    (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1121   "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1122     <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1123    && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1124    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1125    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1126    && ! reg_overlap_mentioned_p (operands[0], operands[3])
1127    && ! reg_overlap_mentioned_p (operands[2], operands[0])
1128    && ! reg_overlap_mentioned_p (operands[0], operands[1])
1129    && (REGNO_REG_CLASS (REGNO (operands[0]))
1130        == REGNO_REG_CLASS (REGNO (operands[2])))
1131    && (REGNO_REG_CLASS (REGNO (operands[1]))
1132        == REGNO_REG_CLASS (REGNO (operands[0])))"
1133   [(set (match_dup 0) (match_dup 3))
1134    (set (match_dup 4) (match_dup 5))]
1135   "
1136 {
1137   rtx set1, set2;
1138   rtx replacements[4];
1139
1140   /* We want to replace occurrences of operands[0] with operands[1] and
1141      operands[2] with operands[0] in operands[4]/operands[5].
1142      Doing just two replace_rtx calls naively would result in the second
1143      replacement undoing all that the first did if operands[1] and operands[2]
1144      are identical, so we must do this simultaneously.  */
1145   replacements[0] = operands[0];
1146   replacements[1] = operands[1];
1147   replacements[2] = operands[2];
1148   replacements[3] = operands[0];
1149   if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1150       || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1151       || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1152     FAIL;
1153
1154   operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1155   replace_n_hard_rtx (operands[4], replacements, 2, 1);
1156   operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1157   /* The operands array is aliased to recog_data.operand, which gets
1158      clobbered by extract_insn, so finish with it now.  */
1159   set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1160   set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1161   /* ??? The last insn might be a jump insn, but the generic peephole2 code
1162      always uses emit_insn.  */
1163   /* Check that we don't violate matching constraints or earlyclobbers.  */
1164   extract_insn (emit_insn (set1));
1165   if (! constrain_operands (1))
1166     goto failure;
1167   extract_insn (emit (set2));
1168   if (! constrain_operands (1))
1169     {
1170       rtx tmp;
1171     failure:
1172       tmp = replacements[0];
1173       replacements[0] = replacements[1];
1174       replacements[1] = tmp;
1175       tmp = replacements[2];
1176       replacements[2] = replacements[3];
1177       replacements[3] = tmp;
1178       replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1179       replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1180       replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1181       FAIL;
1182     }
1183   DONE;
1184 }")
1185
1186 ;; The register allocator is rather clumsy in handling multi-way conditional
1187 ;; moves, so allow the combiner to make them, and we split them up after
1188 ;; reload.  */
1189 (define_insn_and_split "*movsicc_umin"
1190   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1191         (umin:SI (if_then_else:SI
1192                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1193                        (const_int 0))
1194                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1195                    (match_operand:SI 3 "register_operand" "0"))
1196                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1197    (clobber (match_scratch:SI 5 "=&r"))]
1198   "TARGET_SHMEDIA && no_new_pseudos"
1199   "#"
1200   "TARGET_SHMEDIA && reload_completed"
1201   [(pc)]
1202   "
1203 {
1204   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1205                                 operands[3]));
1206   emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1207   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1208                                 operands[0]));
1209   DONE;
1210 }")
1211
1212 (define_insn "*movsicc_t_false"
1213   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1214         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1215                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1216                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1217   "TARGET_PRETEND_CMOVE
1218    && (arith_reg_operand (operands[1], SImode)
1219        || (immediate_operand (operands[1], SImode)
1220            && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
1221   "bt 0f\;mov %1,%0\\n0:"
1222   [(set_attr "type" "mt_group,arith") ;; poor approximation
1223    (set_attr "length" "4")])
1224
1225 (define_insn "*movsicc_t_true"
1226   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1227         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1228                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1229                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1230   "TARGET_PRETEND_CMOVE
1231    && (arith_reg_operand (operands[1], SImode)
1232        || (immediate_operand (operands[1], SImode)
1233            && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
1234   "bf 0f\;mov %1,%0\\n0:"
1235   [(set_attr "type" "mt_group,arith") ;; poor approximation
1236    (set_attr "length" "4")])
1237
1238 (define_expand "movsicc"
1239   [(set (match_operand:SI 0 "arith_reg_dest" "")
1240         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1241                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1242                          (match_operand:SI 3 "arith_reg_operand" "")))]
1243   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1244   "
1245 {
1246   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1247       && GET_MODE (sh_compare_op0) == SImode
1248       && (TARGET_SHMEDIA
1249           || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG))
1250       && sh_compare_op1 == const0_rtx)
1251     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
1252                                   sh_compare_op0, sh_compare_op1);
1253   else if (TARGET_PRETEND_CMOVE)
1254     {
1255       enum rtx_code code = GET_CODE (operands[1]);
1256       enum rtx_code new_code = code;
1257       rtx tmp;
1258
1259       if (! currently_expanding_to_rtl)
1260         FAIL;
1261       switch (code)
1262         {
1263         case LT: case LE: case LEU: case LTU:
1264           if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT)
1265             break;
1266         case NE:
1267           new_code = reverse_condition (code);
1268           break;
1269         case EQ: case GT: case GE: case GEU: case GTU:
1270           break;
1271         default:
1272           FAIL;
1273         }
1274       tmp = prepare_scc_operands (new_code);
1275       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1276                                     tmp, const0_rtx);
1277     }
1278   else
1279     {
1280       rtx tmp;
1281
1282       if (no_new_pseudos)
1283         FAIL;
1284
1285       tmp = gen_reg_rtx (SImode);
1286
1287       switch (GET_CODE (operands[1]))
1288         {
1289         case EQ:
1290           emit_insn (gen_seq (tmp));
1291           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1292           break;
1293
1294         case NE:
1295           emit_insn (gen_seq (tmp));
1296           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1297           break;
1298
1299         case GT:
1300           emit_insn (gen_sgt (tmp));
1301           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1302           break;
1303
1304         case LT:
1305           emit_insn (gen_slt (tmp));
1306           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1307           break;
1308
1309         case GE:
1310           emit_insn (gen_slt (tmp));
1311           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1312           break;
1313
1314         case LE:
1315           emit_insn (gen_sgt (tmp));
1316           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1317           break;
1318
1319         case GTU:
1320           emit_insn (gen_sgtu (tmp));
1321           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1322           break;
1323
1324         case LTU:
1325           emit_insn (gen_sltu (tmp));
1326           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1327           break;
1328
1329         case GEU:
1330           emit_insn (gen_sltu (tmp));
1331           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1332           break;
1333
1334         case LEU:
1335           emit_insn (gen_sgtu (tmp));
1336           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1337           break;
1338
1339         case UNORDERED:
1340           emit_insn (gen_sunordered (tmp));
1341           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1342           break;
1343
1344         case ORDERED:
1345           emit_insn (gen_sunordered (tmp));
1346           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1347           break;
1348
1349         case UNEQ:
1350         case UNGE:
1351         case UNGT:
1352         case UNLE:
1353         case UNLT:
1354         case LTGT:
1355           FAIL;
1356
1357         default:
1358           abort ();
1359         }
1360     }
1361 }")
1362
1363 (define_expand "movqicc"
1364   [(set (match_operand:QI 0 "register_operand" "")
1365         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1366                          (match_operand:QI 2 "register_operand" "")
1367                          (match_operand:QI 3 "register_operand" "")))]
1368   "TARGET_SHMEDIA"
1369   "
1370 {
1371   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1372   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1373   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1374   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1375   DONE;
1376 }")
1377 \f
1378 ;; -------------------------------------------------------------------------
1379 ;; Addition instructions
1380 ;; -------------------------------------------------------------------------
1381
1382 (define_expand "adddi3"
1383   [(set (match_operand:DI 0 "arith_reg_operand" "")
1384         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1385                  (match_operand:DI 2 "arith_operand" "")))]
1386   ""
1387   "
1388 {
1389   if (TARGET_SH1)
1390     {
1391       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
1392         FAIL;
1393       operands[2] = force_reg (DImode, operands[2]);
1394       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1395       DONE;
1396     }
1397 }")
1398
1399 (define_insn "*adddi3_media"
1400   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1401         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1402                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1403   "TARGET_SHMEDIA"
1404   "@
1405         add     %1, %2, %0
1406         addi    %1, %2, %0"
1407   [(set_attr "type" "arith_media")])
1408
1409 (define_insn "*adddisi3_media"
1410   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1411         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1412                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1413   "TARGET_SHMEDIA"
1414   "@
1415         add.l   %1, %2, %0
1416         addi.l  %1, %2, %0"
1417   [(set_attr "type" "arith_media")
1418    (set_attr "highpart" "ignore")])
1419
1420 (define_insn "adddi3z_media"
1421   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1422         (zero_extend:DI
1423          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1424                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1425   "TARGET_SHMEDIA"
1426   "addz.l       %1, %N2, %0"
1427   [(set_attr "type" "arith_media")
1428    (set_attr "highpart" "ignore")])
1429
1430 (define_insn "adddi3_compact"
1431   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1432         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1433                  (match_operand:DI 2 "arith_reg_operand" "r")))
1434    (clobber (reg:SI T_REG))]
1435   "TARGET_SH1"
1436   "#"
1437   [(set_attr "length" "6")])
1438
1439 (define_split
1440   [(set (match_operand:DI 0 "arith_reg_dest" "")
1441         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1442                  (match_operand:DI 2 "arith_reg_operand" "")))
1443    (clobber (reg:SI T_REG))]
1444   "TARGET_SH1 && reload_completed"
1445   [(const_int 0)]
1446   "
1447 {
1448   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1449   high0 = gen_rtx_REG (SImode,
1450                        true_regnum (operands[0])
1451                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1452   high2 = gen_rtx_REG (SImode,
1453                        true_regnum (operands[2])
1454                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1455   emit_insn (gen_clrt ());
1456   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1457   emit_insn (gen_addc1 (high0, high0, high2));
1458   DONE;
1459 }")
1460
1461 (define_insn "addc"
1462   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1463         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1464                           (match_operand:SI 2 "arith_reg_operand" "r"))
1465                  (reg:SI T_REG)))
1466    (set (reg:SI T_REG)
1467         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1468   "TARGET_SH1"
1469   "addc %2,%0"
1470   [(set_attr "type" "arith")])
1471
1472 (define_insn "addc1"
1473   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1474         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1475                           (match_operand:SI 2 "arith_reg_operand" "r"))
1476                  (reg:SI T_REG)))
1477    (clobber (reg:SI T_REG))]
1478   "TARGET_SH1"
1479   "addc %2,%0"
1480   [(set_attr "type" "arith")])
1481
1482 (define_expand "addsi3"
1483   [(set (match_operand:SI 0 "arith_reg_operand" "")
1484         (plus:SI (match_operand:SI 1 "arith_operand" "")
1485                  (match_operand:SI 2 "arith_operand" "")))]
1486   ""
1487   "
1488 {
1489   if (TARGET_SHMEDIA)
1490     operands[1] = force_reg (SImode, operands[1]);
1491 }")
1492
1493 (define_insn "addsi3_media"
1494   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1495         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1496                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1497   "TARGET_SHMEDIA"
1498   "@
1499         add.l   %1, %2, %0
1500         addi.l  %1, %2, %0"
1501   [(set_attr "type" "arith_media")
1502    (set_attr "highpart" "ignore")])
1503
1504 (define_insn "addsidi3_media"
1505   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1506         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1507                                   "%r,r")
1508                                  (match_operand:SI 2 "arith_operand"
1509                                   "r,I10"))))]
1510   "TARGET_SHMEDIA"
1511   "@
1512         add.l   %1, %2, %0
1513         addi.l  %1, %2, %0"
1514   [(set_attr "type" "arith_media")
1515    (set_attr "highpart" "ignore")])
1516
1517 (define_insn "*addsi3_compact"
1518   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1519         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1520                  (match_operand:SI 2 "arith_operand" "rI08")))]
1521   "TARGET_SH1"
1522   "add  %2,%0"
1523   [(set_attr "type" "arith")])
1524
1525 ;; -------------------------------------------------------------------------
1526 ;; Subtraction instructions
1527 ;; -------------------------------------------------------------------------
1528
1529 (define_expand "subdi3"
1530   [(set (match_operand:DI 0 "arith_reg_operand" "")
1531         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1532                   (match_operand:DI 2 "arith_reg_operand" "")))]
1533   ""
1534   "
1535 {
1536   if (TARGET_SH1)
1537     {
1538       operands[1] = force_reg (DImode, operands[1]);
1539       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1540       DONE;
1541     }
1542 }")
1543
1544 (define_insn "*subdi3_media"
1545   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1546         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1547                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1548   "TARGET_SHMEDIA"
1549   "sub  %N1, %2, %0"
1550   [(set_attr "type" "arith_media")])
1551   
1552 (define_insn "subdisi3_media"
1553   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1554         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1555                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1556   "TARGET_SHMEDIA"
1557   "sub.l        %N1, %2, %0"
1558   [(set_attr "type" "arith_media")
1559    (set_attr "highpart" "ignore")])
1560
1561 (define_insn "subdi3_compact"
1562   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1563         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1564                  (match_operand:DI 2 "arith_reg_operand" "r")))
1565    (clobber (reg:SI T_REG))]
1566   "TARGET_SH1"
1567   "#"
1568   [(set_attr "length" "6")])
1569
1570 (define_split
1571   [(set (match_operand:DI 0 "arith_reg_dest" "")
1572         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1573                   (match_operand:DI 2 "arith_reg_operand" "")))
1574    (clobber (reg:SI T_REG))]
1575   "TARGET_SH1 && reload_completed"
1576   [(const_int 0)]
1577   "
1578 {
1579   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1580   high0 = gen_rtx_REG (SImode,
1581                        true_regnum (operands[0])
1582                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1583   high2 = gen_rtx_REG (SImode,
1584                        true_regnum (operands[2])
1585                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1586   emit_insn (gen_clrt ());
1587   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1588   emit_insn (gen_subc1 (high0, high0, high2));
1589   DONE;
1590 }")
1591
1592 (define_insn "subc"
1593   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1594         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1595                             (match_operand:SI 2 "arith_reg_operand" "r"))
1596                   (reg:SI T_REG)))
1597    (set (reg:SI T_REG)
1598         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1599                           (reg:SI T_REG))
1600                 (match_dup 1)))]
1601   "TARGET_SH1"
1602   "subc %2,%0"
1603   [(set_attr "type" "arith")])
1604
1605 (define_insn "subc1"
1606   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1607         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1608                             (match_operand:SI 2 "arith_reg_operand" "r"))
1609                   (reg:SI T_REG)))
1610    (clobber (reg:SI T_REG))]
1611   "TARGET_SH1"
1612   "subc %2,%0"
1613   [(set_attr "type" "arith")])
1614
1615 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1616 ;; pattern for this case.  This helps multimedia applications that compute
1617 ;; the sum of absolute differences.
1618 (define_insn "mov_neg_si_t"
1619   [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1620   "TARGET_SH1"
1621   "subc %0,%0"
1622   [(set_attr "type" "arith")])
1623
1624 (define_insn "*subsi3_internal"
1625   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1626         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1627                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1628   "TARGET_SH1"
1629   "sub  %2,%0"
1630   [(set_attr "type" "arith")])
1631
1632 (define_insn_and_split "*subsi3_media"
1633   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1634         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1635                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1636   "TARGET_SHMEDIA
1637    && (operands[1] != constm1_rtx
1638        || (GET_CODE (operands[2]) != TRUNCATE
1639            && GET_CODE (operands[2]) != SUBREG))"
1640   "sub.l        %N1, %2, %0"
1641   "operands[1] == constm1_rtx"
1642   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1643   ""
1644   [(set_attr "type" "arith_media")
1645    (set_attr "highpart" "ignore")])
1646
1647 (define_split
1648   [(set (match_operand:SI 0 "arith_reg_dest" "")
1649         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1650                                                        "general_extend_operand"
1651                                                        "") 0)) 0)))]
1652   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1653   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1654    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1655   "")
1656
1657 (define_split
1658   [(set (match_operand:SI 0 "arith_reg_dest" "")
1659         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1660                                                        "general_extend_operand"
1661                                                        "") 0)) 3)))]
1662   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1663   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1664    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1665   "")
1666 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1667 ;; will sometimes save one instruction.  Otherwise we might get
1668 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1669 ;; are the same.
1670
1671 (define_expand "subsi3"
1672   [(set (match_operand:SI 0 "arith_reg_operand" "")
1673         (minus:SI (match_operand:SI 1 "arith_operand" "")
1674                   (match_operand:SI 2 "arith_reg_operand" "")))]
1675   ""
1676   "
1677 {
1678   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1679     {
1680       emit_insn (gen_negsi2 (operands[0], operands[2]));
1681       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1682       DONE;
1683     }
1684   if (TARGET_SHMEDIA)
1685     {
1686       if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1687         FAIL;
1688       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1689         operands[1] = force_reg (SImode, operands[1]);
1690     }
1691 }")
1692 \f
1693 ;; -------------------------------------------------------------------------
1694 ;; Division instructions
1695 ;; -------------------------------------------------------------------------
1696
1697 ;; We take advantage of the library routines which don't clobber as many
1698 ;; registers as a normal function call would.
1699
1700 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1701 ;; also has an effect on the register that holds the address of the sfunc.
1702 ;; To make this work, we have an extra dummy insn that shows the use
1703 ;; of this register for reorg.
1704
1705 (define_insn "use_sfunc_addr"
1706   [(set (reg:SI PR_REG)
1707         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1708   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1709   ""
1710   [(set_attr "length" "0")])
1711
1712 (define_insn "udivsi3_sh2a"
1713   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1714         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1715                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1716   "TARGET_SH2A"
1717   "divu %2,%1"
1718   [(set_attr "type" "arith")
1719    (set_attr "in_delay_slot" "no")])
1720
1721 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1722 ;; hard register 0.  If we used hard register 0, then the next instruction
1723 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1724 ;; gets allocated to a stack slot that needs its address reloaded, then
1725 ;; there is nothing to prevent reload from using r0 to reload the address.
1726 ;; This reload would clobber the value in r0 we are trying to store.
1727 ;; If we let reload allocate r0, then this problem can never happen.
1728
1729 (define_insn "udivsi3_i1"
1730   [(set (match_operand:SI 0 "register_operand" "=z")
1731         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1732    (clobber (reg:SI T_REG))
1733    (clobber (reg:SI PR_REG))
1734    (clobber (reg:SI R4_REG))
1735    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1736   "TARGET_SH1 && ! TARGET_SH4"
1737   "jsr  @%1%#"
1738   [(set_attr "type" "sfunc")
1739    (set_attr "needs_delay_slot" "yes")])
1740
1741 ; Since shmedia-nofpu code could be linked against shcompact code, and
1742 ; the udivsi3 libcall has the same name, we must consider all registers
1743 ; clobbered that are in the union of the registers clobbered by the
1744 ; shmedia and the shcompact implementation.  Note, if the shcompact
1745 ; implementation actually used shcompact code, we'd need to clobber
1746 ; also r23 and fr23.
1747 (define_insn "udivsi3_i1_media"
1748   [(set (match_operand:SI 0 "register_operand" "=z")
1749         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1750    (clobber (reg:SI T_MEDIA_REG))
1751    (clobber (reg:SI PR_MEDIA_REG))
1752    (clobber (reg:SI R20_REG))
1753    (clobber (reg:SI R21_REG))
1754    (clobber (reg:SI R22_REG))
1755    (clobber (reg:DI TR0_REG))
1756    (clobber (reg:DI TR1_REG))
1757    (clobber (reg:DI TR2_REG))
1758    (use (match_operand 1 "target_operand" "b"))]
1759   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1760   "blink        %1, r18"
1761   [(set_attr "type" "sfunc")
1762    (set_attr "needs_delay_slot" "yes")])
1763
1764 (define_expand "udivsi3_i4_media"
1765   [(set (match_dup 3)
1766         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1767    (set (match_dup 4)
1768         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1769    (set (match_dup 5) (float:DF (match_dup 3)))
1770    (set (match_dup 6) (float:DF (match_dup 4)))
1771    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1772    (set (match_dup 8) (fix:DI (match_dup 7)))
1773    (set (match_operand:SI 0 "register_operand" "")
1774         (truncate:SI (match_dup 8)))]
1775   "TARGET_SHMEDIA_FPU"
1776   "
1777 {
1778   operands[3] = gen_reg_rtx (DImode);
1779   operands[4] = gen_reg_rtx (DImode);
1780   operands[5] = gen_reg_rtx (DFmode);
1781   operands[6] = gen_reg_rtx (DFmode);
1782   operands[7] = gen_reg_rtx (DFmode);
1783   operands[8] = gen_reg_rtx (DImode);
1784 }")
1785
1786 (define_insn "udivsi3_i4"
1787   [(set (match_operand:SI 0 "register_operand" "=y")
1788         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1789    (clobber (reg:SI T_REG))
1790    (clobber (reg:SI PR_REG))
1791    (clobber (reg:DF DR0_REG))
1792    (clobber (reg:DF DR2_REG))
1793    (clobber (reg:DF DR4_REG))
1794    (clobber (reg:SI R0_REG))
1795    (clobber (reg:SI R1_REG))
1796    (clobber (reg:SI R4_REG))
1797    (clobber (reg:SI R5_REG))
1798    (use (reg:PSI FPSCR_REG))
1799    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1800   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1801   "jsr  @%1%#"
1802   [(set_attr "type" "sfunc")
1803    (set_attr "fp_mode" "double")
1804    (set_attr "needs_delay_slot" "yes")])
1805
1806 (define_insn "udivsi3_i4_single"
1807   [(set (match_operand:SI 0 "register_operand" "=y")
1808         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1809    (clobber (reg:SI T_REG))
1810    (clobber (reg:SI PR_REG))
1811    (clobber (reg:DF DR0_REG))
1812    (clobber (reg:DF DR2_REG))
1813    (clobber (reg:DF DR4_REG))
1814    (clobber (reg:SI R0_REG))
1815    (clobber (reg:SI R1_REG))
1816    (clobber (reg:SI R4_REG))
1817    (clobber (reg:SI R5_REG))
1818    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1819   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1820   "jsr  @%1%#"
1821   [(set_attr "type" "sfunc")
1822    (set_attr "needs_delay_slot" "yes")])
1823
1824 (define_insn "udivsi3_i4_int"
1825   [(set (match_operand:SI 0 "register_operand" "=z")
1826         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1827    (clobber (reg:SI T_REG))
1828    (clobber (reg:SI R1_REG))
1829    (clobber (reg:SI PR_REG))
1830    (clobber (reg:SI MACH_REG))
1831    (clobber (reg:SI MACL_REG))
1832    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1833   "TARGET_SH1"
1834   "jsr  @%1%#"
1835   [(set_attr "type" "sfunc")
1836    (set_attr "needs_delay_slot" "yes")])
1837
1838
1839 (define_expand "udivsi3"
1840   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1841    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1842    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1843    (parallel [(set (match_operand:SI 0 "register_operand" "")
1844                    (udiv:SI (reg:SI R4_REG)
1845                             (reg:SI R5_REG)))
1846               (clobber (reg:SI T_REG))
1847               (clobber (reg:SI PR_REG))
1848               (clobber (reg:SI R4_REG))
1849               (use (match_dup 3))])]
1850   ""
1851   "
1852 {
1853   rtx first, last;
1854
1855   operands[3] = gen_reg_rtx (Pmode);
1856   /* Emit the move of the address to a pseudo outside of the libcall.  */
1857   if (TARGET_DIVIDE_CALL_TABLE)
1858     {
1859       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1860          that causes problems when the divide code is supposed to come from a
1861          separate library.  Division by zero is undefined, so dividing 1 can be
1862          implemented by comparing with the divisor.  */
1863       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1864         {
1865           emit_insn (gen_cmpsi (operands[1], operands[2]));
1866           emit_insn (gen_sgeu (operands[0]));
1867           DONE;
1868         }
1869       else if (operands[2] == const0_rtx)
1870         {
1871           emit_move_insn (operands[0], operands[2]);
1872           DONE;
1873         }
1874       function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1875       last = gen_udivsi3_i4_int (operands[0], operands[3]);
1876     }
1877   else if (TARGET_DIVIDE_CALL_FP)
1878     {
1879       function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1880       if (TARGET_FPU_SINGLE)
1881         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1882       else
1883         last = gen_udivsi3_i4 (operands[0], operands[3]);
1884     }
1885   else if (TARGET_SHMEDIA_FPU)
1886     {
1887       operands[1] = force_reg (SImode, operands[1]);
1888       operands[2] = force_reg (SImode, operands[2]);
1889       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1890       DONE;
1891     }
1892   else if (TARGET_SH2A)
1893     {
1894       operands[1] = force_reg (SImode, operands[1]);
1895       operands[2] = force_reg (SImode, operands[2]);
1896       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1897       DONE;
1898     }
1899   else if (TARGET_SH5)
1900     {
1901       function_symbol (operands[3],
1902                        TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1903                        SFUNC_STATIC);
1904
1905       if (TARGET_SHMEDIA)
1906         last = gen_udivsi3_i1_media (operands[0], operands[3]);
1907       else if (TARGET_FPU_ANY)
1908         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1909       else
1910         last = gen_udivsi3_i1 (operands[0], operands[3]);
1911     }
1912   else
1913     {
1914       function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1915       last = gen_udivsi3_i1 (operands[0], operands[3]);
1916     }
1917   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1918   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1919   last = emit_insn (last);
1920   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1921      invariant code motion can move it.  */
1922   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1923   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1924   DONE;
1925 }")
1926
1927 (define_insn "divsi3_sh2a"
1928   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1929         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1930                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1931   "TARGET_SH2A"
1932   "divs %2,%1"
1933   [(set_attr "type" "arith")
1934    (set_attr "in_delay_slot" "no")])
1935
1936 (define_insn "divsi3_i1"
1937   [(set (match_operand:SI 0 "register_operand" "=z")
1938         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1939    (clobber (reg:SI T_REG))
1940    (clobber (reg:SI PR_REG))
1941    (clobber (reg:SI R1_REG))
1942    (clobber (reg:SI R2_REG))
1943    (clobber (reg:SI R3_REG))
1944    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1945   "TARGET_SH1 && ! TARGET_SH4"
1946   "jsr  @%1%#"
1947   [(set_attr "type" "sfunc")
1948    (set_attr "needs_delay_slot" "yes")])
1949
1950 (define_insn "divsi3_i1_media"
1951   [(set (match_operand:SI 0 "register_operand" "=z")
1952         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1953    (clobber (reg:SI T_MEDIA_REG))
1954    (clobber (reg:SI PR_MEDIA_REG))
1955    (clobber (reg:SI R1_REG))
1956    (clobber (reg:SI R20_REG))
1957    (clobber (reg:SI R21_REG))
1958    (clobber (reg:SI TR0_REG))
1959    (use (match_operand 1 "target_operand" "b"))]
1960   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1961   "blink        %1, r18"
1962   [(set_attr "type" "sfunc")])
1963
1964 (define_insn "divsi3_media_2"
1965   [(set (match_operand:SI 0 "register_operand" "=z")
1966         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1967    (clobber (reg:SI T_MEDIA_REG))
1968    (clobber (reg:SI PR_MEDIA_REG))
1969    (clobber (reg:SI R1_REG))
1970    (clobber (reg:SI R21_REG))
1971    (clobber (reg:SI TR0_REG))
1972    (use (reg:SI R20_REG))
1973    (use (match_operand 1 "target_operand" "b"))]
1974   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1975   "blink        %1, r18"
1976   [(set_attr "type" "sfunc")])
1977
1978 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1979 ;; hard reg clobbers and data dependencies that we need when we want
1980 ;; to rematerialize the division into a call.
1981 (define_insn_and_split "divsi_inv_call"
1982   [(set (match_operand:SI 0 "register_operand" "=r")
1983         (div:SI (match_operand:SI 1 "register_operand" "r")
1984                 (match_operand:SI 2 "register_operand" "r")))
1985    (clobber (reg:SI R4_REG))
1986    (clobber (reg:SI R5_REG))
1987    (clobber (reg:SI T_MEDIA_REG))
1988    (clobber (reg:SI PR_MEDIA_REG))
1989    (clobber (reg:SI R1_REG))
1990    (clobber (reg:SI R21_REG))
1991    (clobber (reg:SI TR0_REG))
1992    (clobber (reg:SI R20_REG))
1993    (use (match_operand:SI 3 "register_operand" "r"))]
1994   "TARGET_SHMEDIA"
1995   "#"
1996   "&& (high_life_started || reload_completed)"
1997   [(set (match_dup 0) (match_dup 3))]
1998   ""
1999   [(set_attr "highpart" "must_split")])
2000
2001 ;; This is the combiner pattern for -mdiv=inv:call .
2002 (define_insn_and_split "*divsi_inv_call_combine"
2003   [(set (match_operand:SI 0 "register_operand" "=z")
2004         (div:SI (match_operand:SI 1 "register_operand" "r")
2005                 (match_operand:SI 2 "register_operand" "r")))
2006    (clobber (reg:SI R4_REG))
2007    (clobber (reg:SI R5_REG))
2008    (clobber (reg:SI T_MEDIA_REG))
2009    (clobber (reg:SI PR_MEDIA_REG))
2010    (clobber (reg:SI R1_REG))
2011    (clobber (reg:SI R21_REG))
2012    (clobber (reg:SI TR0_REG))
2013    (clobber (reg:SI R20_REG))
2014    (use (unspec:SI [(match_dup 1)
2015                     (match_operand:SI 3 "" "")
2016                     (unspec:SI [(match_operand:SI 4 "" "")
2017                                 (match_dup 3)
2018                                 (match_operand:DI 5 "" "")]
2019                      UNSPEC_DIV_INV_M2)
2020                     (match_operand:DI 6 "" "")
2021                     (const_int 0)
2022                     (const_int 0)]
2023          UNSPEC_DIV_INV_M3))]
2024   "TARGET_SHMEDIA"
2025   "#"
2026   "&& (high_life_started || reload_completed)"
2027   [(pc)]
2028   "
2029 {
2030   const char *name = sh_divsi3_libfunc;
2031   enum sh_function_kind kind = SFUNC_GOT;
2032   rtx sym;
2033
2034   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2035   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2036   while (TARGET_DIVIDE_INV_CALL2)
2037     {
2038       rtx x = operands[3];
2039
2040       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2041         break;
2042       x = XVECEXP (x, 0, 0);
2043       name = \"__sdivsi3_2\";
2044       kind = SFUNC_STATIC;
2045       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2046       break;
2047     }
2048   sym = function_symbol (NULL, name, kind);
2049   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2050   DONE;
2051 }"
2052   [(set_attr "highpart" "must_split")])
2053
2054 (define_expand "divsi3_i4_media"
2055   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2056    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2057    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2058    (set (match_operand:SI 0 "register_operand" "=r")
2059         (fix:SI (match_dup 5)))]
2060   "TARGET_SHMEDIA_FPU"
2061   "
2062 {
2063   operands[3] = gen_reg_rtx (DFmode);
2064   operands[4] = gen_reg_rtx (DFmode);
2065   operands[5] = gen_reg_rtx (DFmode);
2066 }")
2067
2068 (define_insn "divsi3_i4"
2069   [(set (match_operand:SI 0 "register_operand" "=y")
2070         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2071    (clobber (reg:SI PR_REG))
2072    (clobber (reg:DF DR0_REG))
2073    (clobber (reg:DF DR2_REG))
2074    (use (reg:PSI FPSCR_REG))
2075    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2076   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2077   "jsr  @%1%#"
2078   [(set_attr "type" "sfunc")
2079    (set_attr "fp_mode" "double")
2080    (set_attr "needs_delay_slot" "yes")])
2081
2082 (define_insn "divsi3_i4_single"
2083   [(set (match_operand:SI 0 "register_operand" "=y")
2084         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2085    (clobber (reg:SI PR_REG))
2086    (clobber (reg:DF DR0_REG))
2087    (clobber (reg:DF DR2_REG))
2088    (clobber (reg:SI R2_REG))
2089    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2090   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2091   "jsr  @%1%#"
2092   [(set_attr "type" "sfunc")
2093    (set_attr "needs_delay_slot" "yes")])
2094
2095 (define_insn "divsi3_i4_int"
2096   [(set (match_operand:SI 0 "register_operand" "=z")
2097         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2098    (clobber (reg:SI T_REG))
2099    (clobber (reg:SI PR_REG))
2100    (clobber (reg:SI R1_REG))
2101    (clobber (reg:SI MACH_REG))
2102    (clobber (reg:SI MACL_REG))
2103    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2104   "TARGET_SH1"
2105   "jsr  @%1%#"
2106   [(set_attr "type" "sfunc")
2107    (set_attr "needs_delay_slot" "yes")])
2108
2109 (define_expand "divsi3"
2110   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2111    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2112    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2113    (parallel [(set (match_operand:SI 0 "register_operand" "")
2114                    (div:SI (reg:SI R4_REG)
2115                            (reg:SI R5_REG)))
2116               (clobber (reg:SI T_REG))
2117               (clobber (reg:SI PR_REG))
2118               (clobber (reg:SI R1_REG))
2119               (clobber (reg:SI R2_REG))
2120               (clobber (reg:SI R3_REG))
2121               (use (match_dup 3))])]
2122   ""
2123   "
2124 {
2125   rtx first, last;
2126
2127   operands[3] = gen_reg_rtx (Pmode);
2128   /* Emit the move of the address to a pseudo outside of the libcall.  */
2129   if (TARGET_DIVIDE_CALL_TABLE)
2130     {
2131       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2132       last = gen_divsi3_i4_int (operands[0], operands[3]);
2133     }
2134   else if (TARGET_DIVIDE_CALL_FP)
2135     {
2136       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2137       if (TARGET_FPU_SINGLE)
2138         last = gen_divsi3_i4_single (operands[0], operands[3]);
2139       else
2140         last = gen_divsi3_i4 (operands[0], operands[3]);
2141     }
2142   else if (TARGET_SH2A)
2143     {
2144       operands[1] = force_reg (SImode, operands[1]);
2145       operands[2] = force_reg (SImode, operands[2]);
2146       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2147       DONE;
2148     }
2149   else if (TARGET_DIVIDE_INV)
2150     {
2151       rtx dividend = operands[1];
2152       rtx divisor = operands[2];
2153       rtx tab_base;
2154       rtx nsb_res = gen_reg_rtx (DImode);
2155       rtx norm64 = gen_reg_rtx (DImode);
2156       rtx tab_ix = gen_reg_rtx (DImode);
2157       rtx norm32 = gen_reg_rtx (SImode);
2158       rtx i92 = force_reg (DImode, GEN_INT (92));
2159       rtx scratch0a = gen_reg_rtx (DImode);
2160       rtx scratch0b = gen_reg_rtx (DImode);
2161       rtx inv0 = gen_reg_rtx (SImode);
2162       rtx scratch1a = gen_reg_rtx (DImode);
2163       rtx scratch1b = gen_reg_rtx (DImode);
2164       rtx shift = gen_reg_rtx (DImode);
2165       rtx i2p27, i43;
2166       rtx inv1 = gen_reg_rtx (SImode);
2167       rtx scratch2a = gen_reg_rtx (DImode);
2168       rtx scratch2b = gen_reg_rtx (SImode);
2169       rtx inv2 = gen_reg_rtx (SImode);
2170       rtx scratch3a = gen_reg_rtx (DImode);
2171       rtx scratch3b = gen_reg_rtx (DImode);
2172       rtx scratch3c = gen_reg_rtx (DImode);
2173       rtx scratch3d = gen_reg_rtx (SImode);
2174       rtx scratch3e = gen_reg_rtx (DImode);
2175       rtx result = gen_reg_rtx (SImode);
2176
2177       if (! arith_reg_or_0_operand (dividend, SImode))
2178         dividend = force_reg (SImode, dividend);
2179       if (! arith_reg_operand (divisor, SImode))
2180         divisor = force_reg (SImode, divisor);
2181       if (flag_pic && Pmode != DImode)
2182         {
2183           tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2184           tab_base = gen_datalabel_ref (tab_base);
2185           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2186         }
2187       else
2188         {
2189           tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2190           tab_base = gen_datalabel_ref (tab_base);
2191           tab_base = force_reg (DImode, tab_base);
2192         }
2193       if (TARGET_DIVIDE_INV20U)
2194         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2195       else
2196         i2p27 = GEN_INT (0);
2197       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2198         i43 = force_reg (DImode, GEN_INT (43));
2199       else
2200         i43 = GEN_INT (0);
2201       emit_insn (gen_nsbdi (nsb_res,
2202                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2203       emit_insn (gen_ashldi3_media (norm64,
2204                                     gen_rtx_SUBREG (DImode, divisor, 0),
2205                                     nsb_res));
2206       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2207       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2208       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2209                                    inv0, scratch0a, scratch0b,
2210                                    scratch1a, scratch1b));
2211       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2212       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2213                                    scratch2a));
2214       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2215                                    i2p27, i43,
2216                                    scratch3a, scratch3b, scratch3c,
2217                                    scratch2a, scratch2b, scratch3d, scratch3e));
2218       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2219         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2220       else if (TARGET_DIVIDE_INV_FP)
2221         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2222                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2223                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2224                                      gen_reg_rtx (DFmode)));
2225       else
2226         emit_move_insn (operands[0], result);
2227       DONE;
2228     }
2229   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2230     {
2231       operands[1] = force_reg (SImode, operands[1]);
2232       operands[2] = force_reg (SImode, operands[2]);
2233       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2234       DONE;
2235     }
2236   else if (TARGET_SH5)
2237     {
2238       if (TARGET_DIVIDE_CALL2)
2239         {
2240           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2241           tab_base = gen_datalabel_ref (tab_base);
2242           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2243         }
2244       if (TARGET_FPU_ANY && TARGET_SH1)
2245         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2246       else if (TARGET_DIVIDE_CALL2)
2247         function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2248       else
2249         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2250
2251       if (TARGET_SHMEDIA)
2252         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2253                 (operands[0], operands[3]));
2254       else if (TARGET_FPU_ANY)
2255         last = gen_divsi3_i4_single (operands[0], operands[3]);
2256       else
2257         last = gen_divsi3_i1 (operands[0], operands[3]);
2258     }
2259   else
2260     {
2261       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2262       last = gen_divsi3_i1 (operands[0], operands[3]);
2263     }
2264   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2265   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2266   last = emit_insn (last);
2267   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2268      invariant code motion can move it.  */
2269   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2270   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2271   DONE;
2272 }")
2273
2274 ;; operands: scratch, tab_base, tab_ix
2275 ;; These are unspecs because we could generate an indexed addressing mode
2276 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2277 ;; confuse reload.  See PR27117.
2278
2279 (define_insn "divsi_inv_qitable"
2280   [(set (match_operand:DI 0 "register_operand" "=r")
2281         (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2282                                     (match_operand:DI 2 "register_operand" "r")]
2283                          UNSPEC_DIV_INV_TABLE)))]
2284   "TARGET_SHMEDIA"
2285   "@
2286         ldx.ub  %1, %2, %0"
2287   [(set_attr "type" "load_media")
2288    (set_attr "highpart" "user")])
2289
2290 ;; operands: scratch, tab_base, tab_ix
2291 (define_insn "divsi_inv_hitable"
2292   [(set (match_operand:DI 0 "register_operand" "=r")
2293         (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2294                                     (match_operand:DI 2 "register_operand" "r")]
2295                          UNSPEC_DIV_INV_TABLE)))]
2296   "TARGET_SHMEDIA"
2297   "@
2298         ldx.w   %1, %2, %0"
2299   [(set_attr "type" "load_media")
2300    (set_attr "highpart" "user")])
2301
2302 ;; operands: inv0, tab_base, tab_ix, norm32
2303 ;; scratch equiv in sdivsi3_2: r19, r21
2304 (define_expand "divsi_inv_m0"
2305   [(set (match_operand:SI 0 "register_operand" "=r")
2306         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2307                     (match_operand:DI 2 "register_operand" "r")
2308                     (match_operand:SI 3 "register_operand" "r")]
2309          UNSPEC_DIV_INV_M0))
2310    (clobber (match_operand:DI 4 "register_operand" "=r"))
2311    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2312   "TARGET_SHMEDIA"
2313   "
2314 {
2315 /*
2316 tab_base: r20
2317 tab_ix: r21
2318 norm32: r25
2319  ldx.ub r20, r21, r19 // u0.8
2320  shlli r21, 1, r21
2321  muls.l r25, r19, r19 // s2.38
2322  ldx.w r20, r21, r21  // s2.14
2323  shari r19, 24, r19   // truncate to s2.14
2324  sub r21, r19, r19    // some 11 bit inverse in s1.14
2325 */
2326
2327   rtx inv0 = operands[0];
2328   rtx tab_base = operands[1];
2329   rtx tab_ix = operands[2];
2330   rtx norm32 = operands[3];
2331   rtx scratch0 = operands[4];
2332   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2333   rtx scratch1 = operands[5];
2334
2335   emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2336   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2337   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2338   emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2339   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2340   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2341   DONE;
2342 }")
2343
2344 ;; operands: inv1, tab_base, tab_ix, norm32
2345 (define_insn_and_split "divsi_inv_m1"
2346   [(set (match_operand:SI 0 "register_operand" "=r")
2347         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2348                     (match_operand:DI 2 "register_operand" "r")
2349                     (match_operand:SI 3 "register_operand" "r")]
2350          UNSPEC_DIV_INV_M1))
2351    (clobber (match_operand:SI 4 "register_operand" "=r"))
2352    (clobber (match_operand:DI 5 "register_operand" "=r"))
2353    (clobber (match_operand:DI 6 "register_operand" "=r"))
2354    (clobber (match_operand:DI 7 "register_operand" "=r"))
2355    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2356   "TARGET_SHMEDIA"
2357   "#"
2358   "&& no_new_pseudos"
2359   [(pc)]
2360   "
2361 {
2362 /* inv0: r19
2363  muls.l r19, r19, r18 // u0.28
2364  muls.l r25, r18, r18 // s2.58
2365  shlli r19, 45, r0    // multiply by two and convert to s2.58
2366  sub r0, r18, r18
2367  shari r18, 28, r18   // some 18 bit inverse in s1.30
2368 */
2369
2370   rtx inv1 = operands[0];
2371   rtx tab_base = operands[1];
2372   rtx tab_ix = operands[2];
2373   rtx norm32 = operands[3];
2374   rtx inv0 = operands[4];
2375   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2376   rtx scratch0a = operands[5];
2377   rtx scratch0b = operands[6];
2378   rtx scratch0 = operands[7];
2379   rtx scratch1 = operands[8];
2380   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2381
2382   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2383                                scratch0a, scratch0b));
2384   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2385   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2386   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2387   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2388   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2389   DONE;
2390 }")
2391
2392 ;; operands: inv2, norm32, inv1, i92
2393 (define_insn_and_split "divsi_inv_m2"
2394   [(set (match_operand:SI 0 "register_operand" "=r")
2395         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2396                     (match_operand:SI 2 "register_operand" "r")
2397                     (match_operand:DI 3 "register_operand" "r")]
2398          UNSPEC_DIV_INV_M2))
2399    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2400   "TARGET_SHMEDIA"
2401   "#"
2402   "&& no_new_pseudos"
2403   [(pc)]
2404   "
2405 {
2406 /*
2407  muls.l r18, r25, r0  // s2.60
2408  shari r0, 16, r0     // s-16.44
2409   sub
2410  muls.l r0, r18, r19  // s-16.74
2411  shari r19, 30, r19   // s-16.44
2412 */
2413   rtx inv2 = operands[0];
2414   rtx norm32 = operands[1];
2415   rtx inv1 = operands[2];
2416   rtx i92 = operands[3];
2417   rtx scratch0 = operands[4];
2418   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2419
2420   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2421   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2422   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2423   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2424   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2425   DONE;
2426 }")
2427
2428 (define_insn_and_split "divsi_inv_m3"
2429   [(set (match_operand:SI 0 "register_operand" "=r")
2430         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2431                     (match_operand:SI 2 "register_operand" "r")
2432                     (match_operand:SI 3 "register_operand" "r")
2433                     (match_operand:DI 4 "register_operand" "r")
2434                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2435                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2436          UNSPEC_DIV_INV_M3))
2437    (clobber (match_operand:DI 7 "register_operand" "=r"))
2438    (clobber (match_operand:DI 8 "register_operand" "=r"))
2439    (clobber (match_operand:DI 9 "register_operand" "=r"))
2440    (clobber (match_operand:DI 10 "register_operand" "=r"))
2441    (clobber (match_operand:SI 11 "register_operand" "=r"))
2442    (clobber (match_operand:SI 12 "register_operand" "=r"))
2443    (clobber (match_operand:DI 13 "register_operand" "=r"))]
2444   "TARGET_SHMEDIA"
2445   "#"
2446   "&& no_new_pseudos"
2447   [(pc)]
2448   "
2449 {
2450 /*
2451   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2452   r0: scratch0  r19: scratch1 r21: scratch2
2453
2454   muls.l r18, r4, r25 // s32.30
2455  muls.l r19, r4, r19  // s15.30
2456  shari r25, 63, r21
2457   shari r19, 14, r19  // s18.-14
2458  sub r25, r19, r0
2459  shard r0, r1, r0
2460  sub r0, r21, r0
2461 */
2462
2463   rtx result = operands[0];
2464   rtx dividend = operands[1];
2465   rtx inv1 = operands[2];
2466   rtx inv2 = operands[3];
2467   rtx shift = operands[4];
2468   rtx scratch0 = operands[7];
2469   rtx scratch1 = operands[8];
2470   rtx scratch2 = operands[9];
2471
2472   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2473   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2474   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2475   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2476   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2477   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2478   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2479   DONE;
2480 }")
2481
2482 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2483 ;; inv1: tab_base, tab_ix, norm32
2484 ;; inv2: norm32, inv1, i92
2485 (define_insn_and_split "divsi_inv_m1_3"
2486   [(set (match_operand:SI 0 "register_operand" "=r")
2487         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2488                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2489                                 (match_operand:DI 3 "register_operand" "r")
2490                                 (match_operand:SI 4 "register_operand" "r")]
2491                      UNSPEC_DIV_INV_M1)
2492                     (unspec:SI [(match_dup 4)
2493                                 (unspec:SI [(match_dup 2)
2494                                             (match_dup 3)
2495                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
2496                                 (match_operand:SI 5 "" "")]
2497                      UNSPEC_DIV_INV_M2)
2498                     (match_operand:DI 6 "register_operand" "r")
2499                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2500                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2501          UNSPEC_DIV_INV_M3))
2502    (clobber (match_operand:DI 9 "register_operand" "=r"))
2503    (clobber (match_operand:DI 10 "register_operand" "=r"))
2504    (clobber (match_operand:DI 11 "register_operand" "=r"))
2505    (clobber (match_operand:DI 12 "register_operand" "=r"))
2506    (clobber (match_operand:SI 13 "register_operand" "=r"))
2507    (clobber (match_operand:SI 14 "register_operand" "=r"))
2508    (clobber (match_operand:DI 15 "register_operand" "=r"))]
2509   "TARGET_SHMEDIA
2510    && (TARGET_DIVIDE_INV_MINLAT
2511        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2512   "#"
2513   "&& no_new_pseudos"
2514   [(pc)]
2515   "
2516 {
2517   rtx result = operands[0];
2518   rtx dividend = operands[1];
2519   rtx tab_base = operands[2];
2520   rtx tab_ix = operands[3];
2521   rtx norm32 = operands[4];
2522   /* rtx i92 = operands[5]; */
2523   rtx shift = operands[6];
2524   rtx i2p27 = operands[7];
2525   rtx i43 = operands[8];
2526   rtx scratch0 = operands[9];
2527   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2528   rtx scratch1 = operands[10];
2529   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2530   rtx scratch2 = operands[11];
2531   rtx scratch3 = operands[12];
2532   rtx scratch4 = operands[13];
2533   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2534   rtx scratch5 = operands[14];
2535   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2536   rtx scratch6 = operands[15];
2537
2538   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2539                                scratch0, scratch1));
2540   /* inv0 == scratch4 */
2541   if (! TARGET_DIVIDE_INV20U)
2542     {
2543       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2544       i2p27 = scratch0;
2545       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2546     }
2547   else
2548     {
2549       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2550       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2551     }
2552   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2553   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2554   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2555   /* inv1 == scratch4 */
2556
2557   if (TARGET_DIVIDE_INV_MINLAT)
2558     {
2559       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2560       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2561       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2562       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2563       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2564       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2565       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2566       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2567       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2568       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2569       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2570     }
2571   else
2572     {
2573       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2574       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2575       emit_insn (gen_nsbdi (scratch6,
2576                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
2577       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2578       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2579       emit_insn (gen_divsi_inv20 (scratch2,
2580                                   norm32, scratch4, dividend,
2581                                   scratch6, scratch3, i43,
2582                                   /* scratch0 may be shared with i2p27.  */
2583                                   scratch0, scratch1, scratch5,
2584                                   label, label, i2p27));
2585     }
2586   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2587   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2588   DONE;
2589 }")
2590
2591 (define_insn "divsi_inv20"
2592   [(set (match_operand:DI 0 "register_operand" "=&r")
2593         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2594                     (match_operand:SI 2 "register_operand" "r")
2595                     (match_operand:SI 3 "register_operand" "r")
2596                     (match_operand:DI 4 "register_operand" "r")
2597                     (match_operand:DI 5 "register_operand" "r")
2598                     (match_operand:DI 6 "register_operand" "r")
2599                     (match_operand:DI 12 "register_operand" "r")
2600                     (match_operand 10 "target_operand" "b")
2601                     (match_operand 11 "immediate_operand" "i")]
2602          UNSPEC_DIV_INV20))
2603    (clobber (match_operand:DI 7 "register_operand" "=&r"))
2604    (clobber (match_operand:DI 8 "register_operand" "=&r"))
2605    (clobber (match_operand:SI 9 "register_operand" "=r"))]
2606   "TARGET_SHMEDIA
2607    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2608   "*
2609 {
2610 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2611              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2612              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2613              %10 label (tr), %11 label (imm)
2614
2615  muls.l inv1, norm32, scratch0  // s2.60
2616   muls.l inv1, dividend, result // s32.30
2617   xor i2p27, result_sign, round_scratch
2618  bge/u dividend_nsb, i43, tr.. (label)
2619  shari scratch0, 16, scratch0   // s-16.44
2620  muls.l sratch0_si, inv1, scratch0 // s-16.74
2621   sub result, round_scratch, result
2622   shari dividend, 14, scratch1   // s19.-14
2623  shari scratch0, 30, scratch0   // s-16.44
2624  muls.l scratch0, scratch1, round_scratch // s15.30
2625 label:
2626  sub result, round_scratch, result */
2627
2628   int likely = TARGET_DIVIDE_INV20L;
2629
2630   if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2631   output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2632   output_asm_insn (likely
2633                    ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2634                    : \"bge/u\t%4, %6, %10\", operands);
2635   output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2636   if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2637   output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2638   return (likely
2639           ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2640           : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2641 }")
2642
2643 (define_insn_and_split "divsi_inv_fp"
2644   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2645         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2646                 (match_operand:SI 2 "register_operand" "rf")))
2647    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2648    (clobber (match_operand:SI 4 "register_operand" "=r"))
2649    (clobber (match_operand:SI 5 "register_operand" "=r"))
2650    (clobber (match_operand:DF 6 "register_operand" "=r"))
2651    (clobber (match_operand:DF 7 "register_operand" "=r"))
2652    (clobber (match_operand:DF 8 "register_operand" "=r"))]
2653   "TARGET_SHMEDIA_FPU"
2654   "#"
2655   "&& (high_life_started || reload_completed)"
2656   [(set (match_dup 0) (match_dup 3))]
2657   ""
2658   [(set_attr "highpart" "must_split")])
2659
2660 ;; If a matching group of divide-by-inverse instructions is in the same
2661 ;; basic block after gcse & loop optimizations, we want to transform them
2662 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2663 (define_insn_and_split "*divsi_inv_fp_combine"
2664   [(set (match_operand:SI 0 "register_operand" "=f")
2665         (div:SI (match_operand:SI 1 "register_operand" "f")
2666                 (match_operand:SI 2 "register_operand" "f")))
2667    (use (unspec:SI [(match_dup 1)
2668                     (match_operand:SI 3 "" "")
2669                     (unspec:SI [(match_operand:SI 4 "" "")
2670                                 (match_dup 3)
2671                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2672                     (match_operand:DI 6 "" "")
2673                     (const_int 0)
2674                     (const_int 0)] UNSPEC_DIV_INV_M3))
2675    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2676    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2677    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2678    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2679    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2680   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos"
2681   "#"
2682   "&& 1"
2683   [(set (match_dup 9) (float:DF (match_dup 1)))
2684    (set (match_dup 10) (float:DF (match_dup 2)))
2685    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2686    (set (match_dup 8)
2687         (fix:SI (match_dup 11)))
2688    (set (match_dup 0) (match_dup 8))]
2689   "
2690 {
2691   if (! fp_arith_reg_operand (operands[1], SImode))
2692     {
2693       emit_move_insn (operands[7], operands[1]);
2694       operands[1] = operands[7];
2695     }
2696   if (! fp_arith_reg_operand (operands[2], SImode))
2697     {
2698       emit_move_insn (operands[8], operands[2]);
2699       operands[2] = operands[8];
2700     }
2701 }"
2702   [(set_attr "highpart" "must_split")])
2703 \f
2704 ;; -------------------------------------------------------------------------
2705 ;; Multiplication instructions
2706 ;; -------------------------------------------------------------------------
2707
2708 (define_insn "umulhisi3_i"
2709   [(set (reg:SI MACL_REG)
2710         (mult:SI (zero_extend:SI
2711                   (match_operand:HI 0 "arith_reg_operand" "r"))
2712                  (zero_extend:SI
2713                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2714   "TARGET_SH1"
2715   "mulu.w       %1,%0"
2716   [(set_attr "type" "smpy")])
2717
2718 (define_insn "mulhisi3_i"
2719   [(set (reg:SI MACL_REG)
2720         (mult:SI (sign_extend:SI
2721                   (match_operand:HI 0 "arith_reg_operand" "r"))
2722                  (sign_extend:SI
2723                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2724   "TARGET_SH1"
2725   "muls.w       %1,%0"
2726   [(set_attr "type" "smpy")])
2727
2728 (define_expand "mulhisi3"
2729   [(set (reg:SI MACL_REG)
2730         (mult:SI (sign_extend:SI
2731                   (match_operand:HI 1 "arith_reg_operand" ""))
2732                  (sign_extend:SI
2733                   (match_operand:HI 2 "arith_reg_operand" ""))))
2734    (set (match_operand:SI 0 "arith_reg_operand" "")
2735         (reg:SI MACL_REG))]
2736   "TARGET_SH1"
2737   "
2738 {
2739   rtx first, last;
2740
2741   first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2742   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
2743   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2744      invariant code motion can move it.  */
2745   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2746   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2747   /* expand_binop can't find a suitable code in umul_widen_optab to
2748      make a REG_EQUAL note from, so make one here.
2749      See also smulsi3_highpart.
2750      ??? Alternatively, we could put this at the calling site of expand_binop,
2751      i.e. expand_expr.  */
2752   REG_NOTES (last)
2753     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2754                          REG_NOTES (last));
2755   DONE;
2756 }")
2757
2758 (define_expand "umulhisi3"
2759   [(set (reg:SI MACL_REG)
2760         (mult:SI (zero_extend:SI
2761                   (match_operand:HI 1 "arith_reg_operand" ""))
2762                  (zero_extend:SI
2763                   (match_operand:HI 2 "arith_reg_operand" ""))))
2764    (set (match_operand:SI 0 "arith_reg_operand" "")
2765         (reg:SI MACL_REG))]
2766   "TARGET_SH1"
2767   "
2768 {
2769   rtx first, last;
2770
2771   first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2772   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
2773   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2774      invariant code motion can move it.  */
2775   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2776   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2777   /* expand_binop can't find a suitable code in umul_widen_optab to
2778      make a REG_EQUAL note from, so make one here.
2779      See also smulsi3_highpart.
2780      ??? Alternatively, we could put this at the calling site of expand_binop,
2781      i.e. expand_expr.  */
2782   REG_NOTES (last)
2783     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2784                          REG_NOTES (last));
2785   DONE;
2786 }")
2787
2788 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2789 ;; a call to a routine which clobbers known registers.
2790
2791 (define_insn ""
2792   [(set (match_operand:SI 1 "register_operand" "=z")
2793         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2794    (clobber (reg:SI MACL_REG))
2795    (clobber (reg:SI T_REG))
2796    (clobber (reg:SI PR_REG))
2797    (clobber (reg:SI R3_REG))
2798    (clobber (reg:SI R2_REG))
2799    (clobber (reg:SI R1_REG))
2800    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2801   "TARGET_SH1"
2802   "jsr  @%0%#"
2803   [(set_attr "type" "sfunc")
2804    (set_attr "needs_delay_slot" "yes")])
2805
2806 (define_expand "mulsi3_call"
2807   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2808    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2809    (parallel[(set (match_operand:SI 0 "register_operand" "")
2810                   (mult:SI (reg:SI R4_REG)
2811                            (reg:SI R5_REG)))
2812              (clobber (reg:SI MACL_REG))
2813              (clobber (reg:SI T_REG))
2814              (clobber (reg:SI PR_REG))
2815              (clobber (reg:SI R3_REG))
2816              (clobber (reg:SI R2_REG))
2817              (clobber (reg:SI R1_REG))
2818              (use (match_operand:SI 3 "register_operand" ""))])]
2819   "TARGET_SH1"
2820   "")
2821
2822 (define_insn "mul_r"
2823   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2824         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2825                  (match_operand:SI 2 "arith_reg_operand" "z")))]
2826   "TARGET_SH2A"
2827   "mulr %2,%0"
2828   [(set_attr "type" "dmpy")])
2829
2830 (define_insn "mul_l"
2831   [(set (reg:SI MACL_REG)
2832         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2833                  (match_operand:SI 1 "arith_reg_operand" "r")))]
2834   "TARGET_SH2"
2835   "mul.l        %1,%0"
2836   [(set_attr "type" "dmpy")])
2837
2838 (define_expand "mulsi3"
2839   [(set (reg:SI MACL_REG)
2840         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
2841                   (match_operand:SI 2 "arith_reg_operand" "")))
2842    (set (match_operand:SI 0 "arith_reg_operand" "")
2843         (reg:SI MACL_REG))]
2844   "TARGET_SH1"
2845   "
2846 {
2847   rtx first, last;
2848
2849   if (!TARGET_SH2)
2850     {
2851       /* The address must be set outside the libcall,
2852          since it goes into a pseudo.  */
2853       rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2854       rtx addr = force_reg (SImode, sym);
2855       rtx insns = gen_mulsi3_call (operands[0], operands[1],
2856                                    operands[2], addr);
2857       first = insns;
2858       last = emit_insn (insns);
2859     }
2860   else
2861     {
2862       rtx macl = gen_rtx_REG (SImode, MACL_REG);
2863
2864       first = emit_insn (gen_mul_l (operands[1], operands[2]));
2865       /* consec_sets_giv can only recognize the first insn that sets a
2866          giv as the giv insn.  So we must tag this also with a REG_EQUAL
2867          note.  */
2868       last = emit_insn (gen_movsi_i ((operands[0]), macl));
2869     }
2870   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2871      invariant code motion can move it.  */
2872   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2873   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2874   DONE;
2875 }")
2876
2877 (define_insn "mulsidi3_i"
2878   [(set (reg:SI MACH_REG)
2879         (truncate:SI
2880          (lshiftrt:DI
2881           (mult:DI
2882            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2883            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2884           (const_int 32))))
2885    (set (reg:SI MACL_REG)
2886         (mult:SI (match_dup 0)
2887                  (match_dup 1)))]
2888   "TARGET_SH2"
2889   "dmuls.l      %1,%0"
2890   [(set_attr "type" "dmpy")])
2891
2892 (define_expand "mulsidi3"
2893   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2894         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2895                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2896   "TARGET_SH2 || TARGET_SHMEDIA"
2897   "
2898 {
2899   if (TARGET_SH2)
2900     {
2901        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2902                                         operands[2]));
2903        DONE;
2904     }
2905 }")
2906
2907 (define_insn "mulsidi3_media"
2908   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2909         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2910                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2911   "TARGET_SHMEDIA"
2912   "muls.l       %1, %2, %0"
2913   [(set_attr "type" "dmpy_media")
2914    (set_attr "highpart" "ignore")])
2915
2916 (define_insn "mulsidi3_compact"
2917   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2918         (mult:DI
2919          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2920          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2921    (clobber (reg:SI MACH_REG))
2922    (clobber (reg:SI MACL_REG))]
2923   "TARGET_SH2"
2924   "#")
2925
2926 (define_split
2927   [(set (match_operand:DI 0 "arith_reg_dest" "")
2928         (mult:DI
2929          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2930          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2931    (clobber (reg:SI MACH_REG))
2932    (clobber (reg:SI MACL_REG))]
2933   "TARGET_SH2"
2934   [(const_int 0)]
2935   "
2936 {
2937   rtx low_dst = gen_lowpart (SImode, operands[0]);
2938   rtx high_dst = gen_highpart (SImode, operands[0]);
2939
2940   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2941
2942   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2943   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2944   /* We need something to tag the possible REG_EQUAL notes on to.  */
2945   emit_move_insn (operands[0], operands[0]);
2946   DONE;
2947 }")
2948
2949 (define_insn "umulsidi3_i"
2950   [(set (reg:SI MACH_REG)
2951         (truncate:SI
2952          (lshiftrt:DI
2953           (mult:DI
2954            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2955            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2956           (const_int 32))))
2957    (set (reg:SI MACL_REG)
2958         (mult:SI (match_dup 0)
2959                  (match_dup 1)))]
2960   "TARGET_SH2"
2961   "dmulu.l      %1,%0"
2962   [(set_attr "type" "dmpy")])
2963
2964 (define_expand "umulsidi3"
2965   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2966         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2967                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2968   "TARGET_SH2 || TARGET_SHMEDIA"
2969   "
2970 {
2971   if (TARGET_SH2)
2972     {
2973        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2974                                          operands[2]));
2975        DONE;
2976     }
2977 }")
2978
2979 (define_insn "umulsidi3_media"
2980   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2981         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2982                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2983   "TARGET_SHMEDIA"
2984   "mulu.l       %1, %2, %0"
2985   [(set_attr "type" "dmpy_media")
2986    (set_attr "highpart" "ignore")])
2987
2988 (define_insn "umulsidi3_compact"
2989   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2990         (mult:DI
2991          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2992          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2993    (clobber (reg:SI MACH_REG))
2994    (clobber (reg:SI MACL_REG))]
2995   "TARGET_SH2"
2996   "#")
2997
2998 (define_split
2999   [(set (match_operand:DI 0 "arith_reg_dest" "")
3000         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3001                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
3002    (clobber (reg:SI MACH_REG))
3003    (clobber (reg:SI MACL_REG))]
3004   "TARGET_SH2"
3005   [(const_int 0)]
3006   "
3007 {
3008   rtx low_dst = gen_lowpart (SImode, operands[0]);
3009   rtx high_dst = gen_highpart (SImode, operands[0]);
3010
3011   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3012
3013   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3014   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3015   /* We need something to tag the possible REG_EQUAL notes on to.  */
3016   emit_move_insn (operands[0], operands[0]);
3017   DONE;
3018 }")
3019
3020 (define_insn "smulsi3_highpart_i"
3021   [(set (reg:SI MACH_REG)
3022         (truncate:SI
3023          (lshiftrt:DI
3024           (mult:DI
3025            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3026            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3027           (const_int 32))))
3028    (clobber (reg:SI MACL_REG))]
3029   "TARGET_SH2"
3030   "dmuls.l      %1,%0"
3031   [(set_attr "type" "dmpy")])
3032
3033 (define_expand "smulsi3_highpart"
3034   [(parallel
3035     [(set (reg:SI MACH_REG)
3036           (truncate:SI
3037            (lshiftrt:DI
3038             (mult:DI
3039              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3040              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3041             (const_int 32))))
3042     (clobber (reg:SI MACL_REG))])
3043    (set (match_operand:SI 0 "arith_reg_operand" "")
3044         (reg:SI MACH_REG))]
3045   "TARGET_SH2"
3046   "
3047 {
3048   rtx first, last;
3049
3050   first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3051   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
3052   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
3053      invariant code motion can move it.  */
3054   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
3055   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
3056   /* expand_binop can't find a suitable code in mul_highpart_optab to
3057      make a REG_EQUAL note from, so make one here.
3058      See also {,u}mulhisi.
3059      ??? Alternatively, we could put this at the calling site of expand_binop,
3060      i.e. expand_mult_highpart.  */
3061   REG_NOTES (last)
3062     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
3063                          REG_NOTES (last));
3064   DONE;
3065 }")
3066
3067 (define_insn "umulsi3_highpart_i"
3068   [(set (reg:SI MACH_REG)
3069         (truncate:SI
3070          (lshiftrt:DI
3071           (mult:DI
3072            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3073            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3074           (const_int 32))))
3075    (clobber (reg:SI MACL_REG))]
3076   "TARGET_SH2"
3077   "dmulu.l      %1,%0"
3078   [(set_attr "type" "dmpy")])
3079
3080 (define_expand "umulsi3_highpart"
3081   [(parallel
3082     [(set (reg:SI MACH_REG)
3083           (truncate:SI
3084            (lshiftrt:DI
3085             (mult:DI
3086              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3087              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3088             (const_int 32))))
3089     (clobber (reg:SI MACL_REG))])
3090    (set (match_operand:SI 0 "arith_reg_operand" "")
3091         (reg:SI MACH_REG))]
3092   "TARGET_SH2"
3093   "
3094 {
3095   rtx first, last;
3096
3097   first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3098   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
3099   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
3100      invariant code motion can move it.  */
3101   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
3102   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
3103   DONE;
3104 }")
3105
3106 (define_insn_and_split "muldi3"
3107   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3108         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3109                  (match_operand:DI 2 "arith_reg_operand" "r")))
3110    (clobber (match_scratch:DI 3 "=&r"))
3111    (clobber (match_scratch:DI 4 "=r"))]
3112   "TARGET_SHMEDIA"
3113   "#"
3114   "reload_completed"
3115   [(const_int 0)]
3116   "
3117 {
3118   rtx op3_v2si, op2_v2si;
3119
3120   op3_v2si = operands[3];
3121   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3122     {
3123       op3_v2si = XEXP (op3_v2si, 0);
3124       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3125     }
3126   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3127   op2_v2si = operands[2];
3128   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3129     {
3130       op2_v2si = XEXP (op2_v2si, 0);
3131       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3132     }
3133   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3134   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3135   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3136   emit_insn (gen_umulsidi3_media (operands[4],
3137                                  sh_gen_truncate (SImode, operands[1], 0),
3138                                  sh_gen_truncate (SImode, operands[2], 0)));
3139   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3140   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3141   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3142   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3143   DONE;
3144 }")
3145
3146 \f
3147 ;; -------------------------------------------------------------------------
3148 ;; Logical operations
3149 ;; -------------------------------------------------------------------------
3150
3151 (define_insn "*andsi3_compact"
3152   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3153         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3154                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3155   "TARGET_SH1"
3156   "and  %2,%0"
3157   [(set_attr "type" "arith")])
3158
3159 (define_insn "*andsi3_media"
3160   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3161         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3162                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3163   "TARGET_SHMEDIA"
3164   "@
3165         and     %1, %2, %0
3166         andi    %1, %2, %0"
3167   [(set_attr "type" "arith_media")])
3168
3169 ;; If the constant is 255, then emit an extu.b instruction instead of an
3170 ;; and, since that will give better code.
3171
3172 (define_expand "andsi3"
3173   [(set (match_operand:SI 0 "arith_reg_operand" "")
3174         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3175                 (match_operand:SI 2 "logical_operand" "")))]
3176   ""
3177   "
3178 {
3179   if (TARGET_SH1
3180       && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
3181     {
3182       emit_insn (gen_zero_extendqisi2 (operands[0],
3183                                        gen_lowpart (QImode, operands[1])));
3184       DONE;
3185     }
3186 }")
3187
3188 (define_insn_and_split "anddi3"
3189   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3190         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3191                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3192   "TARGET_SHMEDIA"
3193   "@
3194         and     %1, %2, %0
3195         andi    %1, %2, %0
3196         #"
3197   "reload_completed
3198    && ! logical_operand (operands[2], DImode)"
3199   [(const_int 0)]
3200   "
3201 {
3202   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3203     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3204   else
3205     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3206   DONE;
3207 }"
3208   [(set_attr "type" "arith_media")])
3209
3210 (define_insn "andcsi3"
3211   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3212         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3213                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3214   "TARGET_SHMEDIA"
3215   "andc %1,%2,%0"
3216   [(set_attr "type" "arith_media")])
3217
3218 (define_insn "andcdi3"
3219   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3220         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3221                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3222   "TARGET_SHMEDIA"
3223   "andc %1,%2,%0"
3224   [(set_attr "type" "arith_media")])
3225
3226 (define_expand "iorsi3"
3227   [(set (match_operand:SI 0 "arith_reg_operand" "")
3228         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3229                 (match_operand:SI 2 "logical_operand" "")))]
3230   ""
3231   "")
3232
3233 (define_insn "*iorsi3_compact"
3234   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3235         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3236                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3237   "TARGET_SH1"
3238   "or   %2,%0"
3239   [(set_attr "type" "arith")])
3240
3241 (define_insn "*iorsi3_media"
3242   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3243         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3244                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3245   "TARGET_SHMEDIA"
3246   "@
3247         or      %1, %2, %0
3248         ori     %1, %2, %0"
3249   [(set_attr "type" "arith_media")])
3250
3251 (define_insn "iordi3"
3252   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3253         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3254                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3255   "TARGET_SHMEDIA"
3256   "@
3257         or      %1, %2, %0
3258         ori     %1, %2, %0"
3259   [(set_attr "type" "arith_media")])
3260
3261 (define_insn_and_split "*logical_sidi3"
3262   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3263         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3264                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3265                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3266   "TARGET_SHMEDIA"
3267   "#"
3268   "&& reload_completed"
3269   [(set (match_dup 0) (match_dup 3))]
3270   "
3271 {
3272   operands[3]
3273     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3274                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3275                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3276 }")
3277
3278 (define_insn_and_split "*logical_sidisi3"
3279   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3280         (truncate:SI (sign_extend:DI
3281                         (match_operator:SI 3 "logical_operator"
3282                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3283                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3284   "TARGET_SHMEDIA"
3285   "#"
3286   "&& 1"
3287   [(set (match_dup 0) (match_dup 3))])
3288
3289 (define_insn_and_split "*logical_sidi3_2"
3290   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3291         (sign_extend:DI (truncate:SI (sign_extend:DI
3292                         (match_operator:SI 3 "logical_operator"
3293                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3294                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3295   "TARGET_SHMEDIA"
3296   "#"
3297   "&& 1"
3298   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3299
3300 (define_expand "xorsi3"
3301   [(set (match_operand:SI 0 "arith_reg_operand" "")
3302         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3303                 (match_operand:SI 2 "xor_operand" "")))]
3304   ""
3305   "")
3306
3307 (define_insn "*xorsi3_compact"
3308   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3309         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3310                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3311   "TARGET_SH1"
3312   "xor  %2,%0"
3313   [(set_attr "type" "arith")])
3314
3315 (define_insn "*xorsi3_media"
3316   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3317         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3318                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3319   "TARGET_SHMEDIA"
3320   "@
3321         xor     %1, %2, %0
3322         xori    %1, %2, %0"
3323   [(set_attr "type" "arith_media")])
3324
3325 (define_insn "xordi3"
3326   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3327         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3328                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3329   "TARGET_SHMEDIA"
3330   "@
3331         xor     %1, %2, %0
3332         xori    %1, %2, %0"
3333   [(set_attr "type" "arith_media")])
3334
3335 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3336 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3337 (define_split
3338   [(set (match_operand:DI 0 "arith_reg_dest" "")
3339         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3340                           [(match_operand 1 "any_register_operand" "")
3341                            (match_operand 2 "any_register_operand" "")])))]
3342   "TARGET_SHMEDIA"
3343   [(set (match_dup 5) (match_dup 4))
3344    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3345 "
3346 {
3347   enum machine_mode inmode = GET_MODE (operands[1]);
3348   int offset = 0;
3349
3350   if (GET_CODE (operands[0]) == SUBREG)
3351     {
3352       offset = SUBREG_BYTE (operands[0]);
3353       operands[0] = SUBREG_REG (operands[0]);
3354     }
3355   gcc_assert (GET_CODE (operands[0]) == REG);
3356   if (! TARGET_LITTLE_ENDIAN)
3357     offset += 8 - GET_MODE_SIZE (inmode);
3358   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3359 }")
3360 \f
3361 ;; -------------------------------------------------------------------------
3362 ;; Shifts and rotates
3363 ;; -------------------------------------------------------------------------
3364
3365 (define_expand "rotldi3"
3366   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3367         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3368                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3369   "TARGET_SHMEDIA"
3370   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3371
3372 (define_insn "rotldi3_mextr"
3373   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3374         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3375                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3376   "TARGET_SHMEDIA"
3377   "*
3378 {
3379   static char templ[16];
3380
3381   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3382            8 - (int) (INTVAL (operands[2]) >> 3));
3383   return templ;
3384 }"
3385   [(set_attr "type" "arith_media")])
3386
3387 (define_expand "rotrdi3"
3388   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3389         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3390                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3391   "TARGET_SHMEDIA"
3392   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3393
3394 (define_insn "rotrdi3_mextr"
3395   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3396         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3397                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3398   "TARGET_SHMEDIA"
3399   "*
3400 {
3401   static char templ[16];
3402
3403   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3404   return templ;
3405 }"
3406   [(set_attr "type" "arith_media")])
3407
3408 (define_split
3409   [(set (match_operand:DI 0 "arith_reg_dest" "")
3410         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3411                                          "ua_address_operand" "")))
3412                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3413                            (const_int 8))))
3414    (clobber (match_operand:DI 3 "register_operand" ""))]
3415   "TARGET_SHMEDIA"
3416   [(match_dup 4) (match_dup 5)]
3417   "
3418 {
3419   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3420                  (operands[3], operands[1]));
3421   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3422                               GEN_INT (56), GEN_INT (8));
3423 }")
3424
3425 (define_insn "rotlsi3_1"
3426   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3427         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3428                    (const_int 1)))
3429    (set (reg:SI T_REG)
3430         (lshiftrt:SI (match_dup 1) (const_int 31)))]
3431   "TARGET_SH1"
3432   "rotl %0"
3433   [(set_attr "type" "arith")])
3434
3435 (define_insn "rotlsi3_31"
3436   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3437         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3438                    (const_int 31)))
3439    (clobber (reg:SI T_REG))]
3440   "TARGET_SH1"
3441   "rotr %0"
3442   [(set_attr "type" "arith")])
3443
3444 (define_insn "rotlsi3_16"
3445   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3446         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3447                    (const_int 16)))]
3448   "TARGET_SH1"
3449   "swap.w       %1,%0"
3450   [(set_attr "type" "arith")])
3451
3452 (define_expand "rotlsi3"
3453   [(set (match_operand:SI 0 "arith_reg_dest" "")
3454         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3455                    (match_operand:SI 2 "immediate_operand" "")))]
3456   "TARGET_SH1"
3457   "
3458 {
3459   static const char rot_tab[] = {
3460     000, 000, 000, 000, 000, 000, 010, 001,
3461     001, 001, 011, 013, 003, 003, 003, 003,
3462     003, 003, 003, 003, 003, 013, 012, 002,
3463     002, 002, 010, 000, 000, 000, 000, 000,
3464   };
3465
3466   int count, choice;
3467
3468   if (GET_CODE (operands[2]) != CONST_INT)
3469     FAIL;
3470   count = INTVAL (operands[2]);
3471   choice = rot_tab[count];
3472   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3473     FAIL;
3474   choice &= 7;
3475   switch (choice)
3476     {
3477     case 0:
3478       emit_move_insn (operands[0], operands[1]);
3479       count -= (count & 16) * 2;
3480       break;
3481     case 3:
3482      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3483      count -= 16;
3484      break;
3485     case 1:
3486     case 2:
3487       {
3488         rtx parts[2];
3489         parts[0] = gen_reg_rtx (SImode);
3490         parts[1] = gen_reg_rtx (SImode);
3491         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3492         emit_move_insn (parts[choice-1], operands[1]);
3493         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3494         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3495         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3496         count = (count & ~16) - 8;
3497       }
3498     }
3499
3500   for (; count > 0; count--)
3501     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3502   for (; count < 0; count++)
3503     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3504
3505   DONE;
3506 }")
3507
3508 (define_insn "*rotlhi3_8"
3509   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3510         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3511                    (const_int 8)))]
3512   "TARGET_SH1"
3513   "swap.b       %1,%0"
3514   [(set_attr "type" "arith")])
3515
3516 (define_expand "rotlhi3"
3517   [(set (match_operand:HI 0 "arith_reg_operand" "")
3518         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3519                    (match_operand:HI 2 "immediate_operand" "")))]
3520   "TARGET_SH1"
3521   "
3522 {
3523   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
3524     FAIL;
3525 }")
3526
3527 ;;
3528 ;; shift left
3529
3530 (define_insn "ashlsi3_sh2a"
3531   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3532         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3533                    (match_operand:SI 2 "arith_reg_operand" "r")))]
3534   "TARGET_SH2A"
3535   "shad %2,%0"
3536   [(set_attr "type" "arith")
3537    (set_attr "length" "4")])
3538
3539 ;; This pattern is used by init_expmed for computing the costs of shift
3540 ;; insns.
3541
3542 (define_insn_and_split "ashlsi3_std"
3543   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3544         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3545                    (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3546    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3547   "TARGET_SH3
3548    || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
3549        && CONST_OK_FOR_P27 (INTVAL (operands[2])))"
3550   "@
3551    shld %2,%0
3552    add  %0,%0
3553    shll%O2      %0
3554    #"
3555   "TARGET_SH3
3556    && reload_completed
3557    && GET_CODE (operands[2]) == CONST_INT
3558    && ! CONST_OK_FOR_P27 (INTVAL (operands[2]))"
3559   [(set (match_dup 3) (match_dup 2))
3560    (parallel
3561     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3562      (clobber (match_dup 4))])]
3563   "operands[4] = gen_rtx_SCRATCH (SImode);"
3564   [(set_attr "length" "*,*,*,4")
3565    (set_attr "type" "dyn_shift,arith,arith,arith")])
3566
3567 (define_insn "ashlhi3_k"
3568   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3569         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3570                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
3571   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))"
3572   "@
3573         add     %0,%0
3574         shll%O2 %0"
3575   [(set_attr "type" "arith")])
3576
3577 (define_insn "ashlsi3_n"
3578   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3579         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3580                    (match_operand:SI 2 "const_int_operand" "n")))
3581    (clobber (reg:SI T_REG))]
3582   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3583   "#"
3584   [(set (attr "length")
3585         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3586                (const_string "2")
3587                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3588                (const_string "4")
3589                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3590                (const_string "6")]
3591               (const_string "8")))
3592    (set_attr "type" "arith")])
3593
3594 (define_split
3595   [(set (match_operand:SI 0 "arith_reg_dest" "")
3596         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3597                    (match_operand:SI 2 "const_int_operand" "")))
3598    (clobber (reg:SI T_REG))]
3599   "TARGET_SH1 && reload_completed"
3600   [(use (reg:SI R0_REG))]
3601   "
3602 {
3603   gen_shifty_op (ASHIFT, operands);
3604   DONE;
3605 }")
3606
3607 (define_insn "ashlsi3_media"
3608   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3609         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3610                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
3611   "TARGET_SHMEDIA"
3612   "@
3613         shlld.l %1, %2, %0
3614         shlli.l %1, %2, %0"
3615   [(set_attr "type" "arith_media")
3616    (set_attr "highpart" "ignore")])
3617
3618 (define_expand "ashlsi3"
3619   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3620                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3621                               (match_operand:SI 2 "nonmemory_operand" "")))
3622               (clobber (reg:SI T_REG))])]
3623   ""
3624   "
3625 {
3626   if (TARGET_SHMEDIA)
3627     {
3628       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3629       DONE;
3630     }
3631   if (GET_CODE (operands[2]) == CONST_INT
3632       && sh_dynamicalize_shift_p (operands[2]))
3633     operands[2] = force_reg (SImode, operands[2]);
3634   if (TARGET_SH3)
3635     {
3636       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3637       DONE;
3638     }
3639   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3640     FAIL;
3641 }")
3642
3643 (define_insn "*ashlhi3_n"
3644   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3645         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3646                    (match_operand:HI 2 "const_int_operand" "n")))
3647    (clobber (reg:SI T_REG))]
3648   "TARGET_SH1"
3649   "#"
3650   [(set (attr "length")
3651         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3652                (const_string "2")
3653                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3654                (const_string "4")]
3655               (const_string "6")))
3656    (set_attr "type" "arith")])
3657
3658 (define_expand "ashlhi3"
3659   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3660                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3661                               (match_operand:SI 2 "nonmemory_operand" "")))
3662               (clobber (reg:SI T_REG))])]
3663   "TARGET_SH1"
3664   "
3665 {
3666   if (GET_CODE (operands[2]) != CONST_INT)
3667     FAIL;
3668   /* It may be possible to call gen_ashlhi3 directly with more generic
3669      operands.  Make sure operands[1] is a HImode register here.  */
3670   if (!arith_reg_operand (operands[1], HImode))
3671     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3672 }")
3673
3674 (define_split
3675   [(set (match_operand:HI 0 "arith_reg_dest" "")
3676         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3677                    (match_operand:HI 2 "const_int_operand" "")))
3678    (clobber (reg:SI T_REG))]
3679   "TARGET_SH1 && reload_completed"
3680   [(use (reg:SI R0_REG))]
3681   "
3682 {
3683   gen_shifty_hi_op (ASHIFT, operands);
3684   DONE;
3685 }")
3686
3687 ;
3688 ; arithmetic shift right
3689 ;
3690
3691 (define_insn "ashrsi3_sh2a"
3692   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3693         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3694                    (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3695   "TARGET_SH2A"
3696   "shad %2,%0"
3697   [(set_attr "type" "dyn_shift")
3698    (set_attr "length" "4")])
3699
3700 (define_insn "ashrsi3_k"
3701   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3702         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3703                      (match_operand:SI 2 "const_int_operand" "M")))
3704    (clobber (reg:SI T_REG))]
3705   "TARGET_SH1 && INTVAL (operands[2]) == 1"
3706   "shar %0"
3707   [(set_attr "type" "arith")])
3708
3709 ;; We can't do HImode right shifts correctly unless we start out with an
3710 ;; explicit zero / sign extension; doing that would result in worse overall
3711 ;; code, so just let the machine independent code widen the mode.
3712 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3713
3714
3715 ;; ??? This should be a define expand.
3716
3717 (define_insn "ashrsi2_16"
3718   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3719         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3720                      (const_int 16)))]
3721   "TARGET_SH1"
3722   "#"
3723   [(set_attr "length" "4")])
3724
3725 (define_split
3726   [(set (match_operand:SI 0 "arith_reg_dest" "")
3727         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3728                      (const_int 16)))]
3729   "TARGET_SH1"
3730   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3731    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3732   "operands[2] = gen_lowpart (HImode, operands[0]);")
3733
3734 ;; ??? This should be a define expand.
3735
3736 (define_insn "ashrsi2_31"
3737   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3738         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3739                      (const_int 31)))
3740    (clobber (reg:SI T_REG))]
3741   "TARGET_SH1"
3742   "#"
3743   [(set_attr "length" "4")])
3744
3745 (define_split
3746   [(set (match_operand:SI 0 "arith_reg_dest" "")
3747         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3748                      (const_int 31)))
3749    (clobber (reg:SI T_REG))]
3750   "TARGET_SH1"
3751   [(const_int 0)]
3752   "
3753 {
3754   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3755   emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3756   DONE;
3757 }")
3758
3759 (define_peephole2
3760   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3761    (set (reg:SI T_REG)
3762         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3763   "TARGET_SH1
3764    && peep2_reg_dead_p (2, operands[0])
3765    && peep2_reg_dead_p (2, operands[1])"
3766   [(const_int 0)]
3767   "
3768 {
3769   emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3770   DONE;
3771 }")
3772
3773 (define_insn "ashlsi_c"
3774   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3775         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3776    (set (reg:SI T_REG)
3777         (lt:SI (match_dup 1) (const_int 0)))]
3778   "TARGET_SH1"
3779   "shll %0"
3780   [(set_attr "type" "arith")])
3781
3782 (define_insn "*ashlsi_c_void"
3783   [(set (reg:SI T_REG)
3784         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3785    (clobber (match_scratch:SI 1 "=0"))]
3786   "TARGET_SH1 && cse_not_expected"
3787   "shll %0"
3788   [(set_attr "type" "arith")])
3789
3790 (define_insn "ashrsi3_d"
3791   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3792         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3793                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3794   "TARGET_SH3"
3795   "shad %2,%0"
3796   [(set_attr "type" "dyn_shift")])
3797
3798 (define_insn "ashrsi3_n"
3799   [(set (reg:SI R4_REG)
3800         (ashiftrt:SI (reg:SI R4_REG)
3801                      (match_operand:SI 0 "const_int_operand" "i")))
3802    (clobber (reg:SI T_REG))
3803    (clobber (reg:SI PR_REG))
3804    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3805   "TARGET_SH1"
3806   "jsr  @%1%#"
3807   [(set_attr "type" "sfunc")
3808    (set_attr "needs_delay_slot" "yes")])
3809
3810 (define_insn "ashrsi3_media"
3811   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3812         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3813                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3814   "TARGET_SHMEDIA"
3815   "@
3816         shard.l %1, %2, %0
3817         shari.l %1, %2, %0"
3818   [(set_attr "type" "arith_media")
3819    (set_attr "highpart" "ignore")])
3820
3821 (define_expand "ashrsi3"
3822   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3823                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3824                                 (match_operand:SI 2 "nonmemory_operand" "")))
3825               (clobber (reg:SI T_REG))])]
3826   ""
3827   "
3828 {
3829   if (TARGET_SHMEDIA)
3830     {
3831       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3832       DONE;
3833     }
3834   if (expand_ashiftrt (operands))
3835     DONE;
3836   else
3837     FAIL;
3838 }")
3839
3840 ;; logical shift right
3841
3842 (define_insn "lshrsi3_sh2a"
3843   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3844         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3845                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3846   "TARGET_SH2A"
3847   "shld %2,%0"
3848   [(set_attr "type" "dyn_shift")
3849    (set_attr "length" "4")])
3850
3851 (define_insn "lshrsi3_d"
3852   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3853         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3854                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3855   "TARGET_SH3"
3856   "shld %2,%0"
3857   [(set_attr "type" "dyn_shift")])
3858
3859 ;;  Only the single bit shift clobbers the T bit.
3860
3861 (define_insn "lshrsi3_m"
3862   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3863         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3864                      (match_operand:SI 2 "const_int_operand" "M")))
3865    (clobber (reg:SI T_REG))]
3866   "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
3867   "shlr %0"
3868   [(set_attr "type" "arith")])
3869
3870 (define_insn "lshrsi3_k"
3871   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3872         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3873                      (match_operand:SI 2 "const_int_operand" "P27")))]
3874   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))
3875    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
3876   "shlr%O2      %0"
3877   [(set_attr "type" "arith")])
3878
3879 (define_insn "lshrsi3_n"
3880   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3881         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3882                      (match_operand:SI 2 "const_int_operand" "n")))
3883    (clobber (reg:SI T_REG))]
3884   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3885   "#"
3886   [(set (attr "length")
3887         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3888                (const_string "2")
3889                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3890                (const_string "4")
3891                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3892                (const_string "6")]
3893               (const_string "8")))
3894    (set_attr "type" "arith")])
3895
3896 (define_split
3897   [(set (match_operand:SI 0 "arith_reg_dest" "")
3898         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3899                      (match_operand:SI 2 "const_int_operand" "")))
3900    (clobber (reg:SI T_REG))]
3901   "TARGET_SH1 && reload_completed"
3902   [(use (reg:SI R0_REG))]
3903   "
3904 {
3905   gen_shifty_op (LSHIFTRT, operands);
3906   DONE;
3907 }")
3908
3909 (define_insn "lshrsi3_media"
3910   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3911         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3912                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3913   "TARGET_SHMEDIA"
3914   "@
3915         shlrd.l %1, %2, %0
3916         shlri.l %1, %2, %0"
3917   [(set_attr "type" "arith_media")
3918    (set_attr "highpart" "ignore")])
3919
3920 (define_expand "lshrsi3"
3921   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3922                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3923                                 (match_operand:SI 2 "nonmemory_operand" "")))
3924               (clobber (reg:SI T_REG))])]
3925   ""
3926   "
3927 {
3928   if (TARGET_SHMEDIA)
3929     {
3930       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3931       DONE;
3932     }
3933   if (GET_CODE (operands[2]) == CONST_INT
3934       && sh_dynamicalize_shift_p (operands[2]))
3935     operands[2] = force_reg (SImode, operands[2]);
3936   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3937     {
3938       rtx count = copy_to_mode_reg (SImode, operands[2]);
3939       emit_insn (gen_negsi2 (count, count));
3940       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3941       DONE;
3942     }
3943   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3944     FAIL;
3945 }")
3946
3947 ;; ??? This should be a define expand.
3948
3949 (define_insn "ashldi3_k"
3950   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3951         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3952                    (const_int 1)))
3953    (clobber (reg:SI T_REG))]
3954   "TARGET_SH1"
3955   "shll %R0\;rotcl      %S0"
3956   [(set_attr "length" "4")
3957    (set_attr "type" "arith")])
3958
3959 (define_insn "ashldi3_media"
3960   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3961         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3962                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
3963   "TARGET_SHMEDIA"
3964   "@
3965         shlld   %1, %2, %0
3966         shlli   %1, %2, %0"
3967   [(set_attr "type" "arith_media")])
3968
3969 (define_insn "*ashldisi3_media"
3970   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3971         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3972                    (match_operand:DI 2 "const_int_operand" "n")))]
3973   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3974   "shlli.l      %1, %2, %0"
3975   [(set_attr "type" "arith_media")
3976    (set_attr "highpart" "ignore")])
3977
3978 (define_expand "ashldi3"
3979   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3980                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3981                               (match_operand:DI 2 "immediate_operand" "")))
3982               (clobber (reg:SI T_REG))])]
3983   ""
3984   "
3985 {
3986   if (TARGET_SHMEDIA)
3987     {
3988       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3989       DONE;
3990     }
3991   if (GET_CODE (operands[2]) != CONST_INT
3992       || INTVAL (operands[2]) != 1)
3993     FAIL;
3994 }")
3995
3996 ;; ??? This should be a define expand.
3997
3998 (define_insn "lshrdi3_k"
3999   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4000         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4001                      (const_int 1)))
4002    (clobber (reg:SI T_REG))]
4003   "TARGET_SH1"
4004   "shlr %S0\;rotcr      %R0"
4005   [(set_attr "length" "4")
4006    (set_attr "type" "arith")])
4007
4008 (define_insn "lshrdi3_media"
4009   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4010         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4011                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4012   "TARGET_SHMEDIA
4013    && (arith_reg_dest (operands[0], DImode)
4014        || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 32))"
4015   "@
4016         shlrd   %1, %2, %0
4017         shlri   %1, %2, %0"
4018   [(set_attr "type" "arith_media")])
4019
4020 (define_insn "*lshrdisi3_media"
4021   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4022         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4023                      (match_operand:DI 2 "const_int_operand" "n")))]
4024   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4025   "shlri.l      %1, %2, %0"
4026   [(set_attr "type" "arith_media")
4027    (set_attr "highpart" "ignore")])
4028
4029 (define_expand "lshrdi3"
4030   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4031                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4032                                (match_operand:DI 2 "immediate_operand" "")))
4033              (clobber (reg:SI T_REG))])]
4034   ""
4035   "
4036 {
4037   if (TARGET_SHMEDIA)
4038     {
4039       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
4040       DONE;
4041     }
4042   if (GET_CODE (operands[2]) != CONST_INT
4043       || INTVAL (operands[2]) != 1)
4044     FAIL;
4045 }")
4046
4047 ;; ??? This should be a define expand.
4048
4049 (define_insn "ashrdi3_k"
4050   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4051         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4052                      (const_int 1)))
4053    (clobber (reg:SI T_REG))]
4054   "TARGET_SH1"
4055   "shar %S0\;rotcr      %R0"
4056   [(set_attr "length" "4")
4057    (set_attr "type" "arith")])
4058
4059 (define_insn "ashrdi3_media"
4060   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4061         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4062                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4063   "TARGET_SHMEDIA
4064    && (arith_reg_dest (operands[0], DImode)
4065        || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32))"
4066   "@
4067         shard   %1, %2, %0
4068         shari   %1, %2, %0"
4069   [(set_attr "type" "arith_media")])
4070
4071 (define_insn "*ashrdisi3_media"
4072   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4073         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4074                      (match_operand:DI 2 "const_int_operand" "n")))]
4075   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4076   "shari.l      %1, %2, %0"
4077   [(set_attr "type" "arith_media")
4078    (set_attr "highpart" "ignore")])
4079
4080 (define_insn "ashrdisi3_media_high"
4081   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4082         (truncate:SI
4083            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4084                         (match_operand:DI 2 "const_int_operand" "n"))))]
4085   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4086   "shari        %1, %2, %0"
4087   [(set_attr "type" "arith_media")])
4088
4089 (define_insn "ashrdisi3_media_opaque"
4090   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4091         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4092                     (match_operand:DI 2 "const_int_operand" "n")]
4093          UNSPEC_ASHIFTRT))]
4094   "TARGET_SHMEDIA"
4095   "shari        %1, %2, %0"
4096   [(set_attr "type" "arith_media")])
4097
4098 (define_expand "ashrdi3"
4099   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4100                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4101                                 (match_operand:DI 2 "immediate_operand" "")))
4102               (clobber (reg:SI T_REG))])]
4103   ""
4104   "
4105 {
4106   if (TARGET_SHMEDIA)
4107     {
4108       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4109       DONE;
4110     }
4111   if (GET_CODE (operands[2]) != CONST_INT
4112       || INTVAL (operands[2]) != 1)
4113     FAIL;
4114 }")
4115
4116 ;; combined left/right shift
4117
4118 (define_split
4119   [(set (match_operand:SI 0 "register_operand" "")
4120         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4121                            (match_operand:SI 2 "const_int_operand" ""))
4122                 (match_operand:SI 3 "const_int_operand" "")))]
4123   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4124   [(use (reg:SI R0_REG))]
4125   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4126    DONE;")
4127
4128 (define_split
4129   [(set (match_operand:SI 0 "register_operand" "")
4130         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4131                            (match_operand:SI 2 "const_int_operand" ""))
4132                 (match_operand:SI 3 "const_int_operand" "")))
4133    (clobber (reg:SI T_REG))]
4134   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4135   [(use (reg:SI R0_REG))]
4136   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4137    DONE;")
4138
4139 (define_insn ""
4140   [(set (match_operand:SI 0 "register_operand" "=r")
4141         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4142                            (match_operand:SI 2 "const_int_operand" "n"))
4143                 (match_operand:SI 3 "const_int_operand" "n")))
4144    (clobber (reg:SI T_REG))]
4145   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4146  "#"
4147   [(set (attr "length")
4148         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4149                (const_string "4")
4150                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4151                (const_string "6")
4152                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4153                (const_string "8")
4154                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4155                (const_string "10")
4156                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4157                (const_string "12")
4158                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4159                (const_string "14")
4160                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4161                (const_string "16")]
4162               (const_string "18")))
4163    (set_attr "type" "arith")])
4164
4165 (define_insn ""
4166   [(set (match_operand:SI 0 "register_operand" "=z")
4167         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4168                            (match_operand:SI 2 "const_int_operand" "n"))
4169                 (match_operand:SI 3 "const_int_operand" "n")))
4170    (clobber (reg:SI T_REG))]
4171   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4172  "#"
4173   [(set (attr "length")
4174         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4175                (const_string "4")
4176                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4177                (const_string "6")
4178                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4179                (const_string "8")]
4180               (const_string "10")))
4181    (set_attr "type" "arith")])
4182
4183 ;; shift left / and combination with a scratch register: The combine pass
4184 ;; does not accept the individual instructions, even though they are
4185 ;; cheap.  But it needs a precise description so that it is usable after
4186 ;; reload.
4187 (define_insn "and_shl_scratch"
4188   [(set (match_operand:SI 0 "register_operand" "=r,&r")
4189         (lshiftrt:SI
4190          (ashift:SI
4191           (and:SI
4192            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4193                         (match_operand:SI 2 "const_int_operand" "N,n"))
4194            (match_operand:SI 3 "" "0,r"))
4195           (match_operand:SI 4 "const_int_operand" "n,n"))
4196          (match_operand:SI 5 "const_int_operand" "n,n")))
4197    (clobber (reg:SI T_REG))]
4198   "TARGET_SH1"
4199   "#"
4200   [(set (attr "length")
4201         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4202                (const_string "4")
4203                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4204                (const_string "6")
4205                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4206                (const_string "8")
4207                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4208                (const_string "10")]
4209               (const_string "12")))
4210    (set_attr "type" "arith")])
4211
4212 (define_split
4213   [(set (match_operand:SI 0 "register_operand" "")
4214         (lshiftrt:SI
4215          (ashift:SI
4216           (and:SI
4217            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4218                         (match_operand:SI 2 "const_int_operand" ""))
4219            (match_operand:SI 3 "register_operand" ""))
4220           (match_operand:SI 4 "const_int_operand" ""))
4221          (match_operand:SI 5 "const_int_operand" "")))
4222    (clobber (reg:SI T_REG))]
4223   "TARGET_SH1"
4224   [(use (reg:SI R0_REG))]
4225   "
4226 {
4227   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4228
4229   if (INTVAL (operands[2]))
4230     {
4231       gen_shifty_op (LSHIFTRT, operands);
4232     }
4233   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4234   operands[2] = operands[4];
4235   gen_shifty_op (ASHIFT, operands);
4236   if (INTVAL (operands[5]))
4237     {
4238       operands[2] = operands[5];
4239       gen_shifty_op (LSHIFTRT, operands);
4240     }
4241   DONE;
4242 }")
4243
4244 ;; signed left/right shift combination.
4245 (define_split
4246   [(set (match_operand:SI 0 "register_operand" "")
4247         (sign_extract:SI
4248          (ashift:SI (match_operand:SI 1 "register_operand" "")
4249                     (match_operand:SI 2 "const_int_operand" ""))
4250          (match_operand:SI 3 "const_int_operand" "")
4251          (const_int 0)))
4252    (clobber (reg:SI T_REG))]
4253   "TARGET_SH1"
4254   [(use (reg:SI R0_REG))]
4255   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4256    DONE;")
4257
4258 (define_insn "shl_sext_ext"
4259   [(set (match_operand:SI 0 "register_operand" "=r")
4260         (sign_extract:SI
4261          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4262                     (match_operand:SI 2 "const_int_operand" "n"))
4263          (match_operand:SI 3 "const_int_operand" "n")
4264          (const_int 0)))
4265    (clobber (reg:SI T_REG))]
4266   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4267   "#"
4268   [(set (attr "length")
4269         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
4270                (const_string "2")
4271                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4272                (const_string "4")
4273                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4274                (const_string "6")
4275                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4276                (const_string "8")
4277                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4278                (const_string "10")
4279                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4280                (const_string "12")
4281                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4282                (const_string "14")
4283                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4284                (const_string "16")]
4285               (const_string "18")))
4286     (set_attr "type" "arith")])
4287
4288 (define_insn "shl_sext_sub"
4289   [(set (match_operand:SI 0 "register_operand" "=z")
4290         (sign_extract:SI
4291          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4292                     (match_operand:SI 2 "const_int_operand" "n"))
4293          (match_operand:SI 3 "const_int_operand" "n")
4294          (const_int 0)))
4295    (clobber (reg:SI T_REG))]
4296   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4297   "#"
4298   [(set (attr "length")
4299         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4300                (const_string "6")
4301                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4302                (const_string "8")
4303                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4304                (const_string "10")
4305                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4306                (const_string "12")]
4307               (const_string "14")))
4308     (set_attr "type" "arith")])
4309
4310 ;; These patterns are found in expansions of DImode shifts by 16, and
4311 ;; allow the xtrct instruction to be generated from C source.
4312
4313 (define_insn "xtrct_left"
4314   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4315         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4316                            (const_int 16))
4317                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4318                              (const_int 16))))]
4319   "TARGET_SH1"
4320   "xtrct        %1,%0"
4321   [(set_attr "type" "arith")])
4322
4323 (define_insn "xtrct_right"
4324   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4325         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4326                              (const_int 16))
4327                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4328                            (const_int 16))))]
4329   "TARGET_SH1"
4330   "xtrct        %2,%0"
4331   [(set_attr "type" "arith")])
4332
4333 ;; -------------------------------------------------------------------------
4334 ;; Unary arithmetic
4335 ;; -------------------------------------------------------------------------
4336
4337 (define_insn "negc"
4338   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4339         (neg:SI (plus:SI (reg:SI T_REG)
4340                          (match_operand:SI 1 "arith_reg_operand" "r"))))
4341    (set (reg:SI T_REG)
4342         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4343                (const_int 0)))]
4344   "TARGET_SH1"
4345   "negc %1,%0"
4346   [(set_attr "type" "arith")])
4347
4348 (define_insn "*negdi_media"
4349   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4350         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4351   "TARGET_SHMEDIA"
4352   "sub  r63, %1, %0"
4353   [(set_attr "type" "arith_media")])
4354
4355 (define_expand "negdi2"
4356   [(set (match_operand:DI 0 "arith_reg_operand" "")
4357         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
4358   ""
4359   "
4360 {
4361   if (TARGET_SH1)
4362     {
4363       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4364       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4365
4366       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4367       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4368
4369       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4370       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4371
4372       emit_insn (gen_clrt ());
4373       emit_insn (gen_negc (low_dst, low_src));
4374       emit_insn (gen_negc (high_dst, high_src));
4375       DONE;
4376     }
4377 }")
4378
4379 (define_insn "negsi2"
4380   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4381         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4382   "TARGET_SH1"
4383   "neg  %1,%0"
4384   [(set_attr "type" "arith")])
4385
4386 (define_insn "one_cmplsi2"
4387   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4388         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4389   "TARGET_SH1"
4390   "not  %1,%0"
4391   [(set_attr "type" "arith")])
4392
4393 (define_expand "one_cmpldi2"
4394   [(set (match_operand:DI 0 "arith_reg_dest" "")
4395         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4396                 (const_int -1)))]
4397   "TARGET_SHMEDIA" "")
4398
4399 /* The SH4 202 can do zero-offset branches without pipeline stalls.
4400    This can be used as some kind of conditional execution, which is useful
4401    for abs.  */
4402 (define_split
4403   [(set (match_operand:SI 0 "arith_reg_dest" "")
4404         (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
4405                          (match_operand:SI 1 "arith_reg_operand" ""))
4406                  (reg:SI T_REG)))]
4407   "TARGET_HARD_SH4"
4408   [(const_int 0)]
4409   "emit_insn (gen_movsi_i (operands[0], operands[1]));
4410    emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
4411    DONE;")
4412
4413 (define_insn "cneg"
4414   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4415         (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
4416                       (match_operand:SI 1 "arith_reg_operand" "0")
4417                       (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4418   "TARGET_HARD_SH4"
4419   "bf 0f\;neg %2,%0\\n0:"
4420   [(set_attr "type" "arith") ;; poor approximation
4421    (set_attr "length" "4")])
4422
4423 \f
4424 ;; -------------------------------------------------------------------------
4425 ;; Zero extension instructions
4426 ;; -------------------------------------------------------------------------
4427
4428 (define_insn "zero_extendsidi2"
4429   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4430         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4431   "TARGET_SHMEDIA"
4432   "addz.l       %1, r63, %0"
4433   [(set_attr "type" "arith_media")
4434    (set_attr "highpart" "extend")])
4435
4436 (define_insn "zero_extendhidi2"
4437   [(set (match_operand:DI 0 "register_operand" "=r,r")
4438         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4439   "TARGET_SHMEDIA"
4440   "@
4441         #
4442         ld%M1.uw        %m1, %0"
4443   [(set_attr "type" "*,load_media")
4444    (set (attr "highpart")
4445         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4446                (const_string "user")]
4447               (const_string "ignore")))])
4448
4449 (define_split
4450   [(set (match_operand:DI 0 "register_operand" "")
4451         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4452   "TARGET_SHMEDIA && reload_completed"
4453   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4454    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4455   "
4456 {
4457   if (GET_CODE (operands[1]) == TRUNCATE)
4458     operands[1] = XEXP (operands[1], 0);
4459 }")
4460
4461 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4462 ;; reload the entire truncate expression.
4463 (define_insn_and_split "*loaddi_trunc"
4464   [(set (match_operand 0 "any_register_operand" "=r")
4465         (truncate (match_operand:DI 1 "memory_operand" "m")))]
4466   "TARGET_SHMEDIA && reload_completed"
4467   "#"
4468   "TARGET_SHMEDIA && reload_completed"
4469   [(set (match_dup 0) (match_dup 1))]
4470   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4471
4472 (define_insn "zero_extendqidi2"
4473   [(set (match_operand:DI 0 "register_operand" "=r,r")
4474         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4475   "TARGET_SHMEDIA"
4476   "@
4477         andi    %1, 255, %0
4478         ld%M1.ub        %m1, %0"
4479   [(set_attr "type" "arith_media,load_media")
4480    (set (attr "highpart")
4481         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4482                (const_string "user")]
4483               (const_string "ignore")))])
4484
4485 (define_expand "zero_extendhisi2"
4486   [(set (match_operand:SI 0 "arith_reg_operand" "")
4487         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4488   ""
4489   "
4490 {
4491   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4492     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4493 }")
4494
4495 (define_insn "*zero_extendhisi2_compact"
4496   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4497         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4498   "TARGET_SH1"
4499   "extu.w       %1,%0"
4500   [(set_attr "type" "arith")])
4501
4502 (define_insn "*zero_extendhisi2_media"
4503   [(set (match_operand:SI 0 "register_operand" "=r,r")
4504         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4505   "TARGET_SHMEDIA"
4506   "@
4507         #
4508         ld%M1.uw        %m1, %0"
4509   [(set_attr "type" "arith_media,load_media")
4510    (set (attr "highpart")
4511         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4512                (const_string "user")]
4513               (const_string "ignore")))])
4514
4515 (define_split
4516   [(set (match_operand:SI 0 "register_operand" "")
4517         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4518   "TARGET_SHMEDIA && reload_completed"
4519   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4520    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4521   "
4522 {
4523   rtx op1 = operands[1];
4524
4525   if (GET_CODE (op1) == TRUNCATE)
4526     op1 = XEXP (op1, 0);
4527   operands[2]
4528     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4529                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4530 }")
4531
4532 (define_expand "zero_extendqisi2"
4533   [(set (match_operand:SI 0 "arith_reg_operand" "")
4534         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4535   ""
4536   "
4537 {
4538   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4539     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4540 }")
4541
4542 (define_insn "*zero_extendqisi2_compact"
4543   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4544         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4545   "TARGET_SH1"
4546   "extu.b       %1,%0"
4547   [(set_attr "type" "arith")])
4548
4549 (define_insn "*zero_extendqisi2_media"
4550   [(set (match_operand:SI 0 "register_operand" "=r,r")
4551         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4552   "TARGET_SHMEDIA"
4553   "@
4554         andi    %1, 255, %0
4555         ld%M1.ub        %m1, %0"
4556   [(set_attr "type" "arith_media,load_media")
4557    (set (attr "highpart")
4558         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4559                (const_string "user")]
4560               (const_string "ignore")))])
4561
4562 (define_insn "zero_extendqihi2"
4563   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4564         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4565   "TARGET_SH1"
4566   "extu.b       %1,%0"
4567   [(set_attr "type" "arith")])
4568
4569 ;; -------------------------------------------------------------------------
4570 ;; Sign extension instructions
4571 ;; -------------------------------------------------------------------------
4572
4573 ;; ??? This should be a define expand.
4574 ;; ??? Or perhaps it should be dropped?
4575
4576 ;; convert_move generates good code for SH[1-4].
4577 (define_insn "extendsidi2"
4578   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4579         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4580   "TARGET_SHMEDIA"
4581   "@
4582         add.l   %1, r63, %0
4583         ld%M1.l %m1, %0
4584         fmov.sl %1, %0"
4585   [(set_attr "type" "arith_media,load_media,fpconv_media")
4586    (set (attr "highpart")
4587         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4588                (const_string "user")]
4589               (const_string "extend")))])
4590
4591 (define_insn "extendhidi2"
4592   [(set (match_operand:DI 0 "register_operand" "=r,r")
4593         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4594   "TARGET_SHMEDIA"
4595   "@
4596         #
4597         ld%M1.w %m1, %0"
4598   [(set_attr "type" "*,load_media")
4599    (set (attr "highpart")
4600         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4601                (const_string "user")]
4602               (const_string "ignore")))])
4603
4604 (define_split
4605   [(set (match_operand:DI 0 "register_operand" "")
4606         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4607   "TARGET_SHMEDIA && reload_completed"
4608   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4609    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4610   "
4611 {
4612   if (GET_CODE (operands[1]) == TRUNCATE)
4613     operands[1] = XEXP (operands[1], 0);
4614 }")
4615
4616 (define_insn "extendqidi2"
4617   [(set (match_operand:DI 0 "register_operand" "=r,r")
4618         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4619   "TARGET_SHMEDIA"
4620   "@
4621         #
4622         ld%M1.b %m1, %0"
4623   [(set_attr "type" "*,load_media")
4624    (set (attr "highpart")
4625         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4626                (const_string "user")]
4627               (const_string "ignore")))])
4628
4629 (define_split
4630   [(set (match_operand:DI 0 "register_operand" "")
4631         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4632   "TARGET_SHMEDIA && reload_completed"
4633   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4634    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4635   "
4636 {
4637   if (GET_CODE (operands[1]) == TRUNCATE)
4638     operands[1] = XEXP (operands[1], 0);
4639 }")
4640
4641 (define_expand "extendhisi2"
4642   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4643         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4644   ""
4645   "")
4646
4647 (define_insn "*extendhisi2_compact"
4648   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4649         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4650   "TARGET_SH1"
4651   "@
4652         exts.w  %1,%0
4653         mov.w   %1,%0"
4654   [(set_attr "type" "arith,load")])
4655
4656 (define_insn "*extendhisi2_media"
4657   [(set (match_operand:SI 0 "register_operand" "=r,r")
4658         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4659   "TARGET_SHMEDIA"
4660   "@
4661         #
4662         ld%M1.w %m1, %0"
4663   [(set_attr "type" "arith_media,load_media")
4664    (set (attr "highpart")
4665         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4666                (const_string "user")]
4667               (const_string "ignore")))])
4668
4669 (define_split
4670   [(set (match_operand:SI 0 "register_operand" "")
4671         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4672   "TARGET_SHMEDIA && reload_completed"
4673   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4674    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4675   "
4676 {
4677   rtx op1 = operands[1];
4678   if (GET_CODE (op1) == TRUNCATE)
4679     op1 = XEXP (op1, 0);
4680   operands[2]
4681     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4682                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4683 }")
4684
4685 (define_expand "extendqisi2"
4686   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4687         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4688   ""
4689   "")
4690
4691 (define_insn "*extendqisi2_compact"
4692   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4693         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4694   "TARGET_SH1"
4695   "@
4696         exts.b  %1,%0
4697         mov.b   %1,%0"
4698   [(set_attr "type" "arith,load")])
4699
4700 (define_insn "*extendqisi2_media"
4701   [(set (match_operand:SI 0 "register_operand" "=r,r")
4702         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4703   "TARGET_SHMEDIA"
4704   "@
4705         #
4706         ld%M1.b %m1, %0"
4707   [(set_attr "type" "arith_media,load_media")
4708    (set (attr "highpart")
4709         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4710                (const_string "user")]
4711               (const_string "ignore")))])
4712
4713 (define_split
4714   [(set (match_operand:SI 0 "register_operand" "")
4715         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4716   "TARGET_SHMEDIA && reload_completed"
4717   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4718    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4719    "
4720 {
4721   rtx op1 = operands[1];
4722   if (GET_CODE (op1) == TRUNCATE)
4723     op1 = XEXP (op1, 0);
4724   operands[2]
4725     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4726                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4727 }")
4728
4729 (define_insn "extendqihi2"
4730   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4731         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4732   "TARGET_SH1"
4733   "@
4734         exts.b  %1,%0
4735         mov.b   %1,%0"
4736   [(set_attr "type" "arith,load")])
4737
4738 /* It would seem useful to combine the truncXi patterns into the movXi
4739    patterns, but unary operators are ignored when matching constraints,
4740    so we need separate patterns.  */
4741 (define_insn "truncdisi2"
4742   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4743         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4744   "TARGET_SHMEDIA"
4745   "@
4746         add.l   %1, r63, %0
4747         st%M0.l %m0, %1
4748         fst%M0.s        %m0, %T1
4749         fmov.ls %1, %0
4750         fmov.sl %T1, %0
4751         fmov.s  %T1, %0"
4752   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4753    (set (attr "highpart")
4754         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4755                (const_string "user")]
4756               (const_string "extend")))])
4757
4758 (define_insn "truncdihi2"
4759   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4760         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4761   "TARGET_SHMEDIA"
4762   "@
4763         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4764         st%M0.w %m0, %1"
4765   [(set_attr "type"   "arith_media,store_media")
4766    (set_attr "length" "8,4")
4767    (set (attr "highpart")
4768         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4769                (const_string "user")]
4770               (const_string "extend")))])
4771
4772 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4773 ; Because we use zero extension, we can't provide signed QImode compares
4774 ; using a simple compare or conditional banch insn.
4775 (define_insn "truncdiqi2"
4776   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4777         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4778   "TARGET_SHMEDIA"
4779   "@
4780         andi    %1, 255, %0
4781         st%M0.b %m0, %1"
4782   [(set_attr "type"   "arith_media,store")
4783    (set (attr "highpart")
4784         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4785                (const_string "user")]
4786               (const_string "extend")))])
4787 ;; -------------------------------------------------------------------------
4788 ;; Move instructions
4789 ;; -------------------------------------------------------------------------
4790
4791 ;; define push and pop so it is easy for sh.c
4792 ;; We can't use push and pop on SHcompact because the stack must always
4793 ;; be 8-byte aligned.
4794
4795 (define_expand "push"
4796   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4797         (match_operand:SI 0 "register_operand" "r,l,x"))]
4798   "TARGET_SH1 && ! TARGET_SH5"
4799   "")
4800
4801 (define_expand "pop"
4802   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4803         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
4804   "TARGET_SH1 && ! TARGET_SH5"
4805   "")
4806
4807 (define_expand "push_e"
4808   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4809                    (match_operand:SF 0 "" ""))
4810               (use (reg:PSI FPSCR_REG))
4811               (clobber (scratch:SI))])]
4812   "TARGET_SH1 && ! TARGET_SH5"
4813   "")
4814
4815 (define_insn "push_fpul"
4816   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4817   "TARGET_SH2E && ! TARGET_SH5"
4818   "sts.l        fpul,@-r15"
4819   [(set_attr "type" "fstore")
4820    (set_attr "late_fp_use" "yes")
4821    (set_attr "hit_stack" "yes")])
4822
4823 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4824 ;; so use that.
4825 (define_expand "push_4"
4826   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4827                    (match_operand:DF 0 "" ""))
4828               (use (reg:PSI FPSCR_REG))
4829               (clobber (scratch:SI))])]
4830   "TARGET_SH1 && ! TARGET_SH5"
4831   "")
4832
4833 (define_expand "pop_e"
4834   [(parallel [(set (match_operand:SF 0 "" "")
4835               (mem:SF (post_inc:SI (reg:SI SP_REG))))
4836               (use (reg:PSI FPSCR_REG))
4837               (clobber (scratch:SI))])]
4838   "TARGET_SH1 && ! TARGET_SH5"
4839   "")
4840
4841 (define_insn "pop_fpul"
4842   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4843   "TARGET_SH2E && ! TARGET_SH5"
4844   "lds.l        @r15+,fpul"
4845   [(set_attr "type" "load")
4846    (set_attr "hit_stack" "yes")])
4847
4848 (define_expand "pop_4"
4849   [(parallel [(set (match_operand:DF 0 "" "")
4850                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
4851               (use (reg:PSI FPSCR_REG))
4852               (clobber (scratch:SI))])]
4853   "TARGET_SH1 && ! TARGET_SH5"
4854   "")
4855
4856 (define_expand "push_fpscr"
4857   [(const_int 0)]
4858   "TARGET_SH2E"
4859   "
4860 {
4861   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4862                                                  gen_rtx_PRE_DEC (Pmode,
4863                                                           stack_pointer_rtx)),
4864                                         get_fpscr_rtx ()));
4865   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4866   DONE;
4867 }")
4868
4869 (define_expand "pop_fpscr"
4870   [(const_int 0)]
4871   "TARGET_SH2E"
4872   "
4873 {
4874   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4875                                         gen_frame_mem (PSImode,
4876                                                  gen_rtx_POST_INC (Pmode,
4877                                                           stack_pointer_rtx))));
4878   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4879   DONE;
4880 }")
4881
4882 ;; These two patterns can happen as the result of optimization, when
4883 ;; comparisons get simplified to a move of zero or 1 into the T reg.
4884 ;; They don't disappear completely, because the T reg is a fixed hard reg.
4885
4886 (define_insn "clrt"
4887   [(set (reg:SI T_REG) (const_int 0))]
4888   "TARGET_SH1"
4889   "clrt")
4890
4891 (define_insn "sett"
4892   [(set (reg:SI T_REG) (const_int 1))]
4893   "TARGET_SH1"
4894   "sett")
4895
4896 ;; t/r must come after r/r, lest reload will try to reload stuff like
4897 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
4898 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
4899 (define_insn "movsi_i"
4900   [(set (match_operand:SI 0 "general_movdst_operand"
4901             "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
4902         (match_operand:SI 1 "general_movsrc_operand"
4903          "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
4904   "TARGET_SH1
4905    && ! TARGET_SH2E
4906    && ! TARGET_SH2A
4907    && (register_operand (operands[0], SImode)
4908        || register_operand (operands[1], SImode))"
4909   "@
4910         mov.l   %1,%0
4911         mov     %1,%0
4912         mov     %1,%0
4913         cmp/pl  %1
4914         mov.l   %1,%0
4915         sts     %1,%0
4916         sts     %1,%0
4917         movt    %0
4918         mov.l   %1,%0
4919         sts.l   %1,%0
4920         sts.l   %1,%0
4921         lds     %1,%0
4922         lds     %1,%0
4923         lds.l   %1,%0
4924         lds.l   %1,%0
4925         fake    %1,%0"
4926   [(set_attr "type" "pcload_si,move,movi8,mt_group,load_si,mac_gp,prget,arith,mac_mem,store,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
4927    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
4928
4929 ;; t/r must come after r/r, lest reload will try to reload stuff like
4930 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
4931 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
4932 ;; will require a reload.
4933 ;; ??? We can't include f/f because we need the proper FPSCR setting when
4934 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
4935 (define_insn "movsi_ie"
4936   [(set (match_operand:SI 0 "general_movdst_operand"
4937             "=r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
4938         (match_operand:SI 1 "general_movsrc_operand"
4939          "Q,r,I08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
4940   "(TARGET_SH2E || TARGET_SH2A)
4941    && (register_operand (operands[0], SImode)
4942        || register_operand (operands[1], SImode))"
4943   "@
4944         mov.l   %1,%0
4945         mov     %1,%0
4946         mov     %1,%0
4947         movi20  %1,%0
4948         cmp/pl  %1
4949         mov.l   %1,%0
4950         sts     %1,%0
4951         sts     %1,%0
4952         movt    %0
4953         mov.l   %1,%0
4954         sts.l   %1,%0
4955         sts.l   %1,%0
4956         lds     %1,%0
4957         lds     %1,%0
4958         lds.l   %1,%0
4959         lds.l   %1,%0
4960         lds.l   %1,%0
4961         sts.l   %1,%0
4962         fake    %1,%0
4963         lds     %1,%0
4964         sts     %1,%0
4965         fsts    fpul,%0
4966         flds    %1,fpul
4967         fmov    %1,%0
4968         ! move optimized away"
4969   [(set_attr "type" "pcload_si,move,movi8,move,*,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
4970    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
4971    (set_attr "length" "*,*,*,4,*,4,*,*,*,4,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
4972
4973 (define_insn "movsi_i_lowpart"
4974   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
4975         (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
4976    "TARGET_SH1
4977     && (register_operand (operands[0], SImode)
4978         || register_operand (operands[1], SImode))"
4979   "@
4980         mov.l   %1,%0
4981         mov     %1,%0
4982         mov     %1,%0
4983         mov.l   %1,%0
4984         sts     %1,%0
4985         sts     %1,%0
4986         movt    %0
4987         mov.l   %1,%0
4988         fake    %1,%0"
4989   [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
4990
4991 (define_insn_and_split "load_ra"
4992   [(set (match_operand:SI 0 "general_movdst_operand" "")
4993         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
4994   "TARGET_SH1"
4995   "#"
4996   "&& ! currently_expanding_to_rtl"
4997   [(set (match_dup 0) (match_dup 1))]
4998   "
4999 {
5000   if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
5001     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
5002 }")
5003
5004 ;; The '?'s in the following constraints may not reflect the time taken
5005 ;; to perform the move. They are there to discourage the use of floating-
5006 ;; point registers for storing integer values.
5007 (define_insn "*movsi_media"
5008   [(set (match_operand:SI 0 "general_movdst_operand"
5009                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
5010         (match_operand:SI 1 "general_movsrc_operand"
5011          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5012   "TARGET_SHMEDIA_FPU
5013    && (register_operand (operands[0], SImode)
5014        || sh_register_operand (operands[1], SImode)
5015        || GET_CODE (operands[1]) == TRUNCATE)"
5016   "@
5017         add.l   %1, r63, %0
5018         movi    %1, %0
5019         #
5020         ld%M1.l %m1, %0
5021         st%M0.l %m0, %N1
5022         fld%M1.s        %m1, %0
5023         fst%M0.s        %m0, %1
5024         fmov.ls %N1, %0
5025         fmov.sl %1, %0
5026         fmov.s  %1, %0
5027         ptabs   %1, %0
5028         gettr   %1, %0
5029         pt      %1, %0"
5030   [(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")
5031    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5032    (set (attr "highpart")
5033         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5034                (const_string "user")]
5035               (const_string "ignore")))])
5036
5037 (define_insn "*movsi_media_nofpu"
5038   [(set (match_operand:SI 0 "general_movdst_operand"
5039                 "=r,r,r,r,m,*b,r,*b")
5040         (match_operand:SI 1 "general_movsrc_operand"
5041          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5042   "TARGET_SHMEDIA
5043    && (register_operand (operands[0], SImode)
5044        || sh_register_operand (operands[1], SImode)
5045        || GET_CODE (operands[1]) == TRUNCATE)"
5046   "@
5047         add.l   %1, r63, %0
5048         movi    %1, %0
5049         #
5050         ld%M1.l %m1, %0
5051         st%M0.l %m0, %N1
5052         ptabs   %1, %0
5053         gettr   %1, %0
5054         pt      %1, %0"
5055   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5056    (set_attr "length" "4,4,8,4,4,4,4,12")
5057    (set (attr "highpart")
5058         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5059                (const_string "user")]
5060               (const_string "ignore")))])
5061
5062 (define_expand "movsi_const"
5063   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5064         (const:SI (sign_extend:SI
5065                    (truncate:HI
5066                     (ashiftrt:SI
5067                      (match_operand:DI 1 "immediate_operand" "s")
5068                      (const_int 16))))))
5069    (set (match_dup 0)
5070         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5071                 (const:SI
5072                   (zero_extend:SI
5073                    (truncate:HI (match_dup 1))))))]
5074   "TARGET_SHMEDIA && reload_completed
5075    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5076   "
5077 {
5078   if (GET_CODE (operands[1]) == LABEL_REF
5079       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5080     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5081   else if (GOTOFF_P (operands[1]))
5082     {
5083       rtx unspec = XEXP (operands[1], 0);
5084
5085       if (! UNSPEC_GOTOFF_P (unspec))
5086         {
5087           unspec = XEXP (unspec, 0);
5088           if (! UNSPEC_GOTOFF_P (unspec))
5089             abort ();
5090         }
5091       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5092           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5093         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5094     }
5095 }")
5096
5097 (define_expand "movsi_const_16bit"
5098   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5099         (const:SI (sign_extend:SI
5100                    (truncate:HI
5101                     (match_operand:DI 1 "immediate_operand" "s")))))]
5102   "TARGET_SHMEDIA && flag_pic && reload_completed
5103    && GET_CODE (operands[1]) == SYMBOL_REF"
5104   "")
5105
5106 (define_split
5107   [(set (match_operand:SI 0 "arith_reg_dest" "")
5108         (match_operand:SI 1 "immediate_operand" ""))]
5109   "TARGET_SHMEDIA && reload_completed
5110    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5111   [(const_int 0)]
5112   "
5113 {
5114   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5115
5116   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (operands[1]),
5117                                         REG_NOTES (insn));
5118
5119   DONE;
5120 }")
5121
5122 (define_split
5123   [(set (match_operand:SI 0 "register_operand" "")
5124         (match_operand:SI 1 "immediate_operand" ""))]
5125   "TARGET_SHMEDIA && reload_completed
5126    && ((GET_CODE (operands[1]) == CONST_INT
5127         && ! CONST_OK_FOR_I16 (INTVAL (operands[1])))
5128        || GET_CODE (operands[1]) == CONST_DOUBLE)"
5129   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5130
5131 (define_expand "movsi"
5132   [(set (match_operand:SI 0 "general_movdst_operand" "")
5133         (match_operand:SI 1 "general_movsrc_operand" ""))]
5134   ""
5135   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5136
5137 (define_expand "ic_invalidate_line"
5138   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5139                                 (match_dup 1)] UNSPEC_ICACHE)
5140               (clobber (scratch:SI))])]
5141   "TARGET_HARD_SH4 || TARGET_SH5"
5142   "
5143 {
5144   if (TARGET_SHMEDIA)
5145     {
5146       emit_insn (gen_ic_invalidate_line_media (operands[0]));
5147       DONE;
5148     }
5149   else if (TARGET_SHCOMPACT)
5150     {
5151       operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5152       operands[1] = force_reg (Pmode, operands[1]);
5153       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5154       DONE;
5155     }
5156   else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5157     {
5158       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5159       DONE;
5160     }
5161   operands[0] = force_reg (Pmode, operands[0]);
5162   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5163                                                                Pmode)));
5164 }")
5165
5166 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
5167 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5168 ;; the requirement *1*00 for associative address writes.  The alignment of
5169 ;; %0 implies that its least significant bit is cleared,
5170 ;; thus we clear the V bit of a matching entry if there is one.
5171 (define_insn "ic_invalidate_line_i"
5172   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5173                      (match_operand:SI 1 "register_operand" "r")]
5174                      UNSPEC_ICACHE)
5175    (clobber (match_scratch:SI 2 "=&r"))]
5176   "TARGET_HARD_SH4"
5177   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5178   [(set_attr "length" "8")
5179    (set_attr "type" "cwb")])
5180
5181 (define_insn "ic_invalidate_line_sh4a"
5182   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5183                     UNSPEC_ICACHE)]
5184   "TARGET_SH4A_ARCH || TARGET_SH4_300"
5185   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5186   [(set_attr "length" "16")
5187    (set_attr "type" "cwb")])
5188
5189 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5190 ;; an add in the code that calculates the address.
5191 (define_insn "ic_invalidate_line_media"
5192   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5193                     UNSPEC_ICACHE)]
5194   "TARGET_SHMEDIA"
5195   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
5196   [(set_attr "length" "16")
5197    (set_attr "type" "invalidate_line_media")])
5198
5199 (define_insn "ic_invalidate_line_compact"
5200   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5201                      (match_operand:SI 1 "register_operand" "r")]
5202                     UNSPEC_ICACHE)
5203    (clobber (reg:SI PR_REG))]
5204   "TARGET_SHCOMPACT"
5205   "jsr @%1%#"
5206   [(set_attr "type" "sfunc")
5207    (set_attr "needs_delay_slot" "yes")])
5208
5209 (define_expand "initialize_trampoline"
5210   [(match_operand:SI 0 "" "")
5211    (match_operand:SI 1 "" "")
5212    (match_operand:SI 2 "" "")]
5213   "TARGET_SHCOMPACT"
5214   "
5215 {
5216   rtx sfun, tramp;
5217
5218   tramp = force_reg (Pmode, operands[0]);
5219   sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5220                                             SFUNC_STATIC));
5221   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5222   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5223
5224   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5225   DONE;
5226 }")
5227
5228 (define_insn "initialize_trampoline_compact"
5229   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5230                      (match_operand:SI 1 "register_operand" "r")
5231                      (reg:SI R2_REG) (reg:SI R3_REG)]
5232                     UNSPEC_INIT_TRAMP)
5233
5234    (clobber (reg:SI PR_REG))]
5235   "TARGET_SHCOMPACT"
5236   "jsr @%1%#"
5237   [(set_attr "type" "sfunc")
5238    (set_attr "needs_delay_slot" "yes")])
5239
5240 (define_insn "movqi_i"
5241   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m,r,r,l")
5242         (match_operand:QI 1 "general_movsrc_operand"  "r,i,m,r,t,l,r"))]
5243   "TARGET_SH1
5244    && (arith_reg_operand (operands[0], QImode)
5245        || arith_reg_operand (operands[1], QImode))"
5246   "@
5247         mov     %1,%0
5248         mov     %1,%0
5249         mov.b   %1,%0
5250         mov.b   %1,%0
5251         movt    %0
5252         sts     %1,%0
5253         lds     %1,%0"
5254  [(set_attr "type" "move,movi8,load,store,arith,prget,prset")])
5255
5256 (define_insn "*movqi_media"
5257   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5258         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5259   "TARGET_SHMEDIA
5260    && (arith_reg_operand (operands[0], QImode)
5261        || extend_reg_or_0_operand (operands[1], QImode))"
5262   "@
5263         add.l   %1, r63, %0
5264         movi    %1, %0
5265         ld%M1.ub        %m1, %0
5266         st%M0.b %m0, %N1"
5267   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5268    (set (attr "highpart")
5269         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5270                (const_string "user")]
5271               (const_string "ignore")))])
5272
5273 (define_expand "movqi"
5274   [(set (match_operand:QI 0 "general_operand" "")
5275         (match_operand:QI 1 "general_operand"  ""))]
5276   ""
5277   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5278
5279 (define_expand "reload_inqi"
5280   [(set (match_operand:SI 2 "" "=&r")
5281         (match_operand:QI 1 "inqhi_operand" ""))
5282    (set (match_operand:QI 0 "arith_reg_operand" "=r")
5283         (truncate:QI (match_dup 3)))]
5284   "TARGET_SHMEDIA"
5285   "
5286 {
5287   rtx inner = XEXP (operands[1], 0);
5288   int regno = REGNO (inner);
5289
5290   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5291   operands[1] = gen_rtx_REG (SImode, regno);
5292   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5293 }")
5294
5295 /* When storing r0, we have to avoid reg+reg addressing.  */
5296 (define_insn "movhi_i"
5297   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
5298         (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5299   "TARGET_SH1
5300    && (arith_reg_operand (operands[0], HImode)
5301        || arith_reg_operand (operands[1], HImode))
5302    && (GET_CODE (operands[0]) != MEM
5303        || GET_CODE (XEXP (operands[0], 0)) != PLUS
5304        || GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != REG
5305        || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5306   "@
5307         mov.w   %1,%0
5308         mov     %1,%0
5309         mov.w   %1,%0
5310         movt    %0
5311         mov.w   %1,%0
5312         sts     %1,%0
5313         lds     %1,%0
5314         fake    %1,%0"
5315   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5316
5317 (define_insn "*movhi_media"
5318   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
5319         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5320   "TARGET_SHMEDIA
5321    && (arith_reg_operand (operands[0], HImode)
5322        || arith_reg_or_0_operand (operands[1], HImode))"
5323   "@
5324         add.l   %1, r63, %0
5325         movi    %1, %0
5326         #
5327         ld%M1.w %m1, %0
5328         st%M0.w %m0, %N1"
5329   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5330    (set (attr "highpart")
5331         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5332                (const_string "user")]
5333               (const_string "ignore")))])
5334
5335 (define_split
5336   [(set (match_operand:HI 0 "register_operand" "")
5337         (match_operand:HI 1 "immediate_operand" ""))]
5338   "TARGET_SHMEDIA && reload_completed
5339    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
5340   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5341
5342 (define_expand "movhi"
5343   [(set (match_operand:HI 0 "general_movdst_operand" "")
5344         (match_operand:HI 1 "general_movsrc_operand"  ""))]
5345   ""
5346   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5347
5348 (define_expand "reload_inhi"
5349   [(set (match_operand:SI 2 "" "=&r")
5350         (match_operand:HI 1 "inqhi_operand" ""))
5351    (set (match_operand:HI 0 "arith_reg_operand" "=r")
5352         (truncate:HI (match_dup 3)))]
5353   "TARGET_SHMEDIA"
5354   "
5355 {
5356   rtx inner = XEXP (operands[1], 0);
5357   int regno = REGNO (inner);
5358
5359   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5360   operands[1] = gen_rtx_REG (SImode, regno);
5361   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5362 }")
5363
5364 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5365 ;; compiled with -m2 -ml -O3 -funroll-loops
5366 (define_insn "*movdi_i"
5367   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5368         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5369   "TARGET_SH1
5370    && (arith_reg_operand (operands[0], DImode)
5371        || arith_reg_operand (operands[1], DImode))"
5372   "* return output_movedouble (insn, operands, DImode);"
5373   [(set_attr "length" "4")
5374    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5375
5376 ;; If the output is a register and the input is memory or a register, we have
5377 ;; to be careful and see which word needs to be loaded first.
5378
5379 (define_split
5380   [(set (match_operand:DI 0 "general_movdst_operand" "")
5381         (match_operand:DI 1 "general_movsrc_operand" ""))]
5382   "TARGET_SH1 && reload_completed"
5383   [(set (match_dup 2) (match_dup 3))
5384    (set (match_dup 4) (match_dup 5))]
5385   "
5386 {
5387   int regno;
5388
5389   if ((GET_CODE (operands[0]) == MEM
5390        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5391       || (GET_CODE (operands[1]) == MEM
5392           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5393     FAIL;
5394
5395   switch (GET_CODE (operands[0]))
5396     {
5397     case REG:
5398       regno = REGNO (operands[0]);
5399       break;
5400     case SUBREG:
5401       regno = subreg_regno (operands[0]);
5402       break;
5403     case MEM:
5404       regno = -1;
5405       break;
5406     default:
5407       gcc_unreachable ();
5408     }
5409
5410   if (regno == -1
5411       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5412     {
5413       operands[2] = operand_subword (operands[0], 0, 0, DImode);
5414       operands[3] = operand_subword (operands[1], 0, 0, DImode);
5415       operands[4] = operand_subword (operands[0], 1, 0, DImode);
5416       operands[5] = operand_subword (operands[1], 1, 0, DImode);
5417     }
5418   else
5419     {
5420       operands[2] = operand_subword (operands[0], 1, 0, DImode);
5421       operands[3] = operand_subword (operands[1], 1, 0, DImode);
5422       operands[4] = operand_subword (operands[0], 0, 0, DImode);
5423       operands[5] = operand_subword (operands[1], 0, 0, DImode);
5424     }
5425
5426   if (operands[2] == 0 || operands[3] == 0
5427       || operands[4] == 0 || operands[5] == 0)
5428     FAIL;
5429 }")
5430
5431 ;; The '?'s in the following constraints may not reflect the time taken
5432 ;; to perform the move. They are there to discourage the use of floating-
5433 ;; point registers for storing integer values.
5434 (define_insn "*movdi_media"
5435   [(set (match_operand:DI 0 "general_movdst_operand"
5436                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5437         (match_operand:DI 1 "general_movsrc_operand"
5438          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5439   "TARGET_SHMEDIA_FPU
5440    && (register_operand (operands[0], DImode)
5441        || sh_register_operand (operands[1], DImode))"
5442   "@
5443         add     %1, r63, %0
5444         movi    %1, %0
5445         #
5446         ld%M1.q %m1, %0
5447         st%M0.q %m0, %N1
5448         fld%M1.d        %m1, %0
5449         fst%M0.d        %m0, %1
5450         fmov.qd %N1, %0
5451         fmov.dq %1, %0
5452         fmov.d  %1, %0
5453         ptabs   %1, %0
5454         gettr   %1, %0
5455         pt      %1, %0"
5456   [(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")
5457    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5458
5459 (define_insn "*movdi_media_nofpu"
5460   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5461         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5462   "TARGET_SHMEDIA
5463    && (register_operand (operands[0], DImode)
5464        || sh_register_operand (operands[1], DImode))"
5465   "@
5466         add     %1, r63, %0
5467         movi    %1, %0
5468         #
5469         ld%M1.q %m1, %0
5470         st%M0.q %m0, %N1
5471         ptabs   %1, %0
5472         gettr   %1, %0
5473         pt      %1, %0"
5474   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5475    (set_attr "length" "4,4,16,4,4,4,4,*")])
5476
5477 (define_insn "*movdi_media_I16"
5478   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5479         (match_operand:DI 1 "const_int_operand" "I16"))]
5480   "TARGET_SHMEDIA && reload_completed"
5481   "movi %1, %0"
5482   [(set_attr "type" "arith_media")
5483    (set_attr "length" "4")])
5484
5485 (define_split
5486   [(set (match_operand:DI 0 "arith_reg_dest" "")
5487         (match_operand:DI 1 "immediate_operand" ""))]
5488   "TARGET_SHMEDIA && reload_completed
5489    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5490   [(set (match_dup 0) (match_dup 1))]
5491   "
5492 {
5493   rtx insn;
5494
5495   if (TARGET_SHMEDIA64)
5496     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5497   else
5498     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5499
5500   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (operands[1]),
5501                                         REG_NOTES (insn));
5502
5503   DONE;
5504 }")
5505
5506 (define_expand "movdi_const"
5507   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5508         (const:DI (sign_extend:DI
5509                    (truncate:HI
5510                     (ashiftrt:DI
5511                      (match_operand:DI 1 "immediate_operand" "s")
5512                      (const_int 48))))))
5513    (set (match_dup 0)
5514         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5515                 (const:DI
5516                  (zero_extend:DI
5517                   (truncate:HI
5518                    (ashiftrt:SI
5519                     (match_dup 1)
5520                     (const_int 32)))))))
5521    (set (match_dup 0)
5522         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5523                 (const:DI
5524                  (zero_extend:DI
5525                   (truncate:HI
5526                    (ashiftrt:SI
5527                     (match_dup 1)
5528                     (const_int 16)))))))
5529    (set (match_dup 0)
5530         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5531                 (const:DI
5532                  (zero_extend:DI
5533                   (truncate:HI
5534                    (match_dup 1))))))]
5535   "TARGET_SHMEDIA64 && reload_completed
5536    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5537   "
5538 {
5539   sh_mark_label (operands[1], 4);
5540 }")
5541
5542 (define_expand "movdi_const_32bit"
5543   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5544         (const:DI (sign_extend:DI
5545                    (truncate:HI
5546                     (ashiftrt:DI
5547                      (match_operand:DI 1 "immediate_operand" "s")
5548                      (const_int 16))))))
5549    (set (match_dup 0)
5550         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5551                 (const:DI
5552                  (zero_extend:DI
5553                   (truncate:HI
5554                    (match_dup 1))))))]
5555   "TARGET_SHMEDIA32 && reload_completed
5556    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5557   "
5558 {
5559   sh_mark_label (operands[1], 2);
5560 }")
5561
5562 (define_expand "movdi_const_16bit"
5563   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5564         (const:DI (sign_extend:DI
5565                    (truncate:HI
5566                     (match_operand:DI 1 "immediate_operand" "s")))))]
5567   "TARGET_SHMEDIA && flag_pic && reload_completed
5568    && GET_CODE (operands[1]) == SYMBOL_REF"
5569   "")
5570
5571 (define_split
5572   [(set (match_operand:DI 0 "ext_dest_operand" "")
5573         (match_operand:DI 1 "immediate_operand" ""))]
5574   "TARGET_SHMEDIA && reload_completed
5575    && GET_CODE (operands[1]) == CONST_INT
5576    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
5577   [(set (match_dup 0) (match_dup 2))
5578    (match_dup 1)]
5579   "
5580 {
5581   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5582   unsigned HOST_WIDE_INT low = val;
5583   unsigned HOST_WIDE_INT high = val;
5584   unsigned HOST_WIDE_INT sign;
5585   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5586
5587   /* Zero-extend the 16 least-significant bits.  */
5588   low &= 0xffff;
5589
5590   /* Arithmetic shift right the word by 16 bits.  */
5591   high >>= 16;
5592   if (GET_CODE (operands[0]) == SUBREG
5593       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5594     {
5595       high &= 0xffff;
5596       high ^= 0x8000;
5597       high -= 0x8000;
5598     }
5599   else
5600     {
5601       sign = 1;
5602       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5603       high ^= sign;
5604       high -= sign;
5605     }
5606   do
5607     {
5608       /* If we can't generate the constant with a two-insn movi / shori
5609          sequence, try some other strategies.  */
5610       if (! CONST_OK_FOR_I16 (high))
5611         {
5612           /* Try constant load / left shift.  We know VAL != 0.  */
5613           val2 = val ^ (val-1);
5614           if (val2 > 0x1ffff)
5615             {
5616               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5617
5618               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5619                   || (! CONST_OK_FOR_I16 (high >> 16)
5620                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5621                 {
5622                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5623                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
5624                                                    GEN_INT (trailing_zeroes));
5625                   break;
5626                 }
5627             }
5628           /* Try constant load / right shift.  */
5629           val2 = (val >> 15) + 1;
5630           if (val2 == (val2 & -val2))
5631             {
5632               int shift = 49 - exact_log2 (val2);
5633
5634               val2 = trunc_int_for_mode (val << shift, DImode);
5635               if (CONST_OK_FOR_I16 (val2))
5636                 {
5637                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5638                                                    GEN_INT (shift));
5639                   break;
5640                 }
5641             }
5642           /* Try mperm.w .  */
5643           val2 = val & 0xffff;
5644           if ((val >> 16 & 0xffff) == val2
5645               && (val >> 32 & 0xffff) == val2
5646               && (val >> 48 & 0xffff) == val2)
5647             {
5648               val2 = (HOST_WIDE_INT) val >> 48;
5649               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5650               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5651               break;
5652             }
5653           /* Try movi / mshflo.l  */
5654           val2 = (HOST_WIDE_INT) val >> 32;
5655           if (val2 == ((unsigned HOST_WIDE_INT)
5656                         trunc_int_for_mode (val, SImode)))
5657             {
5658               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5659                                              operands[0]);
5660               break;
5661             }
5662           /* Try movi / mshflo.l w/ r63.  */
5663           val2 = val + ((HOST_WIDE_INT) -1 << 32);
5664           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5665             {
5666               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5667                                              const0_rtx);
5668               break;
5669             }
5670         }
5671       val2 = high;
5672       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5673     }
5674   while (0);
5675   operands[2] = GEN_INT (val2);
5676 }")
5677
5678 (define_split
5679   [(set (match_operand:DI 0 "ext_dest_operand" "")
5680         (match_operand:DI 1 "immediate_operand" ""))]
5681   "TARGET_SHMEDIA && reload_completed
5682    && GET_CODE (operands[1]) == CONST_DOUBLE"
5683   [(set (match_dup 0) (match_dup 2))
5684   (set (match_dup 0)
5685        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5686   "
5687 {
5688   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5689   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5690   unsigned HOST_WIDE_INT val = low;
5691   unsigned HOST_WIDE_INT sign;
5692
5693   /* Zero-extend the 16 least-significant bits.  */
5694   val &= 0xffff;
5695   operands[1] = GEN_INT (val);
5696
5697   /* Arithmetic shift right the double-word by 16 bits.  */
5698   low >>= 16;
5699   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5700   high >>= 16;
5701   sign = 1;
5702   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5703   high ^= sign;
5704   high -= sign;
5705
5706   /* This will only be true if high is a sign-extension of low, i.e.,
5707      it must be either 0 or (unsigned)-1, and be zero iff the
5708      most-significant bit of low is set.  */
5709   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5710     operands[2] = GEN_INT (low);
5711   else
5712     operands[2] = immed_double_const (low, high, DImode);
5713 }")
5714
5715 (define_insn "shori_media"
5716   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5717         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5718                            (const_int 16))
5719                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5720   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5721   "@
5722         shori   %u2, %0
5723         #"
5724   [(set_attr "type" "arith_media,*")])
5725
5726 (define_insn "*shori_media_si"
5727   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5728         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5729                            (const_int 16))
5730                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
5731   "TARGET_SHMEDIA"
5732   "shori        %u2, %0")
5733
5734 (define_expand "movdi"
5735   [(set (match_operand:DI 0 "general_movdst_operand" "")
5736         (match_operand:DI 1 "general_movsrc_operand" ""))]
5737   ""
5738   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5739
5740 (define_insn "movdf_media"
5741   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5742         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5743   "TARGET_SHMEDIA_FPU
5744    && (register_operand (operands[0], DFmode)
5745        || sh_register_operand (operands[1], DFmode))"
5746   "@
5747         fmov.d  %1, %0
5748         fmov.qd %N1, %0
5749         fmov.dq %1, %0
5750         add     %1, r63, %0
5751         #
5752         fld%M1.d        %m1, %0
5753         fst%M0.d        %m0, %1
5754         ld%M1.q %m1, %0
5755         st%M0.q %m0, %N1"
5756   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5757
5758 (define_insn "movdf_media_nofpu"
5759   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5760         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5761   "TARGET_SHMEDIA
5762    && (register_operand (operands[0], DFmode)
5763        || sh_register_operand (operands[1], DFmode))"
5764   "@
5765         add     %1, r63, %0
5766         #
5767         ld%M1.q %m1, %0
5768         st%M0.q %m0, %N1"
5769   [(set_attr "type" "arith_media,*,load_media,store_media")])
5770
5771 (define_split
5772   [(set (match_operand:DF 0 "arith_reg_dest" "")
5773         (match_operand:DF 1 "immediate_operand" ""))]
5774   "TARGET_SHMEDIA && reload_completed"
5775   [(set (match_dup 3) (match_dup 2))]
5776   "
5777 {
5778   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5779   long values[2];
5780   REAL_VALUE_TYPE value;
5781
5782   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5783   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5784
5785   if (HOST_BITS_PER_WIDE_INT >= 64)
5786     operands[2] = immed_double_const ((unsigned long) values[endian]
5787                                       | ((HOST_WIDE_INT) values[1 - endian]
5788                                          << 32), 0, DImode);
5789   else
5790     {
5791       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5792       operands[2] = immed_double_const (values[endian], values[1 - endian],
5793                                         DImode);
5794     }
5795
5796   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5797 }")
5798
5799 ;; ??? This should be a define expand.
5800
5801 (define_insn "movdf_k"
5802   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5803         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5804   "TARGET_SH1
5805    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5806        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5807        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
5808        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
5809    && (arith_reg_operand (operands[0], DFmode)
5810        || arith_reg_operand (operands[1], DFmode))"
5811   "* return output_movedouble (insn, operands, DFmode);"
5812   [(set_attr "length" "4")
5813    (set_attr "type" "move,pcload,load,store")])
5814
5815 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5816 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
5817 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
5818 ;; the d/m/c/X alternative, which is split later into single-precision
5819 ;; instructions.  And when not optimizing, no splits are done before fixing
5820 ;; up pcloads, so we need usable length information for that.
5821 (define_insn "movdf_i4"
5822   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5823         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
5824    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
5825    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
5826   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5827    && (arith_reg_operand (operands[0], DFmode)
5828        || arith_reg_operand (operands[1], DFmode))"
5829   "@
5830         fmov    %1,%0
5831         #
5832         #
5833         fmov.d  %1,%0
5834         fmov.d  %1,%0
5835         #
5836         #
5837         #
5838         #
5839         #"
5840   [(set_attr_alternative "length"
5841      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
5842       (const_int 4)
5843       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5844       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5845       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5846       (const_int 4)
5847       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
5848       ;; We can't use 4-byte push/pop on SHcompact, so we have to
5849       ;; increment or decrement r15 explicitly.
5850       (if_then_else
5851        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5852        (const_int 10) (const_int 8))
5853       (if_then_else
5854        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5855        (const_int 10) (const_int 8))])
5856    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
5857    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
5858    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
5859                                            (const_string "double")
5860                                            (const_string "none")))])
5861
5862 ;; Moving DFmode between fp/general registers through memory
5863 ;; (the top of the stack) is faster than moving through fpul even for
5864 ;; little endian.  Because the type of an instruction is important for its
5865 ;; scheduling,  it is beneficial to split these operations, rather than
5866 ;; emitting them in one single chunk, even if this will expose a stack
5867 ;; use that will prevent scheduling of other stack accesses beyond this
5868 ;; instruction.
5869 (define_split
5870   [(set (match_operand:DF 0 "register_operand" "")
5871         (match_operand:DF 1 "register_operand" ""))
5872    (use (match_operand:PSI 2 "fpscr_operand" ""))
5873    (clobber (match_scratch:SI 3 "=X"))]
5874   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
5875    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
5876   [(const_int 0)]
5877   "
5878 {
5879   rtx insn, tos;
5880
5881   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
5882     {
5883       emit_move_insn (stack_pointer_rtx,
5884                       plus_constant (stack_pointer_rtx, -8));
5885       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5886     }
5887   else
5888     tos = gen_tmp_stack_mem (DFmode,
5889                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
5890   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
5891   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
5892     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5893   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5894     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5895   else
5896     tos = gen_tmp_stack_mem (DFmode,
5897                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
5898   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
5899   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5900     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
5901   else
5902     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5903   DONE;
5904 }")
5905
5906 ;; local-alloc sometimes allocates scratch registers even when not required,
5907 ;; so we must be prepared to handle these.
5908
5909 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
5910 (define_split
5911   [(set (match_operand:DF 0 "general_movdst_operand" "")
5912         (match_operand:DF 1 "general_movsrc_operand"  ""))
5913    (use (match_operand:PSI 2 "fpscr_operand" ""))
5914    (clobber (match_scratch:SI 3 ""))]
5915   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5916    && reload_completed
5917    && true_regnum (operands[0]) < 16
5918    && true_regnum (operands[1]) < 16"
5919   [(set (match_dup 0) (match_dup 1))]
5920   "
5921 {
5922   /* If this was a reg <-> mem operation with base + index reg addressing,
5923      we have to handle this in a special way.  */
5924   rtx mem = operands[0];
5925   int store_p = 1;
5926   if (! memory_operand (mem, DFmode))
5927     {
5928       mem = operands[1];
5929       store_p = 0;
5930     }
5931   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
5932     mem = SUBREG_REG (mem);
5933   if (GET_CODE (mem) == MEM)
5934     {
5935       rtx addr = XEXP (mem, 0);
5936       if (GET_CODE (addr) == PLUS
5937           && GET_CODE (XEXP (addr, 0)) == REG
5938           && GET_CODE (XEXP (addr, 1)) == REG)
5939         {
5940           int offset;
5941           rtx reg0 = gen_rtx_REG (Pmode, 0);
5942           rtx regop = operands[store_p], word0 ,word1;
5943
5944           if (GET_CODE (regop) == SUBREG)
5945             alter_subreg (&regop);
5946           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
5947             offset = 2;
5948           else
5949             offset = 4;
5950           mem = copy_rtx (mem);
5951           PUT_MODE (mem, SImode);
5952           word0 = gen_rtx_SUBREG (SImode, regop, 0);
5953           alter_subreg (&word0);
5954           word1 = gen_rtx_SUBREG (SImode, regop, 4);
5955           alter_subreg (&word1);
5956           if (store_p || ! refers_to_regno_p (REGNO (word0),
5957                                               REGNO (word0) + 1, addr, 0))
5958             {
5959               emit_insn (store_p
5960                          ? gen_movsi_ie (mem, word0)
5961                          : gen_movsi_ie (word0, mem));
5962               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5963               mem = copy_rtx (mem);
5964               emit_insn (store_p
5965                          ? gen_movsi_ie (mem, word1)
5966                          : gen_movsi_ie (word1, mem));
5967               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5968             }
5969           else
5970             {
5971               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5972               emit_insn (gen_movsi_ie (word1, mem));
5973               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5974               mem = copy_rtx (mem);
5975               emit_insn (gen_movsi_ie (word0, mem));
5976             }
5977           DONE;
5978         }
5979     }
5980 }")
5981
5982 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
5983 (define_split
5984   [(set (match_operand:DF 0 "register_operand" "")
5985         (match_operand:DF 1 "memory_operand"  ""))
5986    (use (match_operand:PSI 2 "fpscr_operand" ""))
5987    (clobber (reg:SI R0_REG))]
5988   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
5989   [(parallel [(set (match_dup 0) (match_dup 1))
5990               (use (match_dup 2))
5991               (clobber (scratch:SI))])]
5992   "")
5993
5994 (define_expand "reload_indf__frn"
5995   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
5996                    (match_operand:DF 1 "immediate_operand" "FQ"))
5997               (use (reg:PSI FPSCR_REG))
5998               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5999   "TARGET_SH1"
6000   "")
6001
6002 (define_expand "reload_outdf__RnFRm"
6003   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
6004                    (match_operand:DF 1 "register_operand" "af,r"))
6005               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
6006   "TARGET_SH1"
6007   "")
6008
6009 ;; Simplify no-op moves.
6010 (define_split
6011   [(set (match_operand:SF 0 "register_operand" "")
6012         (match_operand:SF 1 "register_operand" ""))
6013    (use (match_operand:PSI 2 "fpscr_operand" ""))
6014    (clobber (match_scratch:SI 3 ""))]
6015   "TARGET_SH2E && reload_completed
6016    && true_regnum (operands[0]) == true_regnum (operands[1])"
6017   [(set (match_dup 0) (match_dup 0))]
6018   "")
6019
6020 ;; fmovd substitute post-reload splits
6021 (define_split
6022   [(set (match_operand:DF 0 "register_operand" "")
6023         (match_operand:DF 1 "register_operand" ""))
6024    (use (match_operand:PSI 2 "fpscr_operand" ""))
6025    (clobber (match_scratch:SI 3 ""))]
6026   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
6027    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6028    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6029   [(const_int 0)]
6030   "
6031 {
6032   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6033   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6034                            gen_rtx_REG (SFmode, src), operands[2]));
6035   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6036                            gen_rtx_REG (SFmode, src + 1), operands[2]));
6037   DONE;
6038 }")
6039
6040 (define_split
6041   [(set (match_operand:DF 0 "register_operand" "")
6042         (mem:DF (match_operand:SI 1 "register_operand" "")))
6043    (use (match_operand:PSI 2 "fpscr_operand" ""))
6044    (clobber (match_scratch:SI 3 ""))]
6045   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6046    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6047    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6048   [(const_int 0)]
6049   "
6050 {
6051   int regno = true_regnum (operands[0]);
6052   rtx insn;
6053   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6054   rtx mem2
6055     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6056   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6057                                            regno + !! TARGET_LITTLE_ENDIAN),
6058                                   mem2, operands[2]));
6059   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
6060   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6061                                                regno + ! TARGET_LITTLE_ENDIAN),
6062                                   change_address (mem, SFmode, NULL_RTX),
6063                                   operands[2]));
6064   DONE;
6065 }")
6066
6067 (define_split
6068   [(set (match_operand:DF 0 "register_operand" "")
6069         (match_operand:DF 1 "memory_operand" ""))
6070    (use (match_operand:PSI 2 "fpscr_operand" ""))
6071    (clobber (match_scratch:SI 3 ""))]
6072   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6073    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6074   [(const_int 0)]
6075   "
6076 {
6077   int regno = true_regnum (operands[0]);
6078   rtx addr, insn, adjust = NULL_RTX;
6079   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6080   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
6081   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
6082
6083   operands[1] = copy_rtx (mem2);
6084   addr = XEXP (mem2, 0);
6085   if (GET_CODE (addr) != POST_INC)
6086     {
6087       /* If we have to modify the stack pointer, the value that we have
6088          read with post-increment might be modified by an interrupt,
6089          so write it back.  */
6090       if (REGNO (addr) == STACK_POINTER_REGNUM)
6091         adjust = gen_push_e (reg0);
6092       else
6093         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
6094       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6095     }
6096   addr = XEXP (addr, 0);
6097   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6098   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6099   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6100   if (adjust)
6101     emit_insn (adjust);
6102   else
6103     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6104   DONE;
6105 }")
6106
6107 (define_split
6108   [(set (match_operand:DF 0 "memory_operand" "")
6109         (match_operand:DF 1 "register_operand" ""))
6110    (use (match_operand:PSI 2 "fpscr_operand" ""))
6111    (clobber (match_scratch:SI 3 ""))]
6112   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6113    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6114   [(const_int 0)]
6115   "
6116 {
6117   int regno = true_regnum (operands[1]);
6118   rtx insn, addr, adjust = NULL_RTX;
6119
6120   operands[0] = copy_rtx (operands[0]);
6121   PUT_MODE (operands[0], SFmode);
6122   insn = emit_insn (gen_movsf_ie (operands[0],
6123                                   gen_rtx_REG (SFmode,
6124                                            regno + ! TARGET_LITTLE_ENDIAN),
6125                                   operands[2]));
6126   operands[0] = copy_rtx (operands[0]);
6127   addr = XEXP (operands[0], 0);
6128   if (GET_CODE (addr) != PRE_DEC)
6129     {
6130       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
6131       emit_insn_before (adjust, insn);
6132       XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6133     }
6134   addr = XEXP (addr, 0);
6135   if (! adjust)
6136     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6137   insn = emit_insn (gen_movsf_ie (operands[0],
6138                                   gen_rtx_REG (SFmode,
6139                                            regno + !! TARGET_LITTLE_ENDIAN),
6140                                   operands[2]));
6141   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6142   DONE;
6143 }")
6144
6145 ;; If the output is a register and the input is memory or a register, we have
6146 ;; to be careful and see which word needs to be loaded first.
6147
6148 (define_split
6149   [(set (match_operand:DF 0 "general_movdst_operand" "")
6150         (match_operand:DF 1 "general_movsrc_operand" ""))]
6151   "TARGET_SH1 && reload_completed"
6152   [(set (match_dup 2) (match_dup 3))
6153    (set (match_dup 4) (match_dup 5))]
6154   "
6155 {
6156   int regno;
6157
6158   if ((GET_CODE (operands[0]) == MEM
6159        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6160       || (GET_CODE (operands[1]) == MEM
6161           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6162     FAIL;
6163
6164   switch (GET_CODE (operands[0]))
6165     {
6166     case REG:
6167       regno = REGNO (operands[0]);
6168       break;
6169     case SUBREG:
6170       regno = subreg_regno (operands[0]);
6171       break;
6172     case MEM:
6173       regno = -1;
6174       break;
6175     default:
6176       gcc_unreachable ();
6177     }
6178
6179   if (regno == -1
6180       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6181     {
6182       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6183       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6184       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6185       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6186     }
6187   else
6188     {
6189       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6190       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6191       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6192       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6193     }
6194
6195   if (operands[2] == 0 || operands[3] == 0
6196       || operands[4] == 0 || operands[5] == 0)
6197     FAIL;
6198 }")
6199
6200 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6201 ;; used only once, let combine add in the index again.
6202
6203 (define_split
6204   [(set (match_operand:SI 0 "register_operand" "")
6205         (match_operand:SI 1 "" ""))
6206    (clobber (match_operand 2 "register_operand" ""))]
6207   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6208    && ALLOW_INDEXED_ADDRESS"
6209   [(use (reg:SI R0_REG))]
6210   "
6211 {
6212   rtx addr, reg, const_int;
6213
6214   if (GET_CODE (operands[1]) != MEM)
6215     FAIL;
6216   addr = XEXP (operands[1], 0);
6217   if (GET_CODE (addr) != PLUS)
6218     FAIL;
6219   reg = XEXP (addr, 0);
6220   const_int = XEXP (addr, 1);
6221   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6222          && GET_CODE (const_int) == CONST_INT))
6223     FAIL;
6224   emit_move_insn (operands[2], const_int);
6225   emit_move_insn (operands[0],
6226                   change_address (operands[1], VOIDmode,
6227                                   gen_rtx_PLUS (SImode, reg, operands[2])));
6228   DONE;
6229 }")
6230
6231 (define_split
6232   [(set (match_operand:SI 1 "" "")
6233         (match_operand:SI 0 "register_operand" ""))
6234    (clobber (match_operand 2 "register_operand" ""))]
6235   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6236    && ALLOW_INDEXED_ADDRESS"
6237   [(use (reg:SI R0_REG))]
6238   "
6239 {
6240   rtx addr, reg, const_int;
6241
6242   if (GET_CODE (operands[1]) != MEM)
6243     FAIL;
6244   addr = XEXP (operands[1], 0);
6245   if (GET_CODE (addr) != PLUS)
6246     FAIL;
6247   reg = XEXP (addr, 0);
6248   const_int = XEXP (addr, 1);
6249   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6250          && GET_CODE (const_int) == CONST_INT))
6251     FAIL;
6252   emit_move_insn (operands[2], const_int);
6253   emit_move_insn (change_address (operands[1], VOIDmode,
6254                                   gen_rtx_PLUS (SImode, reg, operands[2])),
6255                   operands[0]);
6256   DONE;
6257 }")
6258
6259 (define_expand "movdf"
6260   [(set (match_operand:DF 0 "general_movdst_operand" "")
6261         (match_operand:DF 1 "general_movsrc_operand" ""))]
6262   ""
6263   "
6264 {
6265   if (prepare_move_operands (operands, DFmode)) DONE;
6266   if (TARGET_SHMEDIA)
6267     {
6268       if (TARGET_SHMEDIA_FPU)
6269         emit_insn (gen_movdf_media (operands[0], operands[1]));
6270       else
6271         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6272       DONE;
6273     }
6274   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6275     {
6276       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6277       DONE;
6278     }
6279 }")
6280
6281 ;;This is incompatible with the way gcc uses subregs.
6282 ;;(define_insn "movv2sf_i"
6283 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6284 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6285 ;;  "TARGET_SHMEDIA_FPU
6286 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
6287 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
6288 ;;  "@
6289 ;;      #
6290 ;;      fld%M1.p        %m1, %0
6291 ;;      fst%M0.p        %m0, %1"
6292 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
6293
6294 (define_insn_and_split "movv2sf_i"
6295   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6296         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6297   "TARGET_SHMEDIA_FPU"
6298   "#"
6299   "TARGET_SHMEDIA_FPU && reload_completed"
6300   [(set (match_dup 0) (match_dup 1))]
6301   "
6302 {
6303   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6304   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6305 }")
6306
6307 (define_expand "movv2sf"
6308   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6309         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6310   "TARGET_SHMEDIA_FPU"
6311   "
6312 {
6313   if (prepare_move_operands (operands, V2SFmode))
6314     DONE;
6315 }")
6316
6317 (define_expand "addv2sf3"
6318   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6319    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6320    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6321   "TARGET_SHMEDIA_FPU"
6322   "
6323 {
6324   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6325   DONE;
6326 }")
6327
6328 (define_expand "subv2sf3"
6329   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6330    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6331    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6332   "TARGET_SHMEDIA_FPU"
6333   "
6334 {
6335   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6336   DONE;
6337 }")
6338
6339 (define_expand "mulv2sf3"
6340   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6341    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6342    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6343   "TARGET_SHMEDIA_FPU"
6344   "
6345 {
6346   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6347   DONE;
6348 }")
6349
6350 (define_expand "divv2sf3"
6351   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6352    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6353    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6354   "TARGET_SHMEDIA_FPU"
6355   "
6356 {
6357   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6358   DONE;
6359 }")
6360
6361 (define_insn_and_split "*movv4sf_i"
6362   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6363         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6364   "TARGET_SHMEDIA_FPU"
6365   "#"
6366   "&& reload_completed"
6367   [(const_int 0)]
6368   "
6369 {
6370   int i;
6371
6372   for (i = 0; i < 4/2; i++)
6373     {
6374       rtx x, y;
6375
6376       if (GET_CODE (operands[0]) == MEM)
6377         x = adjust_address (operands[0], V2SFmode,
6378                             i * GET_MODE_SIZE (V2SFmode));
6379       else
6380         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6381
6382       if (GET_CODE (operands[1]) == MEM)
6383         y = adjust_address (operands[1], V2SFmode,
6384                             i * GET_MODE_SIZE (V2SFmode));
6385       else
6386         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6387
6388       emit_insn (gen_movv2sf_i (x, y));
6389     }
6390
6391   DONE;
6392 }"
6393   [(set_attr "length" "8")])
6394
6395 (define_expand "movv4sf"
6396   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6397         (match_operand:V4SF 1 "general_operand" ""))]
6398   "TARGET_SHMEDIA_FPU"
6399   "
6400 {
6401   if (prepare_move_operands (operands, V4SFmode))
6402     DONE;
6403 }")
6404
6405 (define_insn_and_split "*movv16sf_i"
6406   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6407         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6408   "TARGET_SHMEDIA_FPU"
6409   "#"
6410   "&& reload_completed"
6411   [(const_int 0)]
6412   "
6413 {
6414   int i;
6415
6416   for (i = 0; i < 16/2; i++)
6417     {
6418       rtx x,y;
6419
6420       if (GET_CODE (operands[0]) == MEM)
6421         x = adjust_address (operands[0], V2SFmode,
6422                             i * GET_MODE_SIZE (V2SFmode));
6423       else
6424         {
6425           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6426           alter_subreg (&x);
6427         }
6428
6429       if (GET_CODE (operands[1]) == MEM)
6430         y = adjust_address (operands[1], V2SFmode,
6431                             i * GET_MODE_SIZE (V2SFmode));
6432       else
6433         {
6434           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6435           alter_subreg (&y);
6436         }
6437
6438       emit_insn (gen_movv2sf_i (x, y));
6439     }
6440
6441   DONE;
6442 }"
6443   [(set_attr "length" "32")])
6444
6445 (define_expand "movv16sf"
6446   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6447         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6448   "TARGET_SHMEDIA_FPU"
6449   "
6450 {
6451   if (prepare_move_operands (operands, V16SFmode))
6452     DONE;
6453 }")
6454
6455 (define_insn "movsf_media"
6456   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6457         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6458   "TARGET_SHMEDIA_FPU
6459    && (register_operand (operands[0], SFmode)
6460        || sh_register_operand (operands[1], SFmode))"
6461   "@
6462         fmov.s  %1, %0
6463         fmov.ls %N1, %0
6464         fmov.sl %1, %0
6465         add.l   %1, r63, %0
6466         #
6467         fld%M1.s        %m1, %0
6468         fst%M0.s        %m0, %1
6469         ld%M1.l %m1, %0
6470         st%M0.l %m0, %N1"
6471   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6472    (set (attr "highpart")
6473         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6474                (const_string "user")]
6475               (const_string "ignore")))])
6476
6477 (define_insn "movsf_media_nofpu"
6478   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6479         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6480   "TARGET_SHMEDIA
6481    && (register_operand (operands[0], SFmode)
6482        || sh_register_operand (operands[1], SFmode))"
6483   "@
6484         add.l   %1, r63, %0
6485         #
6486         ld%M1.l %m1, %0
6487         st%M0.l %m0, %N1"
6488   [(set_attr "type" "arith_media,*,load_media,store_media")
6489    (set (attr "highpart")
6490         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6491                (const_string "user")]
6492               (const_string "ignore")))])
6493
6494 (define_split
6495   [(set (match_operand:SF 0 "arith_reg_dest" "")
6496         (match_operand:SF 1 "immediate_operand" ""))]
6497   "TARGET_SHMEDIA && reload_completed
6498    && ! FP_REGISTER_P (true_regnum (operands[0]))"
6499   [(set (match_dup 3) (match_dup 2))]
6500   "
6501 {
6502   long values;
6503   REAL_VALUE_TYPE value;
6504
6505   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6506   REAL_VALUE_TO_TARGET_SINGLE (value, values);
6507   operands[2] = GEN_INT (values);
6508
6509   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6510 }")
6511
6512 (define_insn "movsf_i"
6513   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6514         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
6515   "TARGET_SH1
6516    && (! TARGET_SH2E
6517        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6518        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
6519        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
6520    && (arith_reg_operand (operands[0], SFmode)
6521        || arith_reg_operand (operands[1], SFmode))"
6522   "@
6523         mov     %1,%0
6524         mov     #0,%0
6525         mov.l   %1,%0
6526         mov.l   %1,%0
6527         mov.l   %1,%0
6528         lds     %1,%0
6529         sts     %1,%0"
6530   [(set_attr "type" "move,move,pcload,load,store,move,move")])
6531
6532 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6533 ;; update_flow_info would not know where to put REG_EQUAL notes
6534 ;; when the destination changes mode.
6535 (define_insn "movsf_ie"
6536   [(set (match_operand:SF 0 "general_movdst_operand"
6537          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6538         (match_operand:SF 1 "general_movsrc_operand"
6539           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6540    (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"))
6541    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6542
6543   "TARGET_SH2E
6544    && (arith_reg_operand (operands[0], SFmode)
6545        || arith_reg_operand (operands[1], SFmode)
6546        || arith_reg_operand (operands[3], SImode)
6547        || (fpul_operand (operands[0], SFmode)
6548            && memory_operand (operands[1], SFmode)
6549            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6550        || (fpul_operand (operands[1], SFmode)
6551            && memory_operand (operands[0], SFmode)
6552            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6553   "@
6554         fmov    %1,%0
6555         mov     %1,%0
6556         fldi0   %0
6557         fldi1   %0
6558         #
6559         fmov.s  %1,%0
6560         fmov.s  %1,%0
6561         mov.l   %1,%0
6562         mov.l   %1,%0
6563         mov.l   %1,%0
6564         fsts    fpul,%0
6565         flds    %1,fpul
6566         lds.l   %1,%0
6567         #
6568         sts     %1,%0
6569         lds     %1,%0
6570         sts.l   %1,%0
6571         lds.l   %1,%0
6572         ! move optimized away"
6573   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6574    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6575    (set_attr "length" "*,*,*,*,4,4,4,*,*,*,2,2,2,4,2,2,2,2,0")
6576    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6577                                            (const_string "single")
6578                                            (const_string "none")))])
6579
6580 (define_split
6581   [(set (match_operand:SF 0 "register_operand" "")
6582         (match_operand:SF 1 "register_operand" ""))
6583    (use (match_operand:PSI 2 "fpscr_operand" ""))
6584    (clobber (reg:SI FPUL_REG))]
6585   "TARGET_SH1"
6586   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6587               (use (match_dup 2))
6588               (clobber (scratch:SI))])
6589    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6590               (use (match_dup 2))
6591               (clobber (scratch:SI))])]
6592   "")
6593
6594 (define_expand "movsf"
6595   [(set (match_operand:SF 0 "general_movdst_operand" "")
6596         (match_operand:SF 1 "general_movsrc_operand" ""))]
6597   ""
6598   "
6599 {
6600   if (prepare_move_operands (operands, SFmode))
6601     DONE;
6602   if (TARGET_SHMEDIA)
6603     {
6604       if (TARGET_SHMEDIA_FPU)
6605         emit_insn (gen_movsf_media (operands[0], operands[1]));
6606       else
6607         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6608       DONE;
6609     }
6610   if (TARGET_SH2E)
6611     {
6612       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6613       DONE;
6614     }
6615 }")
6616
6617 (define_insn "mov_nop"
6618   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6619   "TARGET_SH2E"
6620   ""
6621   [(set_attr "length" "0")
6622    (set_attr "type" "nil")])
6623
6624 (define_expand "reload_insf__frn"
6625   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6626                    (match_operand:SF 1 "immediate_operand" "FQ"))
6627               (use (reg:PSI FPSCR_REG))
6628               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6629   "TARGET_SH1"
6630   "")
6631
6632 (define_expand "reload_insi__i_fpul"
6633   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6634                    (match_operand:SI 1 "immediate_operand" "i"))
6635               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6636   "TARGET_SH1"
6637   "")
6638
6639 (define_expand "ptabs"
6640   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6641   "TARGET_SHMEDIA"
6642   "
6643 {
6644   if (!TARGET_PT_FIXED)
6645     {
6646       rtx eq = operands[1];
6647
6648       /* ??? For canonical RTL we really should remove any CONST from EQ
6649          before wrapping it in the AND, and finally wrap the EQ into a
6650          const if is constant.  However, for reload we must expose the
6651          input register or symbolic constant, and we can't have
6652          different insn structures outside of the operands for different
6653          alternatives of the same pattern.  */
6654       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6655                        GEN_INT (3));
6656       operands[1]
6657         = (gen_rtx_IF_THEN_ELSE
6658             (PDImode,
6659              eq,
6660              gen_rtx_MEM (PDImode, operands[1]),
6661              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6662                             PDImode, operands[1])));
6663     }
6664 }")
6665
6666 ;; expanded by ptabs expander.
6667 (define_insn "*extendsipdi_media"
6668   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6669         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6670                                                           "r,Csy")
6671                                       (const_int 3))
6672                               (const_int 3))
6673                           (mem:PDI (match_dup 1))
6674                           (sign_extend:PDI (match_dup 1))))]
6675   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6676   "@
6677         ptabs   %1, %0
6678         pt      %1, %0"
6679   [(set_attr "type"   "ptabs_media,pt_media")
6680    (set_attr "length" "4,*")])
6681
6682 (define_insn "*truncdipdi_media"
6683   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6684         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6685                                                           "r,Csy")
6686                                       (const_int 3))
6687                               (const_int 3))
6688                           (mem:PDI (match_dup 1))
6689                           (truncate:PDI (match_dup 1))))]
6690   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6691   "@
6692         ptabs   %1, %0
6693         pt      %1, %0"
6694   [(set_attr "type"   "ptabs_media,pt_media")
6695    (set_attr "length" "4,*")])
6696
6697 (define_insn "*movsi_y"
6698   [(set (match_operand:SI 0 "register_operand" "=y,y")
6699         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
6700    (clobber (match_scratch:SI 2 "=&z,r"))]
6701   "TARGET_SH2E
6702    && (reload_in_progress || reload_completed)"
6703   "#"
6704   [(set_attr "length" "4")
6705    (set_attr "type" "pcload,move")])
6706
6707 (define_split
6708   [(set (match_operand:SI 0 "register_operand" "")
6709         (match_operand:SI 1 "immediate_operand" ""))
6710    (clobber (match_operand:SI 2 "register_operand" ""))]
6711   "TARGET_SH1"
6712   [(set (match_dup 2) (match_dup 1))
6713    (set (match_dup 0) (match_dup 2))]
6714   "")
6715
6716 (define_split
6717   [(set (match_operand:SI 0 "register_operand" "")
6718         (match_operand:SI 1 "memory_operand" ""))
6719    (clobber (reg:SI R0_REG))]
6720   "TARGET_SH1"
6721   [(set (match_dup 0) (match_dup 1))]
6722   "")
6723 \f
6724 ;; ------------------------------------------------------------------------
6725 ;; Define the real conditional branch instructions.
6726 ;; ------------------------------------------------------------------------
6727
6728 (define_insn "branch_true"
6729   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6730                            (label_ref (match_operand 0 "" ""))
6731                            (pc)))]
6732   "TARGET_SH1"
6733   "* return output_branch (1, insn, operands);"
6734   [(set_attr "type" "cbranch")])
6735
6736 (define_insn "branch_false"
6737   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6738                            (label_ref (match_operand 0 "" ""))
6739                            (pc)))]
6740   "TARGET_SH1"
6741   "* return output_branch (0, insn, operands);"
6742   [(set_attr "type" "cbranch")])
6743
6744 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
6745 ;; which destination is too far away.
6746 ;; The const_int_operand is distinct for each branch target; it avoids
6747 ;; unwanted matches with redundant_insn.
6748 (define_insn "block_branch_redirect"
6749   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
6750   "TARGET_SH1"
6751   ""
6752   [(set_attr "length" "0")])
6753
6754 ;; This one has the additional purpose to record a possible scratch register
6755 ;; for the following branch.
6756 ;; ??? Unfortunately, just setting the scratch register is not good enough,
6757 ;; because the insn then might be deemed dead and deleted.  And we can't
6758 ;; make the use in the jump insn explicit because that would disable
6759 ;; delay slot scheduling from the target.
6760 (define_insn "indirect_jump_scratch"
6761   [(set (match_operand:SI 0 "register_operand" "=r")
6762         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
6763    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
6764   "TARGET_SH1"
6765   ""
6766   [(set_attr "length" "0")])
6767
6768 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
6769 ;; being pulled into the delay slot of a condbranch that has been made to
6770 ;; jump around the unconditional jump because it was out of range.
6771 (define_insn "stuff_delay_slot"
6772   [(set (pc)
6773         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
6774    (set (reg:SI T_REG) (match_operand:SI 1 "const_int_operand" ""))]
6775   "TARGET_SH1"
6776   ""
6777   [(set_attr "length" "0")
6778    (set_attr "cond_delay_slot" "yes")])
6779 \f
6780 ;; Conditional branch insns
6781
6782 (define_expand "beq_media"
6783   [(set (pc)
6784         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
6785                           (match_operand:DI 2 "arith_operand" "r,I06"))
6786                       (match_operand 0 "" "")
6787                       (pc)))]
6788   "TARGET_SHMEDIA"
6789   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6790
6791 (define_insn "*beq_media_i"
6792   [(set (pc)
6793         (if_then_else (match_operator 3 "equality_comparison_operator"
6794                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
6795                          (match_operand:DI 2 "arith_operand" "r,I06")])
6796                       (match_operand 0 "target_operand" "b,b")
6797                       (pc)))]
6798   "TARGET_SHMEDIA"
6799   "@
6800         b%o3%'  %1, %2, %0%>
6801         b%o3i%' %1, %2, %0%>"
6802   [(set_attr "type" "cbranch_media")])
6803
6804 (define_insn "*beq_media_i32"
6805   [(set (pc)
6806         (if_then_else (match_operator 3 "equality_comparison_operator"
6807                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
6808                          (match_operand:SI 2 "arith_operand" "r,I06")])
6809                       (match_operand 0 "target_operand" "b,b")
6810                       (pc)))]
6811   "TARGET_SHMEDIA"
6812   "@
6813         b%o3%'  %1, %2, %0%>
6814         b%o3i%' %1, %2, %0%>"
6815   [(set_attr "type" "cbranch_media")])
6816
6817 (define_expand "bne_media"
6818   [(set (pc)
6819         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
6820                           (match_operand:DI 2 "arith_operand" "r,I06"))
6821                       (match_operand 0 "" "")
6822                       (pc)))]
6823   "TARGET_SHMEDIA"
6824   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6825
6826 (define_expand "bgt_media"
6827   [(set (pc)
6828         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "")
6829                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6830                       (match_operand 0 "" "")
6831                       (pc)))]
6832   "TARGET_SHMEDIA"
6833   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6834
6835 (define_expand "bge_media"
6836   [(set (pc)
6837         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "")
6838                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6839                       (match_operand 0 "" "")
6840                       (pc)))]
6841   "TARGET_SHMEDIA"
6842   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6843
6844 (define_expand "bgtu_media"
6845   [(set (pc)
6846         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6847                            (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6848                       (match_operand 0 "" "")
6849                       (pc)))]
6850   "TARGET_SHMEDIA"
6851   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6852
6853 (define_expand "bgeu_media"
6854   [(set (pc)
6855         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6856                            (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6857                       (match_operand 0 "" "")
6858                       (pc)))]
6859   "TARGET_SHMEDIA"
6860   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6861
6862 (define_insn "*bgt_media_i"
6863   [(set (pc)
6864         (if_then_else (match_operator 3 "greater_comparison_operator"
6865                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6866                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6867                       (match_operand 0 "target_operand" "b")
6868                       (pc)))]
6869   "TARGET_SHMEDIA"
6870   "b%o3%'       %N1, %N2, %0%>"
6871   [(set_attr "type" "cbranch_media")])
6872
6873 (define_insn "*bgt_media_i32"
6874   [(set (pc)
6875         (if_then_else (match_operator 3 "greater_comparison_operator"
6876                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6877                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6878                       (match_operand 0 "target_operand" "b")
6879                       (pc)))]
6880   "TARGET_SHMEDIA"
6881   "b%o3%'       %N1, %N2, %0%>"
6882   [(set_attr "type" "cbranch_media")])
6883
6884 ;; These are only needed to make invert_jump() happy - otherwise, jump
6885 ;; optimization will be silently disabled.
6886 (define_insn "*blt_media_i"
6887   [(set (pc)
6888         (if_then_else (match_operator 3 "less_comparison_operator"
6889                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6890                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6891                       (match_operand 0 "target_operand" "b")
6892                       (pc)))]
6893   "TARGET_SHMEDIA"
6894   "b%o3%'       %N2, %N1, %0%>"
6895   [(set_attr "type" "cbranch_media")])
6896
6897 (define_insn "*blt_media_i32"
6898   [(set (pc)
6899         (if_then_else (match_operator 3 "less_comparison_operator"
6900                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6901                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6902                       (match_operand 0 "target_operand" "b")
6903                       (pc)))]
6904   "TARGET_SHMEDIA"
6905   "b%o3%'       %N2, %N1, %0%>"
6906   [(set_attr "type" "cbranch_media")])
6907
6908 (define_expand "beq"
6909   [(set (pc)
6910         (if_then_else (ne (reg:SI T_REG) (const_int 0))
6911                       (label_ref (match_operand 0 "" ""))
6912                       (pc)))]
6913   ""
6914   "
6915 {
6916   if (TARGET_SHMEDIA)
6917     {
6918       enum machine_mode mode = GET_MODE (sh_compare_op0);
6919
6920       if (mode != DImode && mode != SImode)
6921         {
6922           rtx tmp = gen_reg_rtx (DImode);
6923
6924           emit_insn (gen_seq (tmp));
6925           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6926           DONE;
6927         }
6928
6929       sh_compare_op0 = force_reg (mode, sh_compare_op0);
6930       if (CONSTANT_P (sh_compare_op1)
6931           && (GET_CODE (sh_compare_op1) != CONST_INT
6932               || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
6933         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6934       emit_jump_insn (gen_beq_media (operands[0],
6935                                      sh_compare_op0, sh_compare_op1));
6936       DONE;
6937     }
6938
6939   from_compare (operands, EQ);
6940 }")
6941
6942 (define_expand "bne"
6943   [(set (pc)
6944         (if_then_else (eq (reg:SI T_REG) (const_int 0))
6945                       (label_ref (match_operand 0 "" ""))
6946                       (pc)))]
6947   ""
6948   "
6949 {
6950   if (TARGET_SHMEDIA)
6951     {
6952       enum machine_mode mode = GET_MODE (sh_compare_op0);
6953
6954       if (mode != DImode && mode != SImode)
6955         {
6956           rtx tmp = gen_reg_rtx (DImode);
6957
6958           emit_insn (gen_seq (tmp));
6959           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
6960           DONE;
6961         }
6962
6963       sh_compare_op0 = force_reg (mode, sh_compare_op0);
6964       if (CONSTANT_P (sh_compare_op1)
6965           && (GET_CODE (sh_compare_op1) != CONST_INT
6966               || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
6967         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6968       emit_jump_insn (gen_bne_media (operands[0],
6969                                      sh_compare_op0, sh_compare_op1));
6970       DONE;
6971     }
6972
6973   from_compare (operands, EQ);
6974 }")
6975
6976 (define_expand "bgt"
6977   [(set (pc)
6978         (if_then_else (ne (reg:SI T_REG) (const_int 0))
6979                       (label_ref (match_operand 0 "" ""))
6980                       (pc)))]
6981   ""
6982   "
6983 {
6984   if (TARGET_SHMEDIA)
6985     {
6986       enum machine_mode mode = GET_MODE (sh_compare_op0);
6987
6988       if (mode != DImode && mode != SImode)
6989         {
6990           rtx tmp = gen_reg_rtx (DImode);
6991
6992           emit_insn (gen_sgt (tmp));
6993           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6994           DONE;
6995         }
6996
6997       if (sh_compare_op0 != const0_rtx)
6998         sh_compare_op0 = force_reg (mode, sh_compare_op0);
6999       if (sh_compare_op1 != const0_rtx)
7000         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7001       emit_jump_insn (gen_bgt_media (operands[0],
7002                                      sh_compare_op0, sh_compare_op1));
7003       DONE;
7004     }
7005
7006   from_compare (operands, GT);
7007 }")
7008
7009 (define_expand "blt"
7010   [(set (pc)
7011         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7012                       (label_ref (match_operand 0 "" ""))
7013                       (pc)))]
7014   ""
7015   "
7016 {
7017   if (TARGET_SHMEDIA)
7018     {
7019       enum machine_mode mode = GET_MODE (sh_compare_op0);
7020
7021       if (mode != DImode && mode != SImode)
7022         {
7023           rtx tmp = gen_reg_rtx (DImode);
7024
7025           emit_insn (gen_slt (tmp));
7026           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7027           DONE;
7028         }
7029
7030       if (sh_compare_op0 != const0_rtx)
7031         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7032       if (sh_compare_op1 != const0_rtx)
7033         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7034       emit_jump_insn (gen_bgt_media (operands[0],
7035                                      sh_compare_op1, sh_compare_op0));
7036       DONE;
7037     }
7038
7039   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7040     {
7041       rtx tmp = sh_compare_op0;
7042       sh_compare_op0 = sh_compare_op1;
7043       sh_compare_op1 = tmp;
7044       emit_insn (gen_bgt (operands[0]));
7045       DONE;
7046     }
7047   from_compare (operands, GE);
7048 }")
7049
7050 (define_expand "ble"
7051   [(set (pc)
7052         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7053                       (label_ref (match_operand 0 "" ""))
7054                       (pc)))]
7055   ""
7056   "
7057 {
7058   if (TARGET_SHMEDIA)
7059     {
7060       enum machine_mode mode = GET_MODE (sh_compare_op0);
7061
7062       if (mode != DImode && mode != SImode)
7063         {
7064           rtx tmp = gen_reg_rtx (DImode);
7065
7066           emit_insn (gen_sle (tmp));
7067           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7068           DONE;
7069         }
7070
7071       if (sh_compare_op0 != const0_rtx)
7072         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7073       if (sh_compare_op1 != const0_rtx)
7074         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7075       emit_jump_insn (gen_bge_media (operands[0],
7076                                      sh_compare_op1, sh_compare_op0));
7077       DONE;
7078     }
7079
7080   if (TARGET_SH2E
7081       && TARGET_IEEE
7082       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7083     {
7084       rtx tmp = sh_compare_op0;
7085       sh_compare_op0 = sh_compare_op1;
7086       sh_compare_op1 = tmp;
7087       emit_insn (gen_bge (operands[0]));
7088       DONE;
7089     }
7090   from_compare (operands, GT);
7091 }")
7092
7093 (define_expand "bge"
7094   [(set (pc)
7095         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7096                       (label_ref (match_operand 0 "" ""))
7097                       (pc)))]
7098   ""
7099   "
7100 {
7101   if (TARGET_SHMEDIA)
7102     {
7103       enum machine_mode mode = GET_MODE (sh_compare_op0);
7104
7105       if (mode != DImode && mode != SImode)
7106         {
7107           rtx tmp = gen_reg_rtx (DImode);
7108
7109           emit_insn (gen_sge (tmp));
7110           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7111           DONE;
7112         }
7113
7114       if (sh_compare_op0 != const0_rtx)
7115         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7116       if (sh_compare_op1 != const0_rtx)
7117         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7118       emit_jump_insn (gen_bge_media (operands[0],
7119                                      sh_compare_op0, sh_compare_op1));
7120       DONE;
7121     }
7122
7123   if (TARGET_SH2E
7124       && ! TARGET_IEEE
7125       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7126     {
7127       rtx tmp = sh_compare_op0;
7128       sh_compare_op0 = sh_compare_op1;
7129       sh_compare_op1 = tmp;
7130       emit_insn (gen_ble (operands[0]));
7131       DONE;
7132     }
7133   from_compare (operands, GE);
7134 }")
7135
7136 (define_expand "bgtu"
7137   [(set (pc)
7138         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7139                       (label_ref (match_operand 0 "" ""))
7140                       (pc)))]
7141   ""
7142   "
7143 {
7144   if (TARGET_SHMEDIA)
7145     {
7146       enum machine_mode mode = GET_MODE (sh_compare_op0);
7147
7148       if (sh_compare_op0 != const0_rtx)
7149         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7150       if (sh_compare_op1 != const0_rtx)
7151         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7152       emit_jump_insn (gen_bgtu_media (operands[0],
7153                                       sh_compare_op0, sh_compare_op1));
7154       DONE;
7155     }
7156
7157   from_compare (operands, GTU);
7158 }")
7159
7160 (define_expand "bltu"
7161   [(set (pc)
7162         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7163                       (label_ref (match_operand 0 "" ""))
7164                       (pc)))]
7165   ""
7166   "
7167 {
7168   if (TARGET_SHMEDIA)
7169     {
7170       enum machine_mode mode = GET_MODE (sh_compare_op0);
7171
7172       if (sh_compare_op0 != const0_rtx)
7173         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7174       if (sh_compare_op1 != const0_rtx)
7175         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7176       emit_jump_insn (gen_bgtu_media (operands[0],
7177                                       sh_compare_op1, sh_compare_op0));
7178       DONE;
7179     }
7180
7181   from_compare (operands, GEU);
7182 }")
7183
7184 (define_expand "bgeu"
7185   [(set (pc)
7186         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7187                       (label_ref (match_operand 0 "" ""))
7188                       (pc)))]
7189   ""
7190   "
7191 {
7192   if (TARGET_SHMEDIA)
7193     {
7194       enum machine_mode mode = GET_MODE (sh_compare_op0);
7195
7196       if (sh_compare_op0 != const0_rtx)
7197         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7198       if (sh_compare_op1 != const0_rtx)
7199         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7200       emit_jump_insn (gen_bgeu_media (operands[0],
7201                                       sh_compare_op0, sh_compare_op1));
7202       DONE;
7203     }
7204
7205   from_compare (operands, GEU);
7206 }")
7207
7208 (define_expand "bleu"
7209   [(set (pc)
7210         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7211                       (label_ref (match_operand 0 "" ""))
7212                       (pc)))]
7213   ""
7214   "
7215 {
7216   if (TARGET_SHMEDIA)
7217     {
7218       enum machine_mode mode = GET_MODE (sh_compare_op0);
7219
7220       if (sh_compare_op0 != const0_rtx)
7221         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7222       if (sh_compare_op1 != const0_rtx)
7223         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7224       emit_jump_insn (gen_bgeu_media (operands[0],
7225                                       sh_compare_op1, sh_compare_op0));
7226       DONE;
7227     }
7228
7229   from_compare (operands, GTU);
7230 }")
7231
7232 (define_expand "bunordered"
7233   [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3)))
7234    (set (pc)
7235         (if_then_else (ne (match_dup 1) (const_int 0))
7236                       (match_operand 0 "" "")
7237                       (pc)))]
7238   "TARGET_SHMEDIA"
7239   "
7240 {
7241   operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);
7242   operands[1] = gen_reg_rtx (SImode);
7243   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7244   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7245 }")
7246
7247 ;; combiner splitter for test-and-branch on single bit in register.  This
7248 ;; is endian dependent because the non-paradoxical subreg looks different
7249 ;; on big endian.
7250 (define_split
7251   [(set (pc)
7252         (if_then_else
7253           (match_operator 3 "equality_comparison_operator"
7254             [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7255                                                       "extend_reg_operand" "")
7256                                                     0)
7257                                          (const_int 1)
7258                                          (match_operand 2
7259                                           "const_int_operand" "")) 0)
7260              (const_int 0)])
7261           (match_operand 0 "target_operand" "")
7262           (pc)))
7263    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7264   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7265   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7266    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7267
7268   "
7269 {
7270   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7271   operands[6] = (GET_CODE (operands[3]) == EQ
7272                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7273                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7274 }")
7275 \f
7276 ;; ------------------------------------------------------------------------
7277 ;; Jump and linkage insns
7278 ;; ------------------------------------------------------------------------
7279
7280 (define_insn "jump_compact"
7281   [(set (pc)
7282         (label_ref (match_operand 0 "" "")))]
7283   "TARGET_SH1"
7284   "*
7285 {
7286   /* The length is 16 if the delay slot is unfilled.  */
7287   if (get_attr_length(insn) > 4)
7288     return output_far_jump(insn, operands[0]);
7289   else
7290     return   \"bra      %l0%#\";
7291 }"
7292   [(set_attr "type" "jump")
7293    (set_attr "needs_delay_slot" "yes")])
7294
7295 ;; ??? It would be much saner to explicitly use the scratch register
7296 ;; in the jump insn, and have indirect_jump_scratch only set it,
7297 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7298 ;; from the target then, as it uses simplejump_p.
7299 ;;(define_insn "jump_compact_far"
7300 ;;  [(set (pc)
7301 ;;      (label_ref (match_operand 0 "" "")))
7302 ;;   (use (match_operand 1 "register_operand" "r")]
7303 ;;  "TARGET_SH1"
7304 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
7305 ;;  [(set_attr "type" "jump")
7306 ;;   (set_attr "needs_delay_slot" "yes")])
7307
7308 (define_insn "jump_media"
7309   [(set (pc)
7310         (match_operand 0 "target_operand" "b"))]
7311   "TARGET_SHMEDIA"
7312   "blink        %0, r63%>"
7313   [(set_attr "type" "jump_media")])
7314
7315 (define_expand "jump"
7316   [(set (pc)
7317         (label_ref (match_operand 0 "" "")))]
7318   ""
7319   "
7320 {
7321   if (TARGET_SH1)
7322     emit_jump_insn (gen_jump_compact (operands[0]));
7323   else if (TARGET_SHMEDIA)
7324     {
7325       if (reload_in_progress || reload_completed)
7326         FAIL;
7327       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7328                                                          operands[0])));
7329     }
7330   DONE;
7331 }")
7332
7333 (define_insn "force_mode_for_call"
7334   [(use (reg:PSI FPSCR_REG))]
7335   "TARGET_SHCOMPACT"
7336   ""
7337   [(set_attr "length" "0")
7338    (set (attr "fp_mode")
7339         (if_then_else (eq_attr "fpu_single" "yes")
7340                       (const_string "single") (const_string "double")))])
7341
7342 (define_insn "calli"
7343   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7344          (match_operand 1 "" ""))
7345    (use (reg:PSI FPSCR_REG))
7346    (clobber (reg:SI PR_REG))]
7347   "TARGET_SH1"
7348   "jsr  @%0%#"
7349   [(set_attr "type" "call")
7350    (set (attr "fp_mode")
7351         (if_then_else (eq_attr "fpu_single" "yes")
7352                       (const_string "single") (const_string "double")))
7353    (set_attr "needs_delay_slot" "yes")
7354    (set_attr "fp_set" "unknown")])
7355
7356 ;; This is a pc-rel call, using bsrf, for use with PIC.
7357
7358 (define_insn "calli_pcrel"
7359   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7360          (match_operand 1 "" ""))
7361    (use (reg:PSI FPSCR_REG))
7362    (use (reg:SI PIC_REG))
7363    (use (match_operand 2 "" ""))
7364    (clobber (reg:SI PR_REG))]
7365   "TARGET_SH2"
7366   "bsrf %0\\n%O2:%#"
7367   [(set_attr "type" "call")
7368    (set (attr "fp_mode")
7369         (if_then_else (eq_attr "fpu_single" "yes")
7370                       (const_string "single") (const_string "double")))
7371    (set_attr "needs_delay_slot" "yes")
7372    (set_attr "fp_set" "unknown")])
7373
7374 (define_insn_and_split "call_pcrel"
7375   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7376          (match_operand 1 "" ""))
7377    (use (reg:PSI FPSCR_REG))
7378    (use (reg:SI PIC_REG))
7379    (clobber (reg:SI PR_REG))
7380    (clobber (match_scratch:SI 2 "=r"))]
7381   "TARGET_SH2"
7382   "#"
7383   "reload_completed"
7384   [(const_int 0)]
7385   "
7386 {
7387   rtx lab = PATTERN (gen_call_site ());
7388
7389   if (SYMBOL_REF_LOCAL_P (operands[0]))
7390     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7391   else
7392     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7393   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7394   DONE;
7395 }"
7396   [(set_attr "type" "call")
7397    (set (attr "fp_mode")
7398         (if_then_else (eq_attr "fpu_single" "yes")
7399                       (const_string "single") (const_string "double")))
7400    (set_attr "needs_delay_slot" "yes")
7401    (set_attr "fp_set" "unknown")])
7402
7403 (define_insn "call_compact"
7404   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7405          (match_operand 1 "" ""))
7406    (match_operand 2 "immediate_operand" "n")
7407    (use (reg:SI R0_REG))
7408    (use (reg:SI R1_REG))
7409    (use (reg:PSI FPSCR_REG))
7410    (clobber (reg:SI PR_REG))]
7411   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7412   "jsr  @%0%#"
7413   [(set_attr "type" "call")
7414    (set (attr "fp_mode")
7415         (if_then_else (eq_attr "fpu_single" "yes")
7416                       (const_string "single") (const_string "double")))
7417    (set_attr "needs_delay_slot" "yes")])
7418
7419 (define_insn "call_compact_rettramp"
7420   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7421          (match_operand 1 "" ""))
7422    (match_operand 2 "immediate_operand" "n")
7423    (use (reg:SI R0_REG))
7424    (use (reg:SI R1_REG))
7425    (use (reg:PSI FPSCR_REG))
7426    (clobber (reg:SI R10_REG))
7427    (clobber (reg:SI PR_REG))]
7428   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7429   "jsr  @%0%#"
7430   [(set_attr "type" "call")
7431    (set (attr "fp_mode")
7432         (if_then_else (eq_attr "fpu_single" "yes")
7433                       (const_string "single") (const_string "double")))
7434    (set_attr "needs_delay_slot" "yes")])
7435
7436 (define_insn "call_media"
7437   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7438          (match_operand 1 "" ""))
7439    (clobber (reg:DI PR_MEDIA_REG))]
7440   "TARGET_SHMEDIA"
7441   "blink        %0, r18"
7442   [(set_attr "type" "jump_media")])
7443
7444 (define_insn "call_valuei"
7445   [(set (match_operand 0 "" "=rf")
7446         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7447               (match_operand 2 "" "")))
7448    (use (reg:PSI FPSCR_REG))
7449    (clobber (reg:SI PR_REG))]
7450   "TARGET_SH1"
7451   "jsr  @%1%#"
7452   [(set_attr "type" "call")
7453    (set (attr "fp_mode")
7454         (if_then_else (eq_attr "fpu_single" "yes")
7455                       (const_string "single") (const_string "double")))
7456    (set_attr "needs_delay_slot" "yes")
7457    (set_attr "fp_set" "unknown")])
7458
7459 (define_insn "call_valuei_pcrel"
7460   [(set (match_operand 0 "" "=rf")
7461         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7462               (match_operand 2 "" "")))
7463    (use (reg:PSI FPSCR_REG))
7464    (use (reg:SI PIC_REG))
7465    (use (match_operand 3 "" ""))
7466    (clobber (reg:SI PR_REG))]
7467   "TARGET_SH2"
7468   "bsrf %1\\n%O3:%#"
7469   [(set_attr "type" "call")
7470    (set (attr "fp_mode")
7471         (if_then_else (eq_attr "fpu_single" "yes")
7472                       (const_string "single") (const_string "double")))
7473    (set_attr "needs_delay_slot" "yes")
7474    (set_attr "fp_set" "unknown")])
7475
7476 (define_insn_and_split "call_value_pcrel"
7477   [(set (match_operand 0 "" "=rf")
7478         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7479               (match_operand 2 "" "")))
7480    (use (reg:PSI FPSCR_REG))
7481    (use (reg:SI PIC_REG))
7482    (clobber (reg:SI PR_REG))
7483    (clobber (match_scratch:SI 3 "=r"))]
7484   "TARGET_SH2"
7485   "#"
7486   "reload_completed"
7487   [(const_int 0)]
7488   "
7489 {
7490   rtx lab = PATTERN (gen_call_site ());
7491
7492   if (SYMBOL_REF_LOCAL_P (operands[1]))
7493     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7494   else
7495     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7496   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7497                                          operands[2], copy_rtx (lab)));
7498   DONE;
7499 }"
7500   [(set_attr "type" "call")
7501    (set (attr "fp_mode")
7502         (if_then_else (eq_attr "fpu_single" "yes")
7503                       (const_string "single") (const_string "double")))
7504    (set_attr "needs_delay_slot" "yes")
7505    (set_attr "fp_set" "unknown")])
7506
7507 (define_insn "call_value_compact"
7508   [(set (match_operand 0 "" "=rf")
7509         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7510               (match_operand 2 "" "")))
7511    (match_operand 3 "immediate_operand" "n")
7512    (use (reg:SI R0_REG))
7513    (use (reg:SI R1_REG))
7514    (use (reg:PSI FPSCR_REG))
7515    (clobber (reg:SI PR_REG))]
7516   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7517   "jsr  @%1%#"
7518   [(set_attr "type" "call")
7519    (set (attr "fp_mode")
7520         (if_then_else (eq_attr "fpu_single" "yes")
7521                       (const_string "single") (const_string "double")))
7522    (set_attr "needs_delay_slot" "yes")])
7523
7524 (define_insn "call_value_compact_rettramp"
7525   [(set (match_operand 0 "" "=rf")
7526         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7527               (match_operand 2 "" "")))
7528    (match_operand 3 "immediate_operand" "n")
7529    (use (reg:SI R0_REG))
7530    (use (reg:SI R1_REG))
7531    (use (reg:PSI FPSCR_REG))
7532    (clobber (reg:SI R10_REG))
7533    (clobber (reg:SI PR_REG))]
7534   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7535   "jsr  @%1%#"
7536   [(set_attr "type" "call")
7537    (set (attr "fp_mode")
7538         (if_then_else (eq_attr "fpu_single" "yes")
7539                       (const_string "single") (const_string "double")))
7540    (set_attr "needs_delay_slot" "yes")])
7541
7542 (define_insn "call_value_media"
7543   [(set (match_operand 0 "" "=rf")
7544         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7545               (match_operand 2 "" "")))
7546    (clobber (reg:DI PR_MEDIA_REG))]
7547   "TARGET_SHMEDIA"
7548   "blink        %1, r18"
7549   [(set_attr "type" "jump_media")])
7550
7551 (define_expand "call"
7552   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7553                             (match_operand 1 "" ""))
7554               (match_operand 2 "" "")
7555               (use (reg:PSI FPSCR_REG))
7556               (clobber (reg:SI PR_REG))])]
7557   ""
7558   "
7559 {
7560   if (TARGET_SHMEDIA)
7561     {
7562       operands[0] = shmedia_prepare_call_address (operands[0], 0);
7563       emit_call_insn (gen_call_media (operands[0], operands[1]));
7564       DONE;
7565     }
7566   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7567     {
7568       rtx cookie_rtx = operands[2];
7569       long cookie = INTVAL (cookie_rtx);
7570       rtx func = XEXP (operands[0], 0);
7571       rtx r0, r1;
7572
7573       if (flag_pic)
7574         {
7575           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7576             {
7577               rtx reg = gen_reg_rtx (Pmode);
7578
7579               emit_insn (gen_symGOTPLT2reg (reg, func));
7580               func = reg;
7581             }
7582           else
7583             func = legitimize_pic_address (func, Pmode, 0);
7584         }
7585
7586       r0 = gen_rtx_REG (SImode, R0_REG);
7587       r1 = gen_rtx_REG (SImode, R1_REG);
7588
7589       /* Since such a call function may use all call-clobbered
7590          registers, we force a mode switch earlier, so that we don't
7591          run out of registers when adjusting fpscr for the call.  */
7592       emit_insn (gen_force_mode_for_call ());
7593
7594       operands[0]
7595         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7596                            SFUNC_GOT);
7597       operands[0] = force_reg (SImode, operands[0]);
7598
7599       emit_move_insn (r0, func);
7600       emit_move_insn (r1, cookie_rtx);
7601
7602       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7603         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7604                                                    operands[2]));
7605       else
7606         emit_call_insn (gen_call_compact (operands[0], operands[1],
7607                                           operands[2]));
7608
7609       DONE;
7610     }
7611   else if (TARGET_SHCOMPACT && flag_pic
7612            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7613            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7614     {
7615       rtx reg = gen_reg_rtx (Pmode);
7616
7617       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7618       XEXP (operands[0], 0) = reg;
7619     }
7620   if (flag_pic && TARGET_SH2
7621       && GET_CODE (operands[0]) == MEM
7622       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7623     {
7624       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7625       DONE;
7626     }
7627   else
7628   {
7629     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7630     operands[1] = operands[2];
7631   }
7632
7633   emit_call_insn (gen_calli (operands[0], operands[1]));
7634   DONE;
7635 }")
7636
7637 (define_insn "call_pop_compact"
7638   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7639          (match_operand 1 "" ""))
7640    (match_operand 2 "immediate_operand" "n")
7641    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7642                                  (match_operand 3 "immediate_operand" "n")))
7643    (use (reg:SI R0_REG))
7644    (use (reg:SI R1_REG))
7645    (use (reg:PSI FPSCR_REG))
7646    (clobber (reg:SI PR_REG))]
7647   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7648   "jsr  @%0%#"
7649   [(set_attr "type" "call")
7650    (set (attr "fp_mode")
7651         (if_then_else (eq_attr "fpu_single" "yes")
7652                       (const_string "single") (const_string "double")))
7653    (set_attr "needs_delay_slot" "yes")])
7654
7655 (define_insn "call_pop_compact_rettramp"
7656   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7657          (match_operand 1 "" ""))
7658    (match_operand 2 "immediate_operand" "n")
7659    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7660                                  (match_operand 3 "immediate_operand" "n")))
7661    (use (reg:SI R0_REG))
7662    (use (reg:SI R1_REG))
7663    (use (reg:PSI FPSCR_REG))
7664    (clobber (reg:SI R10_REG))
7665    (clobber (reg:SI PR_REG))]
7666   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7667   "jsr  @%0%#"
7668   [(set_attr "type" "call")
7669    (set (attr "fp_mode")
7670         (if_then_else (eq_attr "fpu_single" "yes")
7671                       (const_string "single") (const_string "double")))
7672    (set_attr "needs_delay_slot" "yes")])
7673
7674 (define_expand "call_pop"
7675   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7676                     (match_operand 1 "" ""))
7677              (match_operand 2 "" "")
7678              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7679                                            (match_operand 3 "" "")))])]
7680   "TARGET_SHCOMPACT"
7681   "
7682 {
7683   rtx cookie_rtx;
7684   long cookie;
7685   rtx func;
7686   rtx r0, r1;
7687
7688   gcc_assert (operands[2] && INTVAL (operands[2]));
7689   cookie_rtx = operands[2];
7690   cookie = INTVAL (cookie_rtx);
7691   func = XEXP (operands[0], 0);
7692
7693   if (flag_pic)
7694     {
7695       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7696         {
7697           rtx reg = gen_reg_rtx (Pmode);
7698           emit_insn (gen_symGOTPLT2reg (reg, func));
7699           func = reg;
7700         }
7701       else
7702         func = legitimize_pic_address (func, Pmode, 0);
7703     }
7704
7705   r0 = gen_rtx_REG (SImode, R0_REG);
7706   r1 = gen_rtx_REG (SImode, R1_REG);
7707
7708   /* Since such a call function may use all call-clobbered
7709      registers, we force a mode switch earlier, so that we don't
7710      run out of registers when adjusting fpscr for the call.  */
7711   emit_insn (gen_force_mode_for_call ());
7712
7713   operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7714                                  SFUNC_GOT);
7715   operands[0] = force_reg (SImode, operands[0]);
7716
7717   emit_move_insn (r0, func);
7718   emit_move_insn (r1, cookie_rtx);
7719
7720   if (cookie & CALL_COOKIE_RET_TRAMP (1))
7721     emit_call_insn (gen_call_pop_compact_rettramp
7722                      (operands[0], operands[1], operands[2], operands[3]));
7723   else
7724     emit_call_insn (gen_call_pop_compact
7725                      (operands[0], operands[1], operands[2], operands[3]));
7726
7727   DONE;
7728 }")
7729
7730 (define_expand "call_value"
7731   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7732                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7733                                  (match_operand 2 "" "")))
7734               (match_operand 3 "" "")
7735               (use (reg:PSI FPSCR_REG))
7736               (clobber (reg:SI PR_REG))])]
7737   ""
7738   "
7739 {
7740   if (TARGET_SHMEDIA)
7741     {
7742       operands[1] = shmedia_prepare_call_address (operands[1], 0);
7743       emit_call_insn (gen_call_value_media (operands[0], operands[1],
7744                                             operands[2]));
7745       DONE;
7746     }
7747   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7748     {
7749       rtx cookie_rtx = operands[3];
7750       long cookie = INTVAL (cookie_rtx);
7751       rtx func = XEXP (operands[1], 0);
7752       rtx r0, r1;
7753
7754       if (flag_pic)
7755         {
7756           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7757             {
7758               rtx reg = gen_reg_rtx (Pmode);
7759
7760               emit_insn (gen_symGOTPLT2reg (reg, func));
7761               func = reg;
7762             }
7763           else
7764             func = legitimize_pic_address (func, Pmode, 0);
7765         }
7766
7767       r0 = gen_rtx_REG (SImode, R0_REG);
7768       r1 = gen_rtx_REG (SImode, R1_REG);
7769
7770       /* Since such a call function may use all call-clobbered
7771          registers, we force a mode switch earlier, so that we don't
7772          run out of registers when adjusting fpscr for the call.  */
7773       emit_insn (gen_force_mode_for_call ());
7774
7775       operands[1]
7776         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7777                            SFUNC_GOT);
7778       operands[1] = force_reg (SImode, operands[1]);
7779
7780       emit_move_insn (r0, func);
7781       emit_move_insn (r1, cookie_rtx);
7782
7783       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7784         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7785                                                          operands[1],
7786                                                          operands[2],
7787                                                          operands[3]));
7788       else
7789         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7790                                                 operands[2], operands[3]));
7791
7792       DONE;
7793     }
7794   else if (TARGET_SHCOMPACT && flag_pic
7795            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7796            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7797     {
7798       rtx reg = gen_reg_rtx (Pmode);
7799
7800       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7801       XEXP (operands[1], 0) = reg;
7802     }
7803   if (flag_pic && TARGET_SH2
7804       && GET_CODE (operands[1]) == MEM
7805       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7806     {
7807       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7808                                             operands[2]));
7809       DONE;
7810     }
7811   else
7812     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7813
7814   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7815   DONE;
7816 }")
7817
7818 (define_insn "sibcalli"
7819   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7820          (match_operand 1 "" ""))
7821    (use (reg:PSI FPSCR_REG))
7822    (return)]
7823   "TARGET_SH1"
7824   "jmp  @%0%#"
7825   [(set_attr "needs_delay_slot" "yes")
7826    (set (attr "fp_mode")
7827         (if_then_else (eq_attr "fpu_single" "yes")
7828                       (const_string "single") (const_string "double")))
7829    (set_attr "type" "jump_ind")])
7830
7831 (define_insn "sibcalli_pcrel"
7832   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7833          (match_operand 1 "" ""))
7834    (use (match_operand 2 "" ""))
7835    (use (reg:PSI FPSCR_REG))
7836    (return)]
7837   "TARGET_SH2"
7838   "braf %0\\n%O2:%#"
7839   [(set_attr "needs_delay_slot" "yes")
7840    (set (attr "fp_mode")
7841         (if_then_else (eq_attr "fpu_single" "yes")
7842                       (const_string "single") (const_string "double")))
7843    (set_attr "type" "jump_ind")])
7844
7845 ;; This uses an unspec to describe that the symbol_ref is very close.
7846 (define_insn "sibcalli_thunk"
7847   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7848                              UNSPEC_THUNK))
7849          (match_operand 1 "" ""))
7850    (use (reg:PSI FPSCR_REG))
7851    (return)]
7852   "TARGET_SH1"
7853   "bra  %O0"
7854   [(set_attr "needs_delay_slot" "yes")
7855    (set (attr "fp_mode")
7856         (if_then_else (eq_attr "fpu_single" "yes")
7857                       (const_string "single") (const_string "double")))
7858    (set_attr "type" "jump")
7859    (set_attr "length" "2")])
7860
7861 (define_insn_and_split "sibcall_pcrel"
7862   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7863          (match_operand 1 "" ""))
7864    (use (reg:PSI FPSCR_REG))
7865    (clobber (match_scratch:SI 2 "=k"))
7866    (return)]
7867   "TARGET_SH2"
7868   "#"
7869   "reload_completed"
7870   [(const_int 0)]
7871   "
7872 {
7873   rtx lab = PATTERN (gen_call_site ());
7874   rtx call_insn;
7875
7876   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7877   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7878                                                   copy_rtx (lab)));
7879   SIBLING_CALL_P (call_insn) = 1;
7880   DONE;
7881 }"
7882   [(set_attr "needs_delay_slot" "yes")
7883    (set (attr "fp_mode")
7884         (if_then_else (eq_attr "fpu_single" "yes")
7885                       (const_string "single") (const_string "double")))
7886    (set_attr "type" "jump_ind")])
7887
7888 (define_insn "sibcall_compact"
7889   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7890          (match_operand 1 "" ""))
7891    (return)
7892    (use (match_operand:SI 2 "register_operand" "z,x"))
7893    (use (reg:SI R1_REG))
7894    (use (reg:PSI FPSCR_REG))
7895    ;; We want to make sure the `x' above will only match MACH_REG
7896    ;; because sibcall_epilogue may clobber MACL_REG.
7897    (clobber (reg:SI MACL_REG))]
7898   "TARGET_SHCOMPACT"
7899   "@
7900         jmp     @%0%#
7901         jmp     @%0\\n  sts     %2, r0"
7902   [(set_attr "needs_delay_slot" "yes,no")
7903    (set_attr "length" "2,4")
7904    (set (attr "fp_mode") (const_string "single"))
7905    (set_attr "type" "jump_ind")])
7906
7907 (define_insn "sibcall_media"
7908   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
7909          (match_operand 1 "" ""))
7910    (use (reg:SI PR_MEDIA_REG))
7911    (return)]
7912   "TARGET_SHMEDIA"
7913   "blink        %0, r63"
7914   [(set_attr "type" "jump_media")])
7915
7916 (define_expand "sibcall"
7917   [(parallel
7918     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7919            (match_operand 1 "" ""))
7920      (match_operand 2 "" "")
7921      (use (reg:PSI FPSCR_REG))
7922      (return)])]
7923   ""
7924   "
7925 {
7926   if (TARGET_SHMEDIA)
7927     {
7928       operands[0] = shmedia_prepare_call_address (operands[0], 1);
7929       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
7930       DONE;
7931     }
7932   else if (TARGET_SHCOMPACT && operands[2]
7933            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7934     {
7935       rtx cookie_rtx = operands[2];
7936       long cookie = INTVAL (cookie_rtx);
7937       rtx func = XEXP (operands[0], 0);
7938       rtx mach, r1;
7939
7940       if (flag_pic)
7941         {
7942           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7943             {
7944               rtx reg = gen_reg_rtx (Pmode);
7945
7946               emit_insn (gen_symGOT2reg (reg, func));
7947               func = reg;
7948             }
7949           else
7950             func = legitimize_pic_address (func, Pmode, 0);
7951         }
7952
7953       /* FIXME: if we could tell whether all argument registers are
7954          already taken, we could decide whether to force the use of
7955          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
7956          simple way to tell.  We could use the CALL_COOKIE, but we
7957          can't currently tell a register used for regular argument
7958          passing from one that is unused.  If we leave it up to reload
7959          to decide which register to use, it seems to always choose
7960          R0_REG, which leaves no available registers in SIBCALL_REGS
7961          to hold the address of the trampoline.  */
7962       mach = gen_rtx_REG (SImode, MACH_REG);
7963       r1 = gen_rtx_REG (SImode, R1_REG);
7964
7965       /* Since such a call function may use all call-clobbered
7966          registers, we force a mode switch earlier, so that we don't
7967          run out of registers when adjusting fpscr for the call.  */
7968       emit_insn (gen_force_mode_for_call ());
7969
7970       operands[0]
7971         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7972                            SFUNC_GOT);
7973       operands[0] = force_reg (SImode, operands[0]);
7974
7975       /* We don't need a return trampoline, since the callee will
7976          return directly to the upper caller.  */
7977       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7978         {
7979           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
7980           cookie_rtx = GEN_INT (cookie);
7981         }
7982
7983       emit_move_insn (mach, func);
7984       emit_move_insn (r1, cookie_rtx);
7985
7986       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
7987       DONE;
7988     }
7989   else if (TARGET_SHCOMPACT && flag_pic
7990            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7991            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7992     {
7993       rtx reg = gen_reg_rtx (Pmode);
7994
7995       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
7996       XEXP (operands[0], 0) = reg;
7997     }
7998   if (flag_pic && TARGET_SH2
7999       && GET_CODE (operands[0]) == MEM
8000       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8001       /* The PLT needs the PIC register, but the epilogue would have
8002          to restore it, so we can only use PC-relative PIC calls for
8003          static functions.  */
8004       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8005     {
8006       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
8007       DONE;
8008     }
8009   else
8010     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
8011
8012   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
8013   DONE;
8014 }")
8015
8016 (define_expand "sibcall_value"
8017   [(set (match_operand 0 "" "")
8018         (call (match_operand 1 "" "")
8019               (match_operand 2 "" "")))
8020    (match_operand 3 "" "")]
8021   ""
8022   "
8023 {
8024   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
8025   DONE;
8026 }")
8027
8028 (define_insn "call_value_pop_compact"
8029   [(set (match_operand 0 "" "=rf")
8030         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8031               (match_operand 2 "" "")))
8032    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8033                                  (match_operand 4 "immediate_operand" "n")))
8034    (match_operand 3 "immediate_operand" "n")
8035    (use (reg:SI R0_REG))
8036    (use (reg:SI R1_REG))
8037    (use (reg:PSI FPSCR_REG))
8038    (clobber (reg:SI PR_REG))]
8039   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8040   "jsr  @%1%#"
8041   [(set_attr "type" "call")
8042    (set (attr "fp_mode")
8043         (if_then_else (eq_attr "fpu_single" "yes")
8044                       (const_string "single") (const_string "double")))
8045    (set_attr "needs_delay_slot" "yes")])
8046
8047 (define_insn "call_value_pop_compact_rettramp"
8048   [(set (match_operand 0 "" "=rf")
8049         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8050               (match_operand 2 "" "")))
8051    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8052                                  (match_operand 4 "immediate_operand" "n")))
8053    (match_operand 3 "immediate_operand" "n")
8054    (use (reg:SI R0_REG))
8055    (use (reg:SI R1_REG))
8056    (use (reg:PSI FPSCR_REG))
8057    (clobber (reg:SI R10_REG))
8058    (clobber (reg:SI PR_REG))]
8059   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8060   "jsr  @%1%#"
8061   [(set_attr "type" "call")
8062    (set (attr "fp_mode")
8063         (if_then_else (eq_attr "fpu_single" "yes")
8064                       (const_string "single") (const_string "double")))
8065    (set_attr "needs_delay_slot" "yes")])
8066
8067 (define_expand "call_value_pop"
8068   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8069                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8070                                  (match_operand 2 "" "")))
8071               (match_operand 3 "" "")
8072               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8073                                             (match_operand 4 "" "")))])]
8074   "TARGET_SHCOMPACT"
8075   "
8076 {
8077   rtx cookie_rtx;
8078   long cookie;
8079   rtx func;
8080   rtx r0, r1;
8081
8082   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8083   cookie_rtx = operands[3];
8084   cookie = INTVAL (cookie_rtx);
8085   func = XEXP (operands[1], 0);
8086
8087   if (flag_pic)
8088     {
8089       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8090         {
8091           rtx reg = gen_reg_rtx (Pmode);
8092
8093           emit_insn (gen_symGOTPLT2reg (reg, func));
8094           func = reg;
8095         }
8096       else
8097         func = legitimize_pic_address (func, Pmode, 0);
8098     }
8099
8100   r0 = gen_rtx_REG (SImode, R0_REG);
8101   r1 = gen_rtx_REG (SImode, R1_REG);
8102
8103   /* Since such a call function may use all call-clobbered
8104      registers, we force a mode switch earlier, so that we don't
8105      run out of registers when adjusting fpscr for the call.  */
8106   emit_insn (gen_force_mode_for_call ());
8107
8108   operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8109                                  SFUNC_GOT);
8110   operands[1] = force_reg (SImode, operands[1]);
8111
8112   emit_move_insn (r0, func);
8113   emit_move_insn (r1, cookie_rtx);
8114
8115   if (cookie & CALL_COOKIE_RET_TRAMP (1))
8116     emit_call_insn (gen_call_value_pop_compact_rettramp
8117                         (operands[0], operands[1], operands[2],
8118                          operands[3], operands[4]));
8119   else
8120     emit_call_insn (gen_call_value_pop_compact
8121                         (operands[0], operands[1], operands[2],
8122                          operands[3], operands[4]));
8123
8124   DONE;
8125 }")
8126
8127 (define_expand "sibcall_epilogue"
8128   [(return)]
8129   ""
8130   "
8131 {
8132   sh_expand_epilogue (1);
8133   if (TARGET_SHCOMPACT)
8134     {
8135       rtx insn, set;
8136
8137       /* If epilogue clobbers r0, preserve it in macl.  */
8138       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8139         if ((set = single_set (insn))
8140             && GET_CODE (SET_DEST (set)) == REG
8141             && REGNO (SET_DEST (set)) == R0_REG)
8142           {
8143             rtx r0 = gen_rtx_REG (SImode, R0_REG);
8144             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8145             rtx i;
8146
8147             /* We can't tell at this point whether the sibcall is a
8148                sibcall_compact and, if it is, whether it uses r0 or
8149                mach as operand 2, so let the instructions that
8150                preserve r0 be optimized away if r0 turns out to be
8151                dead.  */
8152             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8153             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
8154                                                REG_NOTES (i));
8155             i = emit_move_insn (r0, tmp);
8156             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
8157                                                REG_NOTES (i));
8158             break;
8159           }
8160     }
8161   DONE;
8162 }")
8163
8164 (define_insn "indirect_jump_compact"
8165   [(set (pc)
8166         (match_operand:SI 0 "arith_reg_operand" "r"))]
8167   "TARGET_SH1"
8168   "jmp  @%0%#"
8169   [(set_attr "needs_delay_slot" "yes")
8170    (set_attr "type" "jump_ind")])
8171
8172 (define_expand "indirect_jump"
8173   [(set (pc)
8174         (match_operand 0 "register_operand" ""))]
8175   ""
8176   "
8177 {
8178   if (GET_MODE (operands[0]) != Pmode)
8179     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8180 }")
8181
8182 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8183 ;; which can be present in structured code from indirect jumps which can not
8184 ;; be present in structured code.  This allows -fprofile-arcs to work.
8185
8186 ;; For SH1 processors.
8187 (define_insn "casesi_jump_1"
8188   [(set (pc)
8189         (match_operand:SI 0 "register_operand" "r"))
8190    (use (label_ref (match_operand 1 "" "")))]
8191   "TARGET_SH1"
8192   "jmp  @%0%#"
8193   [(set_attr "needs_delay_slot" "yes")
8194    (set_attr "type" "jump_ind")])
8195
8196 ;; For all later processors.
8197 (define_insn "casesi_jump_2"
8198   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8199                       (label_ref (match_operand 1 "" ""))))
8200    (use (label_ref (match_operand 2 "" "")))]
8201   "TARGET_SH2
8202    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8203   "braf %0%#"
8204   [(set_attr "needs_delay_slot" "yes")
8205    (set_attr "type" "jump_ind")])
8206
8207 (define_insn "casesi_jump_media"
8208   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8209    (use (label_ref (match_operand 1 "" "")))]
8210   "TARGET_SHMEDIA"
8211   "blink        %0, r63"
8212   [(set_attr "type" "jump_media")])
8213
8214 ;; Call subroutine returning any type.
8215 ;; ??? This probably doesn't work.
8216
8217 (define_expand "untyped_call"
8218   [(parallel [(call (match_operand 0 "" "")
8219                     (const_int 0))
8220               (match_operand 1 "" "")
8221               (match_operand 2 "" "")])]
8222   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8223   "
8224 {
8225   int i;
8226
8227   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8228
8229   for (i = 0; i < XVECLEN (operands[2], 0); i++)
8230     {
8231       rtx set = XVECEXP (operands[2], 0, i);
8232       emit_move_insn (SET_DEST (set), SET_SRC (set));
8233     }
8234
8235   /* The optimizer does not know that the call sets the function value
8236      registers we stored in the result block.  We avoid problems by
8237      claiming that all hard registers are used and clobbered at this
8238      point.  */
8239   emit_insn (gen_blockage ());
8240
8241   DONE;
8242 }")
8243 \f
8244 ;; ------------------------------------------------------------------------
8245 ;; Misc insns
8246 ;; ------------------------------------------------------------------------
8247
8248 (define_insn "dect"
8249   [(set (reg:SI T_REG)
8250         (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1)))
8251    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
8252   "TARGET_SH2"
8253   "dt   %0"
8254   [(set_attr "type" "arith")])
8255
8256 (define_insn "nop"
8257   [(const_int 0)]
8258   ""
8259   "nop")
8260
8261 ;; Load address of a label. This is only generated by the casesi expand,
8262 ;; and by machine_dependent_reorg (fixing up fp moves).
8263 ;; This must use unspec, because this only works for labels that are
8264 ;; within range,
8265
8266 (define_insn "mova"
8267   [(set (reg:SI R0_REG)
8268         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8269   "TARGET_SH1"
8270   "mova %O0,r0"
8271   [(set_attr "in_delay_slot" "no")
8272    (set_attr "type" "arith")])
8273
8274 ;; machine_dependent_reorg will make this a `mova'.
8275 (define_insn "mova_const"
8276   [(set (reg:SI R0_REG)
8277         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8278   "TARGET_SH1"
8279   "#"
8280   [(set_attr "in_delay_slot" "no")
8281    (set_attr "type" "arith")])
8282
8283 (define_expand "GOTaddr2picreg"
8284   [(set (reg:SI R0_REG)
8285         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8286                    UNSPEC_MOVA))
8287    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8288    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8289   "" "
8290 {
8291   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8292   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8293
8294   if (TARGET_SHMEDIA)
8295     {
8296       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8297       rtx pic = operands[0];
8298       rtx lab = PATTERN (gen_call_site ());
8299       rtx insn, equiv;
8300
8301       equiv = operands[1];
8302       operands[1] = gen_rtx_MINUS (Pmode,
8303                                    operands[1],
8304                                    gen_rtx_CONST
8305                                    (Pmode,
8306                                     gen_rtx_MINUS (Pmode,
8307                                                    gen_rtx_CONST (Pmode,
8308                                                                   lab),
8309                                                    pc_rtx)));
8310       operands[1] = gen_sym2PIC (operands[1]);
8311       PUT_MODE (operands[1], Pmode);
8312
8313       if (Pmode == SImode)
8314         {
8315           emit_insn (gen_movsi_const (pic, operands[1]));
8316           emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8317         }
8318       else
8319         {
8320           emit_insn (gen_movdi_const (pic, operands[1]));
8321           emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8322         }
8323
8324       insn = emit_move_insn (operands[0], tr);
8325
8326       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
8327                                             REG_NOTES (insn));
8328
8329       DONE;
8330     }
8331 }
8332 ")
8333
8334 (define_insn "*ptb"
8335   [(set (match_operand 0 "target_reg_operand" "=b")
8336         (const (unspec [(match_operand 1 "" "Csy")]
8337                              UNSPEC_DATALABEL)))]
8338   "TARGET_SHMEDIA && flag_pic
8339    && EXTRA_CONSTRAINT_Csy (operands[1])"
8340   "ptb/u        datalabel %1, %0"
8341   [(set_attr "type" "ptabs_media")
8342    (set_attr "length" "*")])
8343
8344 (define_insn "ptrel_si"
8345   [(set (match_operand:SI 0 "target_reg_operand" "=b")
8346         (plus:SI (match_operand:SI 1 "register_operand" "r")
8347               (pc)))
8348    (match_operand:SI 2 "" "")]
8349   "TARGET_SHMEDIA"
8350   "%O2: ptrel/u %1, %0"
8351   [(set_attr "type" "ptabs_media")])
8352
8353 (define_insn "ptrel_di"
8354   [(set (match_operand:DI 0 "target_reg_operand" "=b")
8355         (plus:DI (match_operand:DI 1 "register_operand" "r")
8356               (pc)))
8357    (match_operand:DI 2 "" "")]
8358   "TARGET_SHMEDIA"
8359   "%O2: ptrel/u %1, %0"
8360   [(set_attr "type" "ptabs_media")])
8361
8362 (define_expand "builtin_setjmp_receiver"
8363   [(match_operand 0 "" "")]
8364   "flag_pic"
8365   "
8366 {
8367   emit_insn (gen_GOTaddr2picreg ());
8368   DONE;
8369 }")
8370
8371 (define_expand "call_site"
8372   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8373   "TARGET_SH1"
8374   "
8375 {
8376   static HOST_WIDE_INT i = 0;
8377   operands[0] = GEN_INT (i);
8378   i++;
8379 }")
8380
8381 (define_expand "sym_label2reg"
8382   [(set (match_operand:SI 0 "" "")
8383         (const:SI (minus:SI
8384                    (const:SI
8385                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
8386                    (const:SI
8387                     (plus:SI
8388                      (match_operand:SI 2 "" "")
8389                      (const_int 2))))))]
8390   "TARGET_SH1" "")
8391
8392 (define_expand "symGOT_load"
8393   [(set (match_dup 2) (match_operand 1 "" ""))
8394    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8395    (set (match_operand 0 "" "") (mem (match_dup 3)))]
8396   ""
8397   "
8398 {
8399   rtx insn, mem;
8400
8401   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8402   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8403
8404   if (TARGET_SHMEDIA)
8405     {
8406       rtx reg = operands[2];
8407
8408       if (Pmode == DImode)
8409         {      
8410           if (flag_pic > 1)
8411             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8412           else
8413             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8414         }
8415       else
8416         {
8417           if (flag_pic > 1)
8418             emit_insn (gen_movsi_const (reg, operands[1]));
8419           else
8420             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8421         }
8422     }
8423   else
8424     emit_move_insn (operands[2], operands[1]);
8425
8426   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
8427                                              operands[2],
8428                                              gen_rtx_REG (Pmode, PIC_REG)));
8429
8430   /* N.B. This is not constant for a GOTPLT relocation.  */
8431   mem = gen_rtx_MEM (Pmode, operands[3]);
8432   MEM_NOTRAP_P (mem) = 1;
8433   /* ??? Should we have a special alias set for the GOT?  */
8434   insn = emit_move_insn (operands[0], mem);
8435
8436   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
8437                                                                   0), 0, 0),
8438                                         REG_NOTES (insn));
8439
8440   DONE;
8441 }")
8442
8443 (define_expand "sym2GOT"
8444   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8445   ""
8446   "")
8447
8448 (define_expand "symGOT2reg"
8449   [(match_operand 0 "" "") (match_operand 1 "" "")]
8450   ""
8451   "
8452 {
8453   rtx gotsym, insn;
8454
8455   gotsym = gen_sym2GOT (operands[1]);
8456   PUT_MODE (gotsym, Pmode);
8457   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8458
8459   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8460
8461   DONE;
8462 }")
8463
8464 (define_expand "symGOTPLT2reg"
8465   [(match_operand 0 "" "") (match_operand 1 "" "")]
8466   ""
8467   "
8468 {
8469   rtx pltsym = gen_rtx_CONST (Pmode,
8470                               gen_rtx_UNSPEC (Pmode,
8471                                               gen_rtvec (1, operands[1]),
8472                                               UNSPEC_GOTPLT));
8473   emit_insn (gen_symGOT_load (operands[0], pltsym));
8474   DONE;
8475 }")
8476
8477 (define_expand "sym2GOTOFF"
8478   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8479   ""
8480   "")
8481
8482 (define_expand "symGOTOFF2reg"
8483   [(match_operand 0 "" "") (match_operand 1 "" "")]
8484   ""
8485   "
8486 {
8487   rtx gotoffsym, insn;
8488   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8489
8490   gotoffsym = gen_sym2GOTOFF (operands[1]);
8491   PUT_MODE (gotoffsym, Pmode);
8492   emit_move_insn (t, gotoffsym);
8493   insn = emit_move_insn (operands[0],
8494                          gen_rtx_PLUS (Pmode, t,
8495                                        gen_rtx_REG (Pmode, PIC_REG)));
8496
8497   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
8498                                         REG_NOTES (insn));
8499
8500   DONE;
8501 }")
8502
8503 (define_expand "symPLT_label2reg"
8504   [(set (match_operand:SI 0 "" "")
8505         (const:SI (minus:SI
8506                    (const:SI
8507                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8508                    (const:SI
8509                     (minus:SI
8510                      (const:SI (plus:SI
8511                                 (match_operand:SI 2 "" "")
8512                                 (const_int 2)))
8513                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
8514    ;; Even though the PIC register is not really used by the call
8515    ;; sequence in which this is expanded, the PLT code assumes the PIC
8516    ;; register is set, so we must not skip its initialization.  Since
8517    ;; we only use this expand as part of calling sequences, and never
8518    ;; to take the address of a function, this is the best point to
8519    ;; insert the (use).  Using the PLT to take the address of a
8520    ;; function would be wrong, not only because the PLT entry could
8521    ;; then be called from a function that doesn't initialize the PIC
8522    ;; register to the proper GOT, but also because pointers to the
8523    ;; same function might not compare equal, should they be set by
8524    ;; different shared libraries.
8525    (use (reg:SI PIC_REG))]
8526   "TARGET_SH1"
8527   "")
8528
8529 (define_expand "sym2PIC"
8530   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8531   ""
8532   "")
8533
8534 ;; TLS code generation.
8535 ;; ??? this should be a define_insn_and_split
8536 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8537 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8538 ;; for details.
8539
8540 (define_insn "tls_global_dynamic"
8541   [(set (match_operand:SI 0 "register_operand" "=&z")
8542         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8543                                   UNSPEC_TLSGD))
8544               (const_int 0)))
8545    (use (reg:PSI FPSCR_REG))
8546    (use (reg:SI PIC_REG))
8547    (clobber (reg:SI PR_REG))
8548    (clobber (scratch:SI))]
8549   "TARGET_SH1"
8550   "*
8551 {
8552   return \"\\
8553 mov.l\\t1f,r4\\n\\
8554 \\tmova\\t2f,r0\\n\\
8555 \\tmov.l\\t2f,r1\\n\\
8556 \\tadd\\tr0,r1\\n\\
8557 \\tjsr\\t@r1\\n\\
8558 \\tadd\\tr12,r4\\n\\
8559 \\tbra\\t3f\\n\\
8560 \\tnop\\n\\
8561 \\t.align\\t2\\n\\
8562 1:\\t.long\\t%a1@TLSGD\\n\\
8563 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8564 3:\";
8565 }"
8566   [(set_attr "type" "tls_load")
8567    (set_attr "length" "26")])
8568
8569 (define_insn "tls_local_dynamic"
8570   [(set (match_operand:SI 0 "register_operand" "=&z")
8571         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8572                                   UNSPEC_TLSLDM))
8573               (const_int 0)))
8574    (use (reg:PSI FPSCR_REG))
8575    (use (reg:SI PIC_REG))
8576    (clobber (reg:SI PR_REG))
8577    (clobber (scratch:SI))]
8578   "TARGET_SH1"
8579   "*
8580 {
8581   return \"\\
8582 mov.l\\t1f,r4\\n\\
8583 \\tmova\\t2f,r0\\n\\
8584 \\tmov.l\\t2f,r1\\n\\
8585 \\tadd\\tr0,r1\\n\\
8586 \\tjsr\\t@r1\\n\\
8587 \\tadd\\tr12,r4\\n\\
8588 \\tbra\\t3f\\n\\
8589 \\tnop\\n\\
8590 \\t.align\\t2\\n\\
8591 1:\\t.long\\t%a1@TLSLDM\\n\\
8592 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8593 3:\";
8594 }"
8595   [(set_attr "type" "tls_load")
8596    (set_attr "length" "26")])
8597
8598 (define_expand "sym2DTPOFF"
8599   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8600   ""
8601   "")
8602
8603 (define_expand "symDTPOFF2reg"
8604   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8605   ""
8606   "
8607 {
8608   rtx dtpoffsym, insn;
8609   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8610
8611   dtpoffsym = gen_sym2DTPOFF (operands[1]);
8612   PUT_MODE (dtpoffsym, Pmode);
8613   emit_move_insn (t, dtpoffsym);
8614   insn = emit_move_insn (operands[0],
8615                          gen_rtx_PLUS (Pmode, t, operands[2]));
8616   DONE;
8617 }")
8618
8619 (define_expand "sym2GOTTPOFF"
8620   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8621   ""
8622   "")
8623
8624 (define_insn "tls_initial_exec"
8625   [(set (match_operand:SI 0 "register_operand" "=&r")
8626         (unspec:SI [(match_operand:SI 1 "" "")]
8627                     UNSPEC_TLSIE))
8628    (use (reg:SI GBR_REG))
8629    (use (reg:SI PIC_REG))
8630    (clobber (reg:SI R0_REG))]
8631   ""
8632   "*
8633 {
8634   return \"\\
8635 mov.l\\t1f,r0\\n\\
8636 \\tstc\\tgbr,%0\\n\\
8637 \\tmov.l\\t@(r0,r12),r0\\n\\
8638 \\tbra\\t2f\\n\\
8639 \\tadd\\tr0,%0\\n\\
8640 \\t.align\\t2\\n\\
8641 1:\\t.long\\t%a1\\n\\
8642 2:\";
8643 }"
8644   [(set_attr "type" "tls_load")
8645    (set_attr "length" "16")])
8646
8647 (define_expand "sym2TPOFF"
8648   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8649   ""
8650   "")
8651
8652 (define_expand "symTPOFF2reg"
8653   [(match_operand 0 "" "") (match_operand 1 "" "")]
8654   ""
8655   "
8656 {
8657   rtx tpoffsym, insn;
8658
8659   tpoffsym = gen_sym2TPOFF (operands[1]);
8660   PUT_MODE (tpoffsym, Pmode);
8661   insn = emit_move_insn (operands[0], tpoffsym);
8662   DONE;
8663 }")
8664
8665 (define_insn "load_gbr"
8666   [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
8667    (use (reg:SI GBR_REG))]
8668   ""
8669   "stc  gbr,%0"
8670   [(set_attr "type" "tls_load")])
8671
8672 ;; case instruction for switch statements.
8673
8674 ;; Operand 0 is index
8675 ;; operand 1 is the minimum bound
8676 ;; operand 2 is the maximum bound - minimum bound + 1
8677 ;; operand 3 is CODE_LABEL for the table;
8678 ;; operand 4 is the CODE_LABEL to go to if index out of range.
8679
8680 (define_expand "casesi"
8681   [(match_operand:SI 0 "arith_reg_operand" "")
8682    (match_operand:SI 1 "arith_reg_operand" "")
8683    (match_operand:SI 2 "arith_reg_operand" "")
8684    (match_operand 3 "" "") (match_operand 4 "" "")]
8685   ""
8686   "
8687 {
8688   rtx reg = gen_reg_rtx (SImode);
8689   rtx reg2 = gen_reg_rtx (SImode);
8690   if (TARGET_SHMEDIA)
8691     {
8692       rtx reg = gen_reg_rtx (DImode);
8693       rtx reg2 = gen_reg_rtx (DImode);
8694       rtx reg3 = gen_reg_rtx (Pmode);
8695       rtx reg4 = gen_reg_rtx (Pmode);
8696       rtx reg5 = gen_reg_rtx (Pmode);
8697       rtx load;
8698
8699       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
8700       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
8701       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
8702
8703       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
8704       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
8705       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
8706       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
8707       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
8708                                                (Pmode, operands[3])));
8709       /* Messy: can we subreg to clean this up? */
8710       if (Pmode == DImode)
8711         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
8712       else
8713         load = gen_casesi_load_media (reg4,
8714                                       gen_rtx_SUBREG (DImode, reg3, 0),
8715                                       reg2, operands[3]);
8716       PUT_MODE (SET_SRC (load), Pmode);
8717       emit_insn (load);
8718       /* ??? The following add could be eliminated if we used ptrel.  */
8719       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
8720       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
8721       emit_barrier ();
8722       DONE;
8723     }
8724   operands[1] = copy_to_mode_reg (SImode, operands[1]);
8725   operands[2] = copy_to_mode_reg (SImode, operands[2]);
8726   /* If optimizing, casesi_worker depends on the mode of the instruction
8727      before label it 'uses' - operands[3].  */
8728   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
8729                            reg));
8730   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
8731   if (TARGET_SH2)
8732     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
8733   else
8734     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
8735   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
8736      operands[3], but to lab.  We will fix this up in
8737      machine_dependent_reorg.  */
8738   emit_barrier ();
8739   DONE;
8740 }")
8741
8742 (define_expand "casesi_0"
8743   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
8744    (set (match_dup 4) (minus:SI (match_dup 4)
8745                                 (match_operand:SI 1 "arith_operand" "")))
8746    (set (reg:SI T_REG)
8747         (gtu:SI (match_dup 4)
8748                 (match_operand:SI 2 "arith_reg_operand" "")))
8749    (set (pc)
8750         (if_then_else (ne (reg:SI T_REG)
8751                           (const_int 0))
8752                       (label_ref (match_operand 3 "" ""))
8753                       (pc)))]
8754   "TARGET_SH1"
8755   "")
8756
8757 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
8758 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
8759 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
8760
8761 (define_insn "casesi_worker_0"
8762   [(set (match_operand:SI 0 "register_operand" "=r,r")
8763         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
8764                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8765    (clobber (match_scratch:SI 3 "=X,1"))
8766    (clobber (match_scratch:SI 4 "=&z,z"))]
8767   "TARGET_SH1"
8768   "#")
8769
8770 (define_split
8771   [(set (match_operand:SI 0 "register_operand" "")
8772         (unspec:SI [(match_operand:SI 1 "register_operand" "")
8773                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8774    (clobber (match_scratch:SI 3 ""))
8775    (clobber (match_scratch:SI 4 ""))]
8776   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
8777   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8778    (parallel [(set (match_dup 0)
8779               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8780                           (label_ref (match_dup 2))] UNSPEC_CASESI))
8781               (clobber (match_dup 3))])
8782    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8783   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8784
8785 (define_split
8786   [(set (match_operand:SI 0 "register_operand" "")
8787         (unspec:SI [(match_operand:SI 1 "register_operand" "")
8788                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8789    (clobber (match_scratch:SI 3 ""))
8790    (clobber (match_scratch:SI 4 ""))]
8791   "TARGET_SH2 && reload_completed"
8792   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8793    (parallel [(set (match_dup 0)
8794               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8795                           (label_ref (match_dup 2))] UNSPEC_CASESI))
8796               (clobber (match_dup 3))])]
8797   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8798
8799 (define_insn "casesi_worker_1"
8800   [(set (match_operand:SI 0 "register_operand" "=r,r")
8801         (unspec:SI [(reg:SI R0_REG)
8802                     (match_operand:SI 1 "register_operand" "0,r")
8803                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8804    (clobber (match_scratch:SI 3 "=X,1"))]
8805   "TARGET_SH1"
8806   "*
8807 {
8808   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8809
8810   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8811
8812   switch (GET_MODE (diff_vec))
8813     {
8814     case SImode:
8815       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
8816     case HImode:
8817       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
8818     case QImode:
8819       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8820         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
8821       return \"mov.b    @(r0,%1),%0\";
8822     default:
8823       gcc_unreachable ();
8824     }
8825 }"
8826   [(set_attr "length" "4")])
8827
8828 (define_insn "casesi_worker_2"
8829   [(set (match_operand:SI 0 "register_operand" "=r,r")
8830         (unspec:SI [(reg:SI R0_REG)
8831                     (match_operand:SI 1 "register_operand" "0,r")
8832                     (label_ref (match_operand 2 "" ""))
8833                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
8834    (clobber (match_operand:SI 4 "" "=X,1"))]
8835   "TARGET_SH2 && reload_completed && flag_pic"
8836   "*
8837 {
8838   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8839   const char *load;
8840
8841   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8842
8843   switch (GET_MODE (diff_vec))
8844     {
8845     case SImode:
8846       output_asm_insn (\"shll2    %1\", operands);
8847       load = \"mov.l    @(r0,%1),%0\"; break;
8848     case HImode:
8849       output_asm_insn (\"add    %1,%1\", operands);
8850       load = \"mov.w    @(r0,%1),%0\"; break;
8851     case QImode:
8852       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8853         load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
8854       else
8855         load = \"mov.b  @(r0,%1),%0\";
8856       break;
8857     default:
8858       gcc_unreachable ();
8859     }
8860   output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
8861   return load;
8862 }"
8863   [(set_attr "length" "8")])
8864
8865 (define_insn "casesi_shift_media"
8866   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
8867         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
8868                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
8869                     UNSPEC_CASESI)))]
8870   "TARGET_SHMEDIA"
8871   "*
8872 {
8873   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8874
8875   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8876
8877   switch (GET_MODE (diff_vec))
8878     {
8879     case SImode:
8880       return \"shlli    %1, 2, %0\";
8881     case HImode:
8882       return \"shlli    %1, 1, %0\";
8883     case QImode:
8884       if (rtx_equal_p (operands[0], operands[1]))
8885         return \"\";
8886       return \"add      %1, r63, %0\";
8887     default:
8888       gcc_unreachable ();
8889     }
8890 }"
8891   [(set_attr "type" "arith_media")])
8892
8893 (define_insn "casesi_load_media"
8894   [(set (match_operand 0 "any_arith_reg_dest" "=r")
8895         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
8896                          (match_operand:DI 2 "arith_reg_operand" "r")
8897                          (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
8898   "TARGET_SHMEDIA"
8899   "*
8900 {
8901   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
8902
8903   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8904
8905   switch (GET_MODE (diff_vec))
8906     {
8907     case SImode:
8908       return \"ldx.l    %1, %2, %0\";
8909     case HImode:
8910 #if 0
8911       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8912         return \"ldx.uw %1, %2, %0\";
8913 #endif
8914       return \"ldx.w    %1, %2, %0\";
8915     case QImode:
8916       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8917         return \"ldx.ub %1, %2, %0\";
8918       return \"ldx.b    %1, %2, %0\";
8919     default:
8920       gcc_unreachable ();
8921     }
8922 }"
8923   [(set_attr "type" "load_media")])
8924
8925 (define_expand "return"
8926   [(return)]
8927   "reload_completed && ! sh_need_epilogue ()"
8928   "
8929 {
8930   if (TARGET_SHMEDIA)
8931     {
8932       emit_jump_insn (gen_return_media ());
8933       DONE;
8934     }
8935
8936   if (TARGET_SHCOMPACT
8937       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
8938     {
8939       emit_jump_insn (gen_shcompact_return_tramp ());
8940       DONE;
8941     }
8942 }")
8943
8944 (define_insn "*return_i"
8945   [(return)]
8946   "TARGET_SH1 && ! (TARGET_SHCOMPACT
8947                     && (current_function_args_info.call_cookie
8948                         & CALL_COOKIE_RET_TRAMP (1)))
8949    && reload_completed
8950    && lookup_attribute (\"trap_exit\",
8951                         DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
8952   "%@   %#"
8953   [(set_attr "type" "return")
8954    (set_attr "needs_delay_slot" "yes")])
8955
8956 ;; trapa has no delay slot.
8957 (define_insn "*return_trapa"
8958   [(return)]
8959   "TARGET_SH1 && !TARGET_SHCOMPACT
8960    && reload_completed"
8961   "%@"
8962   [(set_attr "type" "return")])
8963
8964 (define_expand "shcompact_return_tramp"
8965   [(return)]
8966   "TARGET_SHCOMPACT
8967    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
8968   "
8969 {
8970   rtx reg = gen_rtx_REG (Pmode, R0_REG);
8971
8972   function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
8973   emit_jump_insn (gen_shcompact_return_tramp_i ());
8974   DONE;
8975 }")
8976
8977 (define_insn "shcompact_return_tramp_i"
8978   [(parallel [(return) (use (reg:SI R0_REG))])]
8979   "TARGET_SHCOMPACT
8980    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
8981   "jmp  @r0%#"
8982   [(set_attr "type" "jump_ind")
8983    (set_attr "needs_delay_slot" "yes")])
8984
8985 (define_insn "return_media_i"
8986   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
8987   "TARGET_SHMEDIA && reload_completed"
8988   "blink        %0, r63"
8989   [(set_attr "type" "jump_media")])
8990
8991 (define_insn "return_media_rte"
8992   [(return)]
8993   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
8994   "rte"
8995   [(set_attr "type" "jump_media")])
8996
8997 (define_expand "return_media"
8998   [(return)]
8999   "TARGET_SHMEDIA && reload_completed"
9000   "
9001 {
9002   int tr_regno = sh_media_register_for_return ();
9003   rtx tr;
9004
9005   if (current_function_interrupt)
9006     {
9007       emit_jump_insn (gen_return_media_rte ());
9008       DONE;
9009     }
9010   if (tr_regno < 0)
9011     {
9012       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9013
9014       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9015       tr_regno = TR0_REG;
9016       tr = gen_rtx_REG (Pmode, tr_regno);
9017       emit_move_insn (tr, r18);
9018     }
9019   else
9020     tr = gen_rtx_REG (Pmode, tr_regno);
9021
9022   emit_jump_insn (gen_return_media_i (tr));
9023   DONE;
9024 }")
9025
9026 (define_insn "shcompact_preserve_incoming_args"
9027   [(set (match_operand:SI 0 "register_operand" "+r")
9028         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9029   "TARGET_SHCOMPACT"
9030   ""
9031   [(set_attr "length" "0")])
9032
9033 (define_insn "shcompact_incoming_args"
9034   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9035    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9036    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9037    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9038    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9039    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9040    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9041    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9042    (set (mem:BLK (reg:SI MACL_REG))
9043         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9044    (use (reg:SI R0_REG))
9045    (clobber (reg:SI R0_REG))
9046    (clobber (reg:SI MACL_REG))
9047    (clobber (reg:SI MACH_REG))
9048    (clobber (reg:SI PR_REG))]
9049   "TARGET_SHCOMPACT"
9050   "jsr  @r0%#"
9051   [(set_attr "needs_delay_slot" "yes")])
9052
9053 (define_insn "shmedia_save_restore_regs_compact"
9054   [(set (reg:SI SP_REG)
9055         (plus:SI (reg:SI SP_REG)
9056                  (match_operand:SI 0 "immediate_operand" "i")))
9057    (use (reg:SI R0_REG))
9058    (clobber (reg:SI PR_REG))]
9059   "TARGET_SHCOMPACT
9060    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9061        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9062   "jsr @r0%#"
9063   [(set_attr "needs_delay_slot" "yes")])
9064
9065 (define_expand "prologue"
9066   [(const_int 0)]
9067   ""
9068   "sh_expand_prologue (); DONE;")
9069
9070 (define_expand "epilogue"
9071   [(return)]
9072   ""
9073   "
9074 {
9075   sh_expand_epilogue (0);
9076   emit_jump_insn (gen_return ());
9077   DONE;
9078 }")
9079
9080 (define_expand "eh_return"
9081   [(use (match_operand 0 "register_operand" ""))]
9082   ""
9083 {
9084   rtx ra = operands[0];
9085
9086   if (TARGET_SHMEDIA64)
9087     emit_insn (gen_eh_set_ra_di (ra));
9088   else
9089     emit_insn (gen_eh_set_ra_si (ra));
9090
9091   DONE;
9092 })
9093
9094 ;; Clobber the return address on the stack.  We can't expand this
9095 ;; until we know where it will be put in the stack frame.
9096
9097 (define_insn "eh_set_ra_si"
9098   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
9099    (clobber (match_scratch:SI 1 "=&r"))]
9100   "! TARGET_SHMEDIA64"
9101   "#")
9102
9103 (define_insn "eh_set_ra_di"
9104   [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
9105    (clobber (match_scratch:DI 1 "=&r"))]
9106   "TARGET_SHMEDIA64"
9107   "#")
9108
9109 (define_split
9110   [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
9111    (clobber (match_scratch 1 ""))]
9112   "reload_completed"
9113   [(const_int 0)]
9114   "
9115 {
9116   sh_set_return_address (operands[0], operands[1]);
9117   DONE;
9118 }")
9119
9120 (define_insn "blockage"
9121   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9122   ""
9123   ""
9124   [(set_attr "length" "0")])
9125 \f
9126 ;; ------------------------------------------------------------------------
9127 ;; Scc instructions
9128 ;; ------------------------------------------------------------------------
9129
9130 (define_insn "movt"
9131   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9132         (eq:SI (reg:SI T_REG) (const_int 1)))]
9133   "TARGET_SH1"
9134   "movt %0"
9135   [(set_attr "type" "arith")])
9136
9137 (define_expand "seq"
9138   [(set (match_operand:SI 0 "arith_reg_dest" "")
9139         (match_dup 1))]
9140   ""
9141   "
9142 {
9143   if (TARGET_SHMEDIA)
9144     {
9145       rtx reg;
9146
9147       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9148       if (sh_compare_op1 != const0_rtx)
9149         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9150                                     ? GET_MODE (sh_compare_op0)
9151                                     : GET_MODE (sh_compare_op1),
9152                                     sh_compare_op1);
9153       if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4)
9154         {
9155           if (GET_MODE (operands[0]) != SImode)
9156             operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
9157
9158           switch (GET_MODE (sh_compare_op0))
9159             {
9160             case SImode:
9161               emit_insn (gen_cmpeqsi_media (operands[0],
9162                                               sh_compare_op0, sh_compare_op1));
9163               break;
9164
9165             case DImode:
9166               emit_insn (gen_cmpeqdi_media (operands[0],
9167                                               sh_compare_op0, sh_compare_op1));
9168               break;
9169
9170             case SFmode:
9171               if (! TARGET_SHMEDIA_FPU)
9172                 FAIL;
9173               emit_insn (gen_cmpeqsf_media (operands[0],
9174                                               sh_compare_op0, sh_compare_op1));
9175               break;
9176
9177             case DFmode:
9178               if (! TARGET_SHMEDIA_FPU)
9179                 FAIL;
9180               emit_insn (gen_cmpeqdf_media (operands[0],
9181                                               sh_compare_op0, sh_compare_op1));
9182               break;
9183
9184             default:
9185               FAIL;
9186             }
9187           DONE;
9188         }
9189
9190       reg = operands[0];
9191       if (GET_MODE (operands[0]) != SImode)
9192         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9193                              : gen_reg_rtx (SImode);
9194
9195       switch (GET_MODE (sh_compare_op0))
9196         {
9197         case SImode:
9198           emit_insn (gen_cmpeqsi_media (reg,
9199                                         sh_compare_op0, sh_compare_op1));
9200           break;
9201
9202         case DImode:
9203           emit_insn (gen_cmpeqdi_media (reg,
9204                                         sh_compare_op0, sh_compare_op1));
9205           break;
9206
9207         case SFmode:
9208           if (! TARGET_SHMEDIA_FPU)
9209             FAIL;
9210           emit_insn (gen_cmpeqsf_media (reg,
9211                                         sh_compare_op0, sh_compare_op1));
9212           break;
9213
9214         case DFmode:
9215           if (! TARGET_SHMEDIA_FPU)
9216             FAIL;
9217           emit_insn (gen_cmpeqdf_media (reg,
9218                                         sh_compare_op0, sh_compare_op1));
9219           break;
9220
9221         default:
9222           FAIL;
9223         }
9224
9225       if (GET_MODE (operands[0]) == DImode)
9226         emit_insn (gen_extendsidi2 (operands[0], reg));
9227
9228       DONE;
9229     }
9230   if (sh_expand_t_scc (EQ, operands[0]))
9231     DONE;
9232   if (! currently_expanding_to_rtl)
9233     FAIL;
9234   operands[1] = prepare_scc_operands (EQ);
9235 }")
9236
9237 (define_expand "slt"
9238   [(set (match_operand:SI 0 "arith_reg_operand" "")
9239         (match_dup 1))]
9240   ""
9241   "
9242 {
9243   if (TARGET_SHMEDIA)
9244     {
9245       rtx reg;
9246
9247       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9248       if (sh_compare_op1 != const0_rtx)
9249         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9250                                     ? GET_MODE (sh_compare_op0)
9251                                     : GET_MODE (sh_compare_op1),
9252                                     sh_compare_op1);
9253
9254       reg = operands[0];
9255       if (GET_MODE (operands[0]) != SImode)
9256         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9257                              : gen_reg_rtx (SImode);
9258
9259       switch (GET_MODE (sh_compare_op0))
9260         {
9261         case SImode:
9262           emit_insn (gen_cmpgtsi_media (reg,
9263                                         sh_compare_op1, sh_compare_op0));
9264           break;
9265
9266         case DImode:
9267           emit_insn (gen_cmpgtdi_media (reg,
9268                                         sh_compare_op1, sh_compare_op0));
9269           break;
9270
9271         case SFmode:
9272           if (! TARGET_SHMEDIA_FPU)
9273             FAIL;
9274           emit_insn (gen_cmpgtsf_media (reg,
9275                                         sh_compare_op1, sh_compare_op0));
9276           break;
9277
9278         case DFmode:
9279           if (! TARGET_SHMEDIA_FPU)
9280             FAIL;
9281           emit_insn (gen_cmpgtdf_media (reg,
9282                                         sh_compare_op1, sh_compare_op0));
9283           break;
9284
9285         default:
9286           FAIL;
9287         }
9288
9289       if (GET_MODE (operands[0]) == DImode)
9290         emit_insn (gen_extendsidi2 (operands[0], reg));
9291
9292       DONE;
9293     }
9294   if (! currently_expanding_to_rtl)
9295     FAIL;
9296   operands[1] = prepare_scc_operands (LT);
9297 }")
9298
9299 (define_expand "sle"
9300   [(match_operand:SI 0 "arith_reg_operand" "")]
9301   ""
9302   "
9303 {
9304   rtx tmp = sh_compare_op0;
9305
9306   if (TARGET_SHMEDIA)
9307     {
9308       rtx reg;
9309
9310       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9311       if (sh_compare_op1 != const0_rtx)
9312         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9313                                     ? GET_MODE (sh_compare_op0)
9314                                     : GET_MODE (sh_compare_op1),
9315                                     sh_compare_op1);
9316
9317       reg = operands[0];
9318       if (GET_MODE (operands[0]) != SImode)
9319         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9320                              : gen_reg_rtx (SImode);
9321
9322       switch (GET_MODE (sh_compare_op0))
9323         {
9324         case SImode:
9325           {
9326             tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9327
9328             emit_insn (gen_cmpgtsi_media (tmp,
9329                                           sh_compare_op0, sh_compare_op1));
9330             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9331             break;
9332           }
9333
9334         case DImode:
9335           {
9336             tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9337
9338             emit_insn (gen_cmpgtdi_media (tmp,
9339                                           sh_compare_op0, sh_compare_op1));
9340             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9341             break;
9342           }
9343
9344         case SFmode:
9345           if (! TARGET_SHMEDIA_FPU)
9346             FAIL;
9347           emit_insn (gen_cmpgesf_media (reg,
9348                                         sh_compare_op1, sh_compare_op0));
9349           break;
9350
9351         case DFmode:
9352           if (! TARGET_SHMEDIA_FPU)
9353             FAIL;
9354           emit_insn (gen_cmpgedf_media (reg,
9355                                         sh_compare_op1, sh_compare_op0));
9356           break;
9357
9358         default:
9359           FAIL;
9360         }
9361
9362       if (GET_MODE (operands[0]) == DImode)
9363         emit_insn (gen_extendsidi2 (operands[0], reg));
9364
9365       DONE;
9366     }
9367
9368   sh_compare_op0 = sh_compare_op1;
9369   sh_compare_op1 = tmp;
9370   emit_insn (gen_sge (operands[0]));
9371   DONE;
9372 }")
9373
9374 (define_expand "sgt"
9375   [(set (match_operand:SI 0 "arith_reg_operand" "")
9376         (match_dup 1))]
9377   ""
9378   "
9379 {
9380   if (TARGET_SHMEDIA)
9381     {
9382       rtx reg;
9383
9384       reg = operands[0];
9385       if (GET_MODE (operands[0]) != SImode)
9386         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9387                              : gen_reg_rtx (SImode);
9388       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9389       if (sh_compare_op1 != const0_rtx)
9390         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9391                                     ? GET_MODE (sh_compare_op0)
9392                                     : GET_MODE (sh_compare_op1),
9393                                     sh_compare_op1);
9394
9395       switch (GET_MODE (sh_compare_op0))
9396         {
9397         case SImode:
9398           emit_insn (gen_cmpgtsi_media (reg,
9399                                         sh_compare_op0, sh_compare_op1));
9400           break;
9401
9402         case DImode:
9403           emit_insn (gen_cmpgtdi_media (reg,
9404                                         sh_compare_op0, sh_compare_op1));
9405           break;
9406
9407         case SFmode:
9408           if (! TARGET_SHMEDIA_FPU)
9409             FAIL;
9410           emit_insn (gen_cmpgtsf_media (reg,
9411                                         sh_compare_op0, sh_compare_op1));
9412           break;
9413
9414         case DFmode:
9415           if (! TARGET_SHMEDIA_FPU)
9416             FAIL;
9417           emit_insn (gen_cmpgtdf_media (reg,
9418                                         sh_compare_op0, sh_compare_op1));
9419           break;
9420
9421         default:
9422           FAIL;
9423         }
9424
9425       if (GET_MODE (operands[0]) == DImode)
9426         emit_insn (gen_extendsidi2 (operands[0], reg));
9427
9428       DONE;
9429     }
9430   if (! currently_expanding_to_rtl)
9431     FAIL;
9432   operands[1] = prepare_scc_operands (GT);
9433 }")
9434
9435 (define_expand "sge"
9436   [(set (match_operand:SI 0 "arith_reg_operand" "")
9437         (match_dup 1))]
9438   ""
9439   "
9440 {
9441   if (TARGET_SHMEDIA)
9442     {
9443       rtx reg;
9444       enum machine_mode mode = GET_MODE (sh_compare_op0);
9445
9446       if ((mode) == VOIDmode)
9447         mode = GET_MODE (sh_compare_op1);
9448       reg = operands[0];
9449       if (GET_MODE (operands[0]) != SImode)
9450         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9451                              : gen_reg_rtx (SImode);
9452       sh_compare_op0 = force_reg (mode, sh_compare_op0);
9453       if (sh_compare_op1 != const0_rtx)
9454         sh_compare_op1 = force_reg (mode, sh_compare_op1);
9455
9456       switch (mode)
9457         {
9458         case SImode:
9459           {
9460             rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9461
9462             emit_insn (gen_cmpgtsi_media (tmp,
9463                                           sh_compare_op1, sh_compare_op0));
9464             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9465             break;
9466           }
9467
9468         case DImode:
9469           {
9470             rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9471
9472             emit_insn (gen_cmpgtdi_media (tmp,
9473                                           sh_compare_op1, sh_compare_op0));
9474             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9475             break;
9476           }
9477
9478         case SFmode:
9479           if (! TARGET_SHMEDIA_FPU)
9480             FAIL;
9481           emit_insn (gen_cmpgesf_media (reg,
9482                                         sh_compare_op0, sh_compare_op1));
9483           break;
9484
9485         case DFmode:
9486           if (! TARGET_SHMEDIA_FPU)
9487             FAIL;
9488           emit_insn (gen_cmpgedf_media (reg,
9489                                         sh_compare_op0, sh_compare_op1));
9490           break;
9491
9492         default:
9493           FAIL;
9494         }
9495
9496       if (GET_MODE (operands[0]) == DImode)
9497         emit_insn (gen_extendsidi2 (operands[0], reg));
9498
9499       DONE;
9500     }
9501
9502   if (! currently_expanding_to_rtl)
9503     FAIL;
9504   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
9505     {
9506       if (TARGET_IEEE)
9507         {
9508           rtx lab = gen_label_rtx ();
9509           prepare_scc_operands (EQ);
9510           emit_jump_insn (gen_branch_true (lab));
9511           prepare_scc_operands (GT);
9512           emit_label (lab);
9513           emit_insn (gen_movt (operands[0]));
9514         }
9515       else
9516         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
9517       DONE;
9518     }
9519   operands[1] = prepare_scc_operands (GE);
9520 }")
9521
9522 (define_expand "sgtu"
9523   [(set (match_operand:SI 0 "arith_reg_operand" "")
9524         (match_dup 1))]
9525   ""
9526   "
9527 {
9528   if (TARGET_SHMEDIA)
9529     {
9530       rtx reg;
9531
9532       reg = operands[0];
9533       if (GET_MODE (operands[0]) == DImode)
9534         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9535                              : gen_reg_rtx (SImode);
9536       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9537       if (sh_compare_op1 != const0_rtx)
9538         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9539                                     ? GET_MODE (sh_compare_op0)
9540                                     : GET_MODE (sh_compare_op1),
9541                                     sh_compare_op1);
9542
9543       emit_insn (gen_cmpgtudi_media (reg,
9544                                      sh_compare_op0, sh_compare_op1));
9545       if (GET_MODE (operands[0]) == DImode)
9546         emit_insn (gen_extendsidi2 (operands[0], reg));
9547
9548       DONE;
9549     }
9550   if (! currently_expanding_to_rtl)
9551     FAIL;
9552   operands[1] = prepare_scc_operands (GTU);
9553 }")
9554
9555 (define_expand "sltu"
9556   [(set (match_operand:SI 0 "arith_reg_operand" "")
9557         (match_dup 1))]
9558   ""
9559   "
9560 {
9561   if (TARGET_SHMEDIA)
9562     {
9563       rtx reg;
9564
9565       reg = operands[0];
9566       if (GET_MODE (operands[0]) == DImode)
9567         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9568                              : gen_reg_rtx (SImode);
9569       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9570       if (sh_compare_op1 != const0_rtx)
9571         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9572                                     ? GET_MODE (sh_compare_op0)
9573                                     : GET_MODE (sh_compare_op1),
9574                                     sh_compare_op1);
9575
9576       emit_insn (gen_cmpgtudi_media (reg,
9577                                      sh_compare_op1, sh_compare_op0));
9578       if (GET_MODE (operands[0]) == DImode)
9579         emit_insn (gen_extendsidi2 (operands[0], reg));
9580
9581       DONE;
9582     }
9583   if (! currently_expanding_to_rtl)
9584     FAIL;
9585   operands[1] = prepare_scc_operands (LTU);
9586 }")
9587
9588 (define_expand "sleu"
9589   [(set (match_operand:SI 0 "arith_reg_operand" "")
9590         (match_dup 1))]
9591   ""
9592   "
9593 {
9594   if (TARGET_SHMEDIA)
9595     {
9596       rtx tmp, reg;
9597
9598       reg = operands[0];
9599       if (GET_MODE (operands[0]) != SImode)
9600         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9601                              : gen_reg_rtx (SImode);
9602       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9603       if (sh_compare_op1 != const0_rtx)
9604         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9605                                     ? GET_MODE (sh_compare_op0)
9606                                     : GET_MODE (sh_compare_op1),
9607                                     sh_compare_op1);
9608
9609       tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9610
9611       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
9612       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9613       if (GET_MODE (operands[0]) == DImode)
9614         emit_insn (gen_extendsidi2 (operands[0], reg));
9615
9616       DONE;
9617     }
9618   if (! currently_expanding_to_rtl)
9619     FAIL;
9620   operands[1] = prepare_scc_operands (LEU);
9621 }")
9622
9623 (define_expand "sgeu"
9624   [(set (match_operand:SI 0 "arith_reg_operand" "")
9625         (match_dup 1))]
9626   ""
9627   "
9628 {
9629   if (TARGET_SHMEDIA)
9630     {
9631       rtx tmp, reg;
9632
9633       reg = operands[0];
9634       if (GET_MODE (operands[0]) != SImode)
9635         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9636                              : gen_reg_rtx (SImode);
9637       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9638       if (sh_compare_op1 != const0_rtx)
9639         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9640                                     ? GET_MODE (sh_compare_op0)
9641                                     : GET_MODE (sh_compare_op1),
9642                                     sh_compare_op1);
9643
9644       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
9645
9646       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
9647       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9648       if (GET_MODE (operands[0]) == DImode)
9649         emit_insn (gen_extendsidi2 (operands[0], reg));
9650
9651       DONE;
9652     }
9653
9654   if (! currently_expanding_to_rtl)
9655     FAIL;
9656   operands[1] = prepare_scc_operands (GEU);
9657 }")
9658
9659 ;; sne moves the complement of the T reg to DEST like this:
9660 ;;      cmp/eq ...
9661 ;;      mov    #-1,temp
9662 ;;      negc   temp,dest
9663 ;;   This is better than xoring compare result with 1 because it does
9664 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
9665 ;;   loop.
9666
9667 (define_expand "sne"
9668   [(set (match_dup 2) (const_int -1))
9669    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
9670                    (neg:SI (plus:SI (match_dup 1)
9671                                     (match_dup 2))))
9672               (set (reg:SI T_REG)
9673                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
9674                           (const_int 0)))])]
9675   ""
9676   "
9677 {
9678   if (TARGET_SHMEDIA)
9679     {
9680       rtx tmp, reg;
9681
9682       reg = operands[0];
9683       if (GET_MODE (operands[0]) != SImode)
9684         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9685                              : gen_reg_rtx (SImode);
9686       if (! TARGET_SHMEDIA_FPU
9687           && GET_MODE (sh_compare_op0) != DImode
9688           && GET_MODE (sh_compare_op0) != SImode)
9689         FAIL;
9690
9691       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9692       if (sh_compare_op1 != const0_rtx)
9693         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9694                                     ? GET_MODE (sh_compare_op0)
9695                                     : GET_MODE (sh_compare_op1),
9696                                     sh_compare_op1);
9697
9698       tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9699
9700       emit_insn (gen_seq (tmp));
9701       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9702       if (GET_MODE (operands[0]) == DImode)
9703         emit_insn (gen_extendsidi2 (operands[0], reg));
9704
9705       DONE;
9706     }
9707
9708   if (sh_expand_t_scc (NE, operands[0]))
9709     DONE;
9710   if (! currently_expanding_to_rtl)
9711     FAIL;
9712   operands[1] = prepare_scc_operands (EQ);
9713   operands[2] = gen_reg_rtx (SImode);
9714 }")
9715
9716 (define_expand "sunordered"
9717   [(set (match_operand:SI 0 "arith_reg_operand" "")
9718         (unordered:SI (match_dup 1) (match_dup 2)))]
9719   "TARGET_SHMEDIA_FPU"
9720   "
9721 {
9722   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9723   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
9724 }")
9725
9726 ;; Use the same trick for FP sle / sge
9727
9728 ;; Apart from the constant use and the T setting, this is like movt,
9729 ;; except that it uses the logically negated value of T, i.e.
9730 ;; operand[0] := T ? 0 : 1.
9731 (define_expand "movnegt"
9732   [(set (match_dup 2) (const_int -1))
9733    (parallel [(set (match_operand 0 "" "")
9734                    (neg:SI (plus:SI (match_dup 1)
9735                                     (match_dup 2))))
9736               (set (reg:SI T_REG)
9737                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
9738                           (const_int 0)))])]
9739   "TARGET_SH1"
9740   "operands[2] = gen_reg_rtx (SImode);")
9741
9742 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
9743 ;; This prevents a regression that occurred when we switched from xor to
9744 ;; mov/neg for sne.
9745
9746 (define_split
9747   [(set (match_operand:SI 0 "arith_reg_dest" "")
9748         (plus:SI (reg:SI T_REG)
9749                  (const_int -1)))]
9750   "TARGET_SH1"
9751   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
9752    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
9753   "")
9754
9755 ;; -------------------------------------------------------------------------
9756 ;; Instructions to cope with inline literal tables
9757 ;; -------------------------------------------------------------------------
9758
9759 ; 2 byte integer in line
9760
9761 (define_insn "consttable_2"
9762  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9763                     (match_operand 1 "" "")]
9764                    UNSPECV_CONST2)]
9765  ""
9766  "*
9767 {
9768   if (operands[1] != const0_rtx)
9769     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9770   return \"\";
9771 }"
9772  [(set_attr "length" "2")
9773  (set_attr "in_delay_slot" "no")])
9774
9775 ; 4 byte integer in line
9776
9777 (define_insn "consttable_4"
9778  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9779                     (match_operand 1 "" "")]
9780                    UNSPECV_CONST4)]
9781  ""
9782  "*
9783 {
9784   if (operands[1] != const0_rtx)
9785     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9786   return \"\";
9787 }"
9788  [(set_attr "length" "4")
9789   (set_attr "in_delay_slot" "no")])
9790
9791 ; 8 byte integer in line
9792
9793 (define_insn "consttable_8"
9794  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9795                     (match_operand 1 "" "")]
9796                    UNSPECV_CONST8)]
9797  ""
9798  "*
9799 {
9800   if (operands[1] != const0_rtx)
9801     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9802   return \"\";
9803 }"
9804  [(set_attr "length" "8")
9805   (set_attr "in_delay_slot" "no")])
9806
9807 ; 4 byte floating point
9808
9809 (define_insn "consttable_sf"
9810  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9811                     (match_operand 1 "" "")]
9812                    UNSPECV_CONST4)]
9813  ""
9814  "*
9815 {
9816   if (operands[1] != const0_rtx)
9817     {
9818       REAL_VALUE_TYPE d;
9819       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9820       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9821     }
9822   return \"\";
9823 }"
9824  [(set_attr "length" "4")
9825   (set_attr "in_delay_slot" "no")])
9826
9827 ; 8 byte floating point
9828
9829 (define_insn "consttable_df"
9830  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9831                     (match_operand 1 "" "")]
9832                    UNSPECV_CONST8)]
9833  ""
9834  "*
9835 {
9836   if (operands[1] != const0_rtx)
9837     {
9838       REAL_VALUE_TYPE d;
9839       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9840       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9841     }
9842   return \"\";
9843 }"
9844  [(set_attr "length" "8")
9845   (set_attr "in_delay_slot" "no")])
9846
9847 ;; Alignment is needed for some constant tables; it may also be added for
9848 ;; Instructions at the start of loops, or after unconditional branches.
9849 ;; ??? We would get more accurate lengths if we did instruction
9850 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9851 ;; here is too conservative.
9852
9853 ; align to a two byte boundary
9854
9855 (define_expand "align_2"
9856  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9857  ""
9858  "")
9859
9860 ; align to a four byte boundary
9861 ;; align_4 and align_log are instructions for the starts of loops, or
9862 ;; after unconditional branches, which may take up extra room.
9863
9864 (define_expand "align_4"
9865  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9866  ""
9867  "")
9868
9869 ; align to a cache line boundary
9870
9871 (define_insn "align_log"
9872  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9873  ""
9874  ""
9875  [(set_attr "length" "0")
9876   (set_attr "in_delay_slot" "no")])
9877
9878 ; emitted at the end of the literal table, used to emit the
9879 ; 32bit branch labels if needed.
9880
9881 (define_insn "consttable_end"
9882   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9883   ""
9884   "* return output_jump_label_table ();"
9885   [(set_attr "in_delay_slot" "no")])
9886
9887 ; emitted at the end of the window in the literal table.
9888
9889 (define_insn "consttable_window_end"
9890   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
9891   ""
9892   ""
9893   [(set_attr "length" "0")
9894    (set_attr "in_delay_slot" "no")])
9895
9896 ;; -------------------------------------------------------------------------
9897 ;; Misc
9898 ;; -------------------------------------------------------------------------
9899
9900 ;; String/block move insn.
9901
9902 (define_expand "movmemsi"
9903   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
9904                    (mem:BLK (match_operand:BLK 1 "" "")))
9905               (use (match_operand:SI 2 "nonmemory_operand" ""))
9906               (use (match_operand:SI 3 "immediate_operand" ""))
9907               (clobber (reg:SI PR_REG))
9908               (clobber (reg:SI R4_REG))
9909               (clobber (reg:SI R5_REG))
9910               (clobber (reg:SI R0_REG))])]
9911   "TARGET_SH1 && ! TARGET_SH5"
9912   "
9913 {
9914   if(expand_block_move (operands))
9915      DONE;
9916   else FAIL;
9917 }")
9918
9919 (define_insn "block_move_real"
9920   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9921                    (mem:BLK (reg:SI R5_REG)))
9922               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9923               (clobber (reg:SI PR_REG))
9924               (clobber (reg:SI R0_REG))])]
9925   "TARGET_SH1 && ! TARGET_HARD_SH4"
9926   "jsr  @%0%#"
9927   [(set_attr "type" "sfunc")
9928    (set_attr "needs_delay_slot" "yes")])
9929
9930 (define_insn "block_lump_real"
9931   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9932                    (mem:BLK (reg:SI R5_REG)))
9933               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9934               (use (reg:SI R6_REG))
9935               (clobber (reg:SI PR_REG))
9936               (clobber (reg:SI T_REG))
9937               (clobber (reg:SI R4_REG))
9938               (clobber (reg:SI R5_REG))
9939               (clobber (reg:SI R6_REG))
9940               (clobber (reg:SI R0_REG))])]
9941   "TARGET_SH1 && ! TARGET_HARD_SH4"
9942   "jsr  @%0%#"
9943   [(set_attr "type" "sfunc")
9944    (set_attr "needs_delay_slot" "yes")])
9945
9946 (define_insn "block_move_real_i4"
9947   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9948                    (mem:BLK (reg:SI R5_REG)))
9949               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9950               (clobber (reg:SI PR_REG))
9951               (clobber (reg:SI R0_REG))
9952               (clobber (reg:SI R1_REG))
9953               (clobber (reg:SI R2_REG))])]
9954   "TARGET_HARD_SH4"
9955   "jsr  @%0%#"
9956   [(set_attr "type" "sfunc")
9957    (set_attr "needs_delay_slot" "yes")])
9958
9959 (define_insn "block_lump_real_i4"
9960   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9961                    (mem:BLK (reg:SI R5_REG)))
9962               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9963               (use (reg:SI R6_REG))
9964               (clobber (reg:SI PR_REG))
9965               (clobber (reg:SI T_REG))
9966               (clobber (reg:SI R4_REG))
9967               (clobber (reg:SI R5_REG))
9968               (clobber (reg:SI R6_REG))
9969               (clobber (reg:SI R0_REG))
9970               (clobber (reg:SI R1_REG))
9971               (clobber (reg:SI R2_REG))
9972               (clobber (reg:SI R3_REG))])]
9973   "TARGET_HARD_SH4"
9974   "jsr  @%0%#"
9975   [(set_attr "type" "sfunc")
9976    (set_attr "needs_delay_slot" "yes")])
9977 \f
9978 ;; -------------------------------------------------------------------------
9979 ;; Floating point instructions.
9980 ;; -------------------------------------------------------------------------
9981
9982 ;; ??? All patterns should have a type attribute.
9983
9984 (define_expand "movpsi"
9985   [(set (match_operand:PSI 0 "register_operand" "")
9986         (match_operand:PSI 1 "general_movsrc_operand" ""))]
9987   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9988   "")
9989
9990 ;; The c / m alternative is a fake to guide reload to load directly into
9991 ;; fpscr, since reload doesn't know how to use post-increment.
9992 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
9993 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
9994 ;; predicate after reload.
9995 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
9996 ;; like a mac -> gpr move.
9997 (define_insn "fpu_switch"
9998   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
9999         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
10000   "TARGET_SH2E
10001    && (! reload_completed
10002        || true_regnum (operands[0]) != FPSCR_REG
10003        || GET_CODE (operands[1]) != MEM
10004        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
10005   "@
10006         ! precision stays the same
10007         lds.l   %1,fpscr
10008         mov.l   %1,%0
10009         #
10010         lds     %1,fpscr
10011         mov     %1,%0
10012         mov.l   %1,%0
10013         sts     fpscr,%0
10014         sts.l   fpscr,%0"
10015   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
10016    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
10017
10018 (define_peephole2
10019   [(set (reg:PSI FPSCR_REG)
10020         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10021   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
10022   [(const_int 0)]
10023 {
10024   rtx fpscr, mem, new_insn;
10025
10026   fpscr = SET_DEST (PATTERN (curr_insn));
10027   mem = SET_SRC (PATTERN (curr_insn));
10028   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10029
10030   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10031   REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
10032   DONE;
10033 })
10034
10035 (define_split
10036   [(set (reg:PSI FPSCR_REG)
10037         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10038   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
10039    && (flag_peephole2 ? flow2_completed : reload_completed)"
10040   [(const_int 0)]
10041 {
10042   rtx fpscr, mem, new_insn;
10043
10044   fpscr = SET_DEST (PATTERN (curr_insn));
10045   mem = SET_SRC (PATTERN (curr_insn));
10046   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10047
10048   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10049   REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
10050
10051   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
10052     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
10053   DONE;
10054 })
10055
10056 ;; ??? This uses the fp unit, but has no type indicating that.
10057 ;; If we did that, this would either give a bogus latency or introduce
10058 ;; a bogus FIFO constraint.
10059 ;; Since this insn is currently only used for prologues/epilogues,
10060 ;; it is probably best to claim no function unit, which matches the
10061 ;; current setting.
10062 (define_insn "toggle_sz"
10063   [(set (reg:PSI FPSCR_REG)
10064         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
10065   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10066   "fschg"
10067   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
10068
10069 ;; There's no way we can use it today, since optimize mode switching
10070 ;; doesn't enable us to know from which mode we're switching to the
10071 ;; mode it requests, to tell whether we can use a relative mode switch
10072 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
10073 ;; memory).
10074 (define_insn "toggle_pr"
10075   [(set (reg:PSI FPSCR_REG)
10076         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
10077   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
10078   "fpchg"
10079   [(set_attr "type" "fpscr_toggle")])
10080
10081 (define_expand "addsf3"
10082   [(set (match_operand:SF 0 "arith_reg_operand" "")
10083         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
10084                  (match_operand:SF 2 "arith_reg_operand" "")))]
10085   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10086   "
10087 {
10088   if (TARGET_SH2E)
10089     {
10090       expand_sf_binop (&gen_addsf3_i, operands);
10091       DONE;
10092     }
10093 }")
10094
10095 (define_insn "*addsf3_media"
10096   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10097         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10098                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10099   "TARGET_SHMEDIA_FPU"
10100   "fadd.s       %1, %2, %0"
10101   [(set_attr "type" "fparith_media")])
10102
10103 (define_insn_and_split "unary_sf_op"
10104   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10105         (vec_select:V2SF
10106          (vec_concat:V2SF
10107           (vec_select:SF
10108            (match_dup 0)
10109            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
10110           (match_operator:SF 2 "unary_float_operator"
10111             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10112                             (parallel [(match_operand 4
10113                                         "const_int_operand" "n")]))]))
10114          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
10115   "TARGET_SHMEDIA_FPU"
10116   "#"
10117   "TARGET_SHMEDIA_FPU && reload_completed"
10118   [(set (match_dup 5) (match_dup 6))]
10119   "
10120 {
10121   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10122   rtx op1 = gen_rtx_REG (SFmode,
10123                          (true_regnum (operands[1])
10124                           + (INTVAL (operands[4]) ^ endian)));
10125
10126   operands[7] = gen_rtx_REG (SFmode,
10127                              (true_regnum (operands[0])
10128                               + (INTVAL (operands[3]) ^ endian)));
10129   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10130 }"
10131   [(set_attr "type" "fparith_media")])
10132
10133 (define_insn_and_split "binary_sf_op"
10134   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10135         (vec_select:V2SF
10136          (vec_concat:V2SF
10137           (vec_select:SF
10138            (match_dup 0)
10139            (parallel [(match_operand 7 "const_int_operand" "n")]))
10140           (match_operator:SF 3 "binary_float_operator"
10141             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10142                             (parallel [(match_operand 5
10143                                         "const_int_operand" "n")]))
10144              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10145                             (parallel [(match_operand 6
10146                                         "const_int_operand" "n")]))]))
10147          (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
10148   "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
10149   "#"
10150   "&& reload_completed"
10151   [(set (match_dup 8) (match_dup 9))]
10152   "
10153 {
10154   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10155   rtx op1 = gen_rtx_REG (SFmode,
10156                          (true_regnum (operands[1])
10157                           + (INTVAL (operands[5]) ^ endian)));
10158   rtx op2 = gen_rtx_REG (SFmode,
10159                          (true_regnum (operands[2])
10160                           + (INTVAL (operands[6]) ^ endian)));
10161
10162   operands[8] = gen_rtx_REG (SFmode,
10163                              (true_regnum (operands[0])
10164                               + (INTVAL (operands[4]) ^ endian)));
10165   operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10166 }"
10167   [(set_attr "type" "fparith_media")])
10168
10169 (define_insn "addsf3_i"
10170   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10171         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10172                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10173    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10174   "TARGET_SH2E"
10175   "fadd %2,%0"
10176   [(set_attr "type" "fp")
10177    (set_attr "fp_mode" "single")])
10178
10179 (define_expand "subsf3"
10180   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10181         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10182                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10183   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10184   "
10185 {
10186   if (TARGET_SH2E)
10187     {
10188       expand_sf_binop (&gen_subsf3_i, operands);
10189       DONE;
10190     }
10191 }")
10192
10193 (define_insn "*subsf3_media"
10194   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10195         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10196                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10197   "TARGET_SHMEDIA_FPU"
10198   "fsub.s       %1, %2, %0"
10199   [(set_attr "type" "fparith_media")])
10200
10201 (define_insn "subsf3_i"
10202   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10203         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10204                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10205    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10206   "TARGET_SH2E"
10207   "fsub %2,%0"
10208   [(set_attr "type" "fp")
10209    (set_attr "fp_mode" "single")])
10210
10211 (define_expand "mulsf3"
10212   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10213         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10214                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10215   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10216   "")
10217
10218 (define_insn "*mulsf3_media"
10219   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10220         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10221                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10222   "TARGET_SHMEDIA_FPU"
10223   "fmul.s       %1, %2, %0"
10224   [(set_attr "type" "fparith_media")])
10225
10226 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10227 ;; register in feeding fp instructions.  Thus, in order to generate fmac,
10228 ;; we start out with a mulsf pattern that does not depend on fpscr.
10229 ;; This is split after combine to introduce the dependency, in order to
10230 ;; get mode switching and scheduling right.
10231 (define_insn_and_split "mulsf3_ie"
10232   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10233         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10234                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10235   "TARGET_SH2E"
10236   "fmul %2,%0"
10237   "TARGET_SH4 || TARGET_SH2A_SINGLE"
10238   [(const_int 0)]
10239   "
10240 {
10241   emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
10242              get_fpscr_rtx ()));
10243   DONE;
10244 }"
10245   [(set_attr "type" "fp")])
10246
10247 (define_insn "mulsf3_i4"
10248   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10249         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10250                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10251    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10252   "TARGET_SH2E"
10253   "fmul %2,%0"
10254   [(set_attr "type" "fp")
10255    (set_attr "fp_mode" "single")])
10256
10257 (define_insn "mac_media"
10258   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10259         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10260                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10261                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10262   "TARGET_SHMEDIA_FPU && TARGET_FMAC"
10263   "fmac.s %1, %2, %0"
10264   [(set_attr "type" "fparith_media")])
10265
10266 (define_insn "*macsf3"
10267   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10268         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10269                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10270                  (match_operand:SF 3 "arith_reg_operand" "0")))
10271    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10272   "TARGET_SH2E && TARGET_FMAC"
10273   "fmac fr0,%2,%0"
10274   [(set_attr "type" "fp")
10275    (set_attr "fp_mode" "single")])
10276
10277 (define_expand "divsf3"
10278   [(set (match_operand:SF 0 "arith_reg_operand" "")
10279         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10280                 (match_operand:SF 2 "arith_reg_operand" "")))]
10281   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10282   "
10283 {
10284   if (TARGET_SH2E)
10285     {
10286       expand_sf_binop (&gen_divsf3_i, operands);
10287       DONE;
10288     }
10289 }")
10290
10291 (define_insn "*divsf3_media"
10292   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10293         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10294                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10295   "TARGET_SHMEDIA_FPU"
10296   "fdiv.s       %1, %2, %0"
10297   [(set_attr "type" "fdiv_media")])
10298
10299 (define_insn "divsf3_i"
10300   [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10301         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10302                  (match_operand:SF 2 "arith_reg_operand" "f")))
10303    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10304   "TARGET_SH2E"
10305   "fdiv %2,%0"
10306   [(set_attr "type" "fdiv")
10307    (set_attr "fp_mode" "single")])
10308
10309 (define_insn "floatdisf2"
10310   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10311         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10312   "TARGET_SHMEDIA_FPU"
10313   "float.qs %1, %0"
10314   [(set_attr "type" "fpconv_media")])
10315
10316 (define_expand "floatsisf2"
10317   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10318         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10319   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10320   "
10321 {
10322   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10323     {
10324       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10325       DONE;
10326     }
10327 }")
10328
10329 (define_insn "*floatsisf2_media"
10330   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10331         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10332   "TARGET_SHMEDIA_FPU"
10333   "float.ls     %1, %0"
10334   [(set_attr "type" "fpconv_media")])
10335
10336 (define_insn "floatsisf2_i4"
10337   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10338         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10339    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10340   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10341   "float        %1,%0"
10342   [(set_attr "type" "fp")
10343    (set_attr "fp_mode" "single")])
10344
10345 (define_insn "*floatsisf2_ie"
10346   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10347         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10348   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10349   "float        %1,%0"
10350   [(set_attr "type" "fp")])
10351
10352 (define_insn "fix_truncsfdi2"
10353   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10354         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10355   "TARGET_SHMEDIA_FPU"
10356   "ftrc.sq %1, %0"
10357   [(set_attr "type" "fpconv_media")])
10358
10359 (define_expand "fix_truncsfsi2"
10360   [(set (match_operand:SI 0 "fpul_operand" "=y")
10361         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10362   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10363   "
10364 {
10365   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10366     {
10367       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10368       DONE;
10369     }
10370 }")
10371
10372 (define_insn "*fix_truncsfsi2_media"
10373   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10374         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10375   "TARGET_SHMEDIA_FPU"
10376   "ftrc.sl      %1, %0"
10377   [(set_attr "type" "fpconv_media")])
10378
10379 (define_insn "fix_truncsfsi2_i4"
10380   [(set (match_operand:SI 0 "fpul_operand" "=y")
10381         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10382    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10383   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10384   "ftrc %1,%0"
10385   [(set_attr "type" "ftrc_s")
10386    (set_attr "fp_mode" "single")])
10387
10388 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
10389 ;; fix_truncsfsi2_i4.
10390 ;; (define_insn "fix_truncsfsi2_i4_2"
10391 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10392 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10393 ;;   (use (reg:PSI FPSCR_REG))
10394 ;;   (clobber (reg:SI FPUL_REG))]
10395 ;;  "TARGET_SH4"
10396 ;;  "#"
10397 ;;  [(set_attr "length" "4")
10398 ;;   (set_attr "fp_mode" "single")])
10399
10400 ;;(define_split
10401 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10402 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10403 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
10404 ;;   (clobber (reg:SI FPUL_REG))]
10405 ;;  "TARGET_SH4"
10406 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10407 ;;            (use (match_dup 2))])
10408 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
10409
10410 (define_insn "*fixsfsi"
10411   [(set (match_operand:SI 0 "fpul_operand" "=y")
10412         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10413   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10414   "ftrc %1,%0"
10415   [(set_attr "type" "fp")])
10416
10417 (define_insn "cmpgtsf_t"
10418   [(set (reg:SI T_REG)
10419         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10420                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10421   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10422   "fcmp/gt      %1,%0"
10423   [(set_attr "type" "fp_cmp")
10424    (set_attr "fp_mode" "single")])
10425
10426 (define_insn "cmpeqsf_t"
10427   [(set (reg:SI T_REG)
10428         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10429                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10430   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10431   "fcmp/eq      %1,%0"
10432   [(set_attr "type" "fp_cmp")
10433    (set_attr "fp_mode" "single")])
10434
10435 (define_insn "ieee_ccmpeqsf_t"
10436   [(set (reg:SI T_REG)
10437         (ior:SI (reg:SI T_REG)
10438                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10439                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10440   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10441   "* return output_ieee_ccmpeq (insn, operands);"
10442   [(set_attr "length" "4")])
10443
10444
10445 (define_insn "cmpgtsf_t_i4"
10446   [(set (reg:SI T_REG)
10447         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10448                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10449    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10450   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10451   "fcmp/gt      %1,%0"
10452   [(set_attr "type" "fp_cmp")
10453    (set_attr "fp_mode" "single")])
10454
10455 (define_insn "cmpeqsf_t_i4"
10456   [(set (reg:SI T_REG)
10457         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10458                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10459    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10460   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10461   "fcmp/eq      %1,%0"
10462   [(set_attr "type" "fp_cmp")
10463    (set_attr "fp_mode" "single")])
10464
10465 (define_insn "*ieee_ccmpeqsf_t_4"
10466   [(set (reg:SI T_REG)
10467         (ior:SI (reg:SI T_REG)
10468                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10469                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10470    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10471   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10472   "* return output_ieee_ccmpeq (insn, operands);"
10473   [(set_attr "length" "4")
10474    (set_attr "fp_mode" "single")])
10475
10476 (define_insn "cmpeqsf_media"
10477   [(set (match_operand:SI 0 "register_operand" "=r")
10478         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10479                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10480   "TARGET_SHMEDIA_FPU"
10481   "fcmpeq.s     %1, %2, %0"
10482   [(set_attr "type" "fcmp_media")])
10483
10484 (define_insn "cmpgtsf_media"
10485   [(set (match_operand:SI 0 "register_operand" "=r")
10486         (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10487                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10488   "TARGET_SHMEDIA_FPU"
10489   "fcmpgt.s     %1, %2, %0"
10490   [(set_attr "type" "fcmp_media")])
10491
10492 (define_insn "cmpgesf_media"
10493   [(set (match_operand:SI 0 "register_operand" "=r")
10494         (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10495                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10496   "TARGET_SHMEDIA_FPU"
10497   "fcmpge.s     %1, %2, %0"
10498   [(set_attr "type" "fcmp_media")])
10499
10500 (define_insn "cmpunsf_media"
10501   [(set (match_operand:SI 0 "register_operand" "=r")
10502         (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10503                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10504   "TARGET_SHMEDIA_FPU"
10505   "fcmpun.s     %1, %2, %0"
10506   [(set_attr "type" "fcmp_media")])
10507
10508 (define_expand "cmpsf"
10509   [(set (reg:SI T_REG)
10510         (compare (match_operand:SF 0 "arith_operand" "")
10511                  (match_operand:SF 1 "arith_operand" "")))]
10512   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10513   "
10514 {
10515   sh_compare_op0 = operands[0];
10516   sh_compare_op1 = operands[1];
10517   DONE;
10518 }")
10519
10520 (define_expand "negsf2"
10521   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10522         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10523   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10524   "
10525 {
10526   if (TARGET_SH2E)
10527     {
10528       expand_sf_unop (&gen_negsf2_i, operands);
10529       DONE;
10530     }
10531 }")
10532
10533 (define_insn "*negsf2_media"
10534   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10535         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10536   "TARGET_SHMEDIA_FPU"
10537   "fneg.s       %1, %0"
10538   [(set_attr "type" "fmove_media")])
10539
10540 (define_insn "negsf2_i"
10541   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10542         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10543    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10544   "TARGET_SH2E"
10545   "fneg %0"
10546   [(set_attr "type" "fmove")
10547    (set_attr "fp_mode" "single")])
10548
10549 (define_expand "sqrtsf2"
10550   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10551         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10552   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10553   "
10554 {
10555   if (TARGET_SH3E)
10556     {
10557       expand_sf_unop (&gen_sqrtsf2_i, operands);
10558       DONE;
10559     }
10560 }")
10561
10562 (define_insn "*sqrtsf2_media"
10563   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10564         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10565   "TARGET_SHMEDIA_FPU"
10566   "fsqrt.s      %1, %0"
10567   [(set_attr "type" "fdiv_media")])
10568
10569 (define_insn "sqrtsf2_i"
10570   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10571         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10572    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10573   "TARGET_SH3E"
10574   "fsqrt        %0"
10575   [(set_attr "type" "fdiv")
10576    (set_attr "fp_mode" "single")])
10577
10578 (define_insn "rsqrtsf2"
10579   [(set (match_operand:SF 0 "register_operand" "=f")
10580         (div:SF (match_operand:SF 1 "immediate_operand" "i")
10581                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10582    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10583   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10584    && operands[1] == CONST1_RTX (SFmode)"
10585   "fsrra        %0"
10586   [(set_attr "type" "fsrra")
10587    (set_attr "fp_mode" "single")])
10588
10589 (define_insn "fsca"
10590   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10591         (vec_concat:V2SF
10592          (unspec:SF [(mult:SF
10593                       (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10594                       (match_operand:SF 2 "immediate_operand" "i"))
10595                     ] UNSPEC_FSINA)
10596          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10597                     ] UNSPEC_FCOSA)))
10598    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10599   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10600    && operands[2] == sh_fsca_int2sf ()"
10601   "fsca fpul,%d0"
10602   [(set_attr "type" "fsca")
10603    (set_attr "fp_mode" "single")])
10604
10605 (define_expand "sinsf2"
10606   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10607         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10608                    UNSPEC_FSINA))]
10609   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10610   "
10611 {
10612   rtx scaled = gen_reg_rtx (SFmode);
10613   rtx truncated = gen_reg_rtx (SImode);
10614   rtx fsca = gen_reg_rtx (V2SFmode);
10615   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10616
10617   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10618   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10619   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10620                           get_fpscr_rtx ()));
10621   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10622   DONE;
10623 }")
10624
10625 (define_expand "cossf2"
10626   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10627         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10628                    UNSPEC_FCOSA))]
10629   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10630   "
10631 {
10632   rtx scaled = gen_reg_rtx (SFmode);
10633   rtx truncated = gen_reg_rtx (SImode);
10634   rtx fsca = gen_reg_rtx (V2SFmode);
10635   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10636
10637   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10638   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10639   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10640                           get_fpscr_rtx ()));
10641   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10642   DONE;
10643 }")
10644
10645 (define_expand "sindf2"
10646   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10647         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10648                    UNSPEC_FSINA))]
10649   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10650   "
10651 {
10652   rtx scaled = gen_reg_rtx (DFmode);
10653   rtx truncated = gen_reg_rtx (SImode);
10654   rtx fsca = gen_reg_rtx (V2SFmode);
10655   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10656   rtx sfresult = gen_reg_rtx (SFmode);
10657
10658   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10659   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10660   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10661                           get_fpscr_rtx ()));
10662   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10663   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10664   DONE;
10665 }")
10666
10667 (define_expand "cosdf2"
10668   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10669         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10670                    UNSPEC_FCOSA))]
10671   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10672   "
10673 {
10674   rtx scaled = gen_reg_rtx (DFmode);
10675   rtx truncated = gen_reg_rtx (SImode);
10676   rtx fsca = gen_reg_rtx (V2SFmode);
10677   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10678   rtx sfresult = gen_reg_rtx (SFmode);
10679
10680   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10681   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10682   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10683                           get_fpscr_rtx ()));
10684   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10685   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10686   DONE;
10687 }")
10688
10689 (define_expand "abssf2"
10690   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10691         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10692   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10693   "
10694 {
10695   if (TARGET_SH2E)
10696     {
10697       expand_sf_unop (&gen_abssf2_i, operands);
10698       DONE;
10699     }
10700 }")
10701
10702 (define_insn "*abssf2_media"
10703   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10704         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10705   "TARGET_SHMEDIA_FPU"
10706   "fabs.s       %1, %0"
10707   [(set_attr "type" "fmove_media")])
10708
10709 (define_insn "abssf2_i"
10710   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10711         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10712    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10713   "TARGET_SH2E"
10714   "fabs %0"
10715   [(set_attr "type" "fmove")
10716    (set_attr "fp_mode" "single")])
10717
10718 (define_expand "adddf3"
10719   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10720         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10721                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10722   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10723   "
10724 {
10725   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10726     {
10727       expand_df_binop (&gen_adddf3_i, operands);
10728       DONE;
10729     }
10730 }")
10731
10732 (define_insn "*adddf3_media"
10733   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10734         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10735                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10736   "TARGET_SHMEDIA_FPU"
10737   "fadd.d       %1, %2, %0"
10738   [(set_attr "type" "dfparith_media")])
10739
10740 (define_insn "adddf3_i"
10741   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10742         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10743                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10744    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10745   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10746   "fadd %2,%0"
10747   [(set_attr "type" "dfp_arith")
10748    (set_attr "fp_mode" "double")])
10749
10750 (define_expand "subdf3"
10751   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10752         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10753                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10754   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10755   "
10756 {
10757   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10758     {
10759       expand_df_binop (&gen_subdf3_i, operands);
10760       DONE;
10761     }
10762 }")
10763
10764 (define_insn "*subdf3_media"
10765   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10766         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10767                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10768   "TARGET_SHMEDIA_FPU"
10769   "fsub.d       %1, %2, %0"
10770   [(set_attr "type" "dfparith_media")])
10771
10772 (define_insn "subdf3_i"
10773   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10774         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10775                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10776    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10777   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10778   "fsub %2,%0"
10779   [(set_attr "type" "dfp_arith")
10780    (set_attr "fp_mode" "double")])
10781
10782 (define_expand "muldf3"
10783   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10784         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10785                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10786   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10787   "
10788 {
10789   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10790     {
10791       expand_df_binop (&gen_muldf3_i, operands);
10792       DONE;
10793     }
10794 }")
10795
10796 (define_insn "*muldf3_media"
10797   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10798         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10799                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10800   "TARGET_SHMEDIA_FPU"
10801   "fmul.d       %1, %2, %0"
10802   [(set_attr "type" "dfmul_media")])
10803
10804 (define_insn "muldf3_i"
10805   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10806         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10807                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10808    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10809   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10810   "fmul %2,%0"
10811   [(set_attr "type" "dfp_mul")
10812    (set_attr "fp_mode" "double")])
10813
10814 (define_expand "divdf3"
10815   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10816         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10817                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10818   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10819   "
10820 {
10821   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10822     {
10823       expand_df_binop (&gen_divdf3_i, operands);
10824       DONE;
10825     }
10826 }")
10827
10828 (define_insn "*divdf3_media"
10829   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10830         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10831                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10832   "TARGET_SHMEDIA_FPU"
10833   "fdiv.d       %1, %2, %0"
10834   [(set_attr "type" "dfdiv_media")])
10835
10836 (define_insn "divdf3_i"
10837   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10838         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10839                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10840    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10841   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10842   "fdiv %2,%0"
10843   [(set_attr "type" "dfdiv")
10844    (set_attr "fp_mode" "double")])
10845
10846 (define_insn "floatdidf2"
10847   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10848         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10849   "TARGET_SHMEDIA_FPU"
10850   "float.qd     %1, %0"
10851   [(set_attr "type" "dfpconv_media")])
10852
10853 (define_expand "floatsidf2"
10854   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10855         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
10856   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10857   "
10858 {
10859   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10860     {
10861       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10862                                       get_fpscr_rtx ()));
10863       DONE;
10864     }
10865 }")
10866
10867 (define_insn "*floatsidf2_media"
10868   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10869         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10870   "TARGET_SHMEDIA_FPU"
10871   "float.ld     %1, %0"
10872   [(set_attr "type" "dfpconv_media")])
10873
10874 (define_insn "floatsidf2_i"
10875   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10876         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
10877    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10878   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10879   "float        %1,%0"
10880   [(set_attr "type" "dfp_conv")
10881    (set_attr "fp_mode" "double")])
10882
10883 (define_insn "fix_truncdfdi2"
10884   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10885         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10886   "TARGET_SHMEDIA_FPU"
10887   "ftrc.dq      %1, %0"
10888   [(set_attr "type" "dfpconv_media")])
10889
10890 (define_expand "fix_truncdfsi2"
10891   [(set (match_operand:SI 0 "fpul_operand" "")
10892         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10893   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10894   "
10895 {
10896   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10897     {
10898       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10899                                           get_fpscr_rtx ()));
10900       DONE;
10901     }
10902 }")
10903
10904 (define_insn "*fix_truncdfsi2_media"
10905   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10906         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10907   "TARGET_SHMEDIA_FPU"
10908   "ftrc.dl      %1, %0"
10909   [(set_attr "type" "dfpconv_media")])
10910
10911 (define_insn "fix_truncdfsi2_i"
10912   [(set (match_operand:SI 0 "fpul_operand" "=y")
10913         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10914    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10915   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10916   "ftrc %1,%0"
10917   [(set_attr "type" "dfp_conv")
10918    (set_attr "dfp_comp" "no")
10919    (set_attr "fp_mode" "double")])
10920
10921 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
10922 ;; fix_truncdfsi2_i.
10923 ;; (define_insn "fix_truncdfsi2_i4"
10924 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10925 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10926 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10927 ;;    (clobber (reg:SI FPUL_REG))]
10928 ;;   "TARGET_SH4"
10929 ;;   "#"
10930 ;;   [(set_attr "length" "4")
10931 ;;    (set_attr "fp_mode" "double")])
10932 ;;
10933 ;; (define_split
10934 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10935 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10936 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10937 ;;    (clobber (reg:SI FPUL_REG))]
10938 ;;   "TARGET_SH4"
10939 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10940 ;;            (use (match_dup 2))])
10941 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
10942
10943 (define_insn "cmpgtdf_t"
10944   [(set (reg:SI T_REG)
10945         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
10946                (match_operand:DF 1 "arith_reg_operand" "f")))
10947    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10948   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10949   "fcmp/gt      %1,%0"
10950   [(set_attr "type" "dfp_cmp")
10951    (set_attr "fp_mode" "double")])
10952
10953 (define_insn "cmpeqdf_t"
10954   [(set (reg:SI T_REG)
10955         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10956                (match_operand:DF 1 "arith_reg_operand" "f")))
10957    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10958   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10959   "fcmp/eq      %1,%0"
10960   [(set_attr "type" "dfp_cmp")
10961    (set_attr "fp_mode" "double")])
10962
10963 (define_insn "*ieee_ccmpeqdf_t"
10964   [(set (reg:SI T_REG)
10965         (ior:SI (reg:SI T_REG)
10966                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10967                        (match_operand:DF 1 "arith_reg_operand" "f"))))
10968    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10969   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10970   "* return output_ieee_ccmpeq (insn, operands);"
10971   [(set_attr "length" "4")
10972    (set_attr "fp_mode" "double")])
10973
10974 (define_insn "cmpeqdf_media"
10975   [(set (match_operand:SI 0 "register_operand" "=r")
10976         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10977                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10978   "TARGET_SHMEDIA_FPU"
10979   "fcmpeq.d     %1,%2,%0"
10980   [(set_attr "type" "fcmp_media")])
10981
10982 (define_insn "cmpgtdf_media"
10983   [(set (match_operand:SI 0 "register_operand" "=r")
10984         (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10985                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10986   "TARGET_SHMEDIA_FPU"
10987   "fcmpgt.d     %1,%2,%0"
10988   [(set_attr "type" "fcmp_media")])
10989
10990 (define_insn "cmpgedf_media"
10991   [(set (match_operand:SI 0 "register_operand" "=r")
10992         (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10993                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10994   "TARGET_SHMEDIA_FPU"
10995   "fcmpge.d     %1,%2,%0"
10996   [(set_attr "type" "fcmp_media")])
10997
10998 (define_insn "cmpundf_media"
10999   [(set (match_operand:SI 0 "register_operand" "=r")
11000         (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11001                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11002   "TARGET_SHMEDIA_FPU"
11003   "fcmpun.d     %1,%2,%0"
11004   [(set_attr "type" "fcmp_media")])
11005
11006 (define_expand "cmpdf"
11007   [(set (reg:SI T_REG)
11008         (compare (match_operand:DF 0 "arith_operand" "")
11009                  (match_operand:DF 1 "arith_operand" "")))]
11010   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11011   "
11012 {
11013   sh_compare_op0 = operands[0];
11014   sh_compare_op1 = operands[1];
11015   DONE;
11016 }")
11017
11018 (define_expand "negdf2"
11019   [(set (match_operand:DF 0 "arith_reg_operand" "")
11020         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11021   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11022   "
11023 {
11024   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11025     {
11026       expand_df_unop (&gen_negdf2_i, operands);
11027       DONE;
11028     }
11029 }")
11030
11031 (define_insn "*negdf2_media"
11032   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11033         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11034   "TARGET_SHMEDIA_FPU"
11035   "fneg.d       %1, %0"
11036   [(set_attr "type" "fmove_media")])
11037
11038 (define_insn "negdf2_i"
11039   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11040         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11041    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11042   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11043   "fneg %0"
11044   [(set_attr "type" "fmove")
11045    (set_attr "fp_mode" "double")])
11046
11047 (define_expand "sqrtdf2"
11048   [(set (match_operand:DF 0 "arith_reg_operand" "")
11049         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11050   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11051   "
11052 {
11053   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11054     {
11055       expand_df_unop (&gen_sqrtdf2_i, operands);
11056       DONE;
11057     }
11058 }")
11059
11060 (define_insn "*sqrtdf2_media"
11061   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11062         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11063   "TARGET_SHMEDIA_FPU"
11064   "fsqrt.d      %1, %0"
11065   [(set_attr "type" "dfdiv_media")])
11066
11067 (define_insn "sqrtdf2_i"
11068   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11069         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11070    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11071   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11072   "fsqrt        %0"
11073   [(set_attr "type" "dfdiv")
11074    (set_attr "fp_mode" "double")])
11075
11076 (define_expand "absdf2"
11077   [(set (match_operand:DF 0 "arith_reg_operand" "")
11078         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11079   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11080   "
11081 {
11082   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11083     {
11084       expand_df_unop (&gen_absdf2_i, operands);
11085       DONE;
11086     }
11087 }")
11088
11089 (define_insn "*absdf2_media"
11090   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11091         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11092   "TARGET_SHMEDIA_FPU"
11093   "fabs.d       %1, %0"
11094   [(set_attr "type" "fmove_media")])
11095
11096 (define_insn "absdf2_i"
11097   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11098         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11099    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11100   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11101   "fabs %0"
11102   [(set_attr "type" "fmove")
11103    (set_attr "fp_mode" "double")])
11104
11105 (define_expand "extendsfdf2"
11106   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11107         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11108   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11109   "
11110 {
11111   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11112     {
11113       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11114                                         get_fpscr_rtx ()));
11115       DONE;
11116     }
11117 }")
11118
11119 (define_insn "*extendsfdf2_media"
11120   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11121         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11122   "TARGET_SHMEDIA_FPU"
11123   "fcnv.sd      %1, %0"
11124   [(set_attr "type" "dfpconv_media")])
11125
11126 (define_insn "extendsfdf2_i4"
11127   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11128         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11129    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11130   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11131   "fcnvsd  %1,%0"
11132   [(set_attr "type" "fp")
11133    (set_attr "fp_mode" "double")])
11134
11135 (define_expand "truncdfsf2"
11136   [(set (match_operand:SF 0 "fpul_operand" "")
11137         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11138   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11139   "
11140 {
11141   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11142     {
11143       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11144                                        get_fpscr_rtx ()));
11145       DONE;
11146     }
11147 }")
11148
11149 (define_insn "*truncdfsf2_media"
11150   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11151         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11152   "TARGET_SHMEDIA_FPU"
11153   "fcnv.ds      %1, %0"
11154   [(set_attr "type" "dfpconv_media")])
11155
11156 (define_insn "truncdfsf2_i4"
11157   [(set (match_operand:SF 0 "fpul_operand" "=y")
11158         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11159    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11160   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11161   "fcnvds  %1,%0"
11162   [(set_attr "type" "fp")
11163    (set_attr "fp_mode" "double")])
11164 \f
11165 ;; Bit field extract patterns.  These give better code for packed bitfields,
11166 ;; because they allow auto-increment addresses to be generated.
11167
11168 (define_expand "insv"
11169   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11170                          (match_operand:SI 1 "immediate_operand" "")
11171                          (match_operand:SI 2 "immediate_operand" ""))
11172         (match_operand:SI 3 "general_operand" ""))]
11173   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11174   "
11175 {
11176   rtx addr_target, orig_address, shift_reg, qi_val;
11177   HOST_WIDE_INT bitsize, size, v = 0;
11178   rtx x = operands[3];
11179
11180   /* ??? expmed doesn't care for non-register predicates.  */
11181   if (! memory_operand (operands[0], VOIDmode)
11182       || ! immediate_operand (operands[1], VOIDmode)
11183       || ! immediate_operand (operands[2], VOIDmode)
11184       || ! general_operand (x, VOIDmode))
11185     FAIL;
11186   /* If this isn't a 16 / 24 / 32 bit field, or if
11187      it doesn't start on a byte boundary, then fail.  */
11188   bitsize = INTVAL (operands[1]);
11189   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11190       || (INTVAL (operands[2]) % 8) != 0)
11191     FAIL;
11192
11193   size = bitsize / 8;
11194   orig_address = XEXP (operands[0], 0);
11195   shift_reg = gen_reg_rtx (SImode);
11196   if (GET_CODE (x) == CONST_INT)
11197     {
11198       v = INTVAL (x);
11199       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11200     }
11201   else
11202     {
11203       emit_insn (gen_movsi (shift_reg, operands[3]));
11204       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11205     }
11206   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11207
11208   operands[0] = replace_equiv_address (operands[0], addr_target);
11209   emit_insn (gen_movqi (operands[0], qi_val));
11210
11211   while (size -= 1)
11212     {
11213       if (GET_CODE (x) == CONST_INT)
11214         qi_val
11215           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11216       else
11217         {
11218           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11219           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11220         }
11221       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11222       emit_insn (gen_movqi (operands[0], qi_val));
11223     }
11224
11225   DONE;
11226 }")
11227
11228 (define_insn "movua"
11229   [(set (match_operand:SI 0 "register_operand" "=z")
11230         (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
11231                    UNSPEC_MOVUA))]
11232   "TARGET_SH4A_ARCH"
11233   "movua.l      %1,%0"
11234   [(set_attr "type" "movua")])
11235
11236 ;; We shouldn't need this, but cse replaces increments with references
11237 ;; to other regs before flow has a chance to create post_inc
11238 ;; addressing modes, and only postreload's cse_move2add brings the
11239 ;; increments back to a usable form.
11240 (define_peephole2
11241   [(set (match_operand:SI 0 "register_operand" "")
11242         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11243                          (const_int 32) (const_int 0)))
11244    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11245   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11246   [(set (match_operand:SI 0 "register_operand" "")
11247         (sign_extract:SI (mem:SI (post_inc:SI
11248                                   (match_operand:SI 1 "register_operand" "")))
11249                          (const_int 32) (const_int 0)))]
11250   "")
11251
11252 (define_expand "extv"
11253   [(set (match_operand:SI 0 "register_operand" "")
11254         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11255                          (match_operand 2 "const_int_operand" "")
11256                          (match_operand 3 "const_int_operand" "")))]
11257   "TARGET_SH4A_ARCH"
11258 {
11259   if (TARGET_SH4A_ARCH
11260       && INTVAL (operands[2]) == 32
11261       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11262       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11263     {
11264       rtx src = adjust_address (operands[1], BLKmode, 0);
11265       set_mem_size (src, GEN_INT (4));
11266       emit_insn (gen_movua (operands[0], src));
11267       DONE;
11268     }
11269
11270   FAIL;
11271 })
11272
11273 (define_expand "extzv"
11274   [(set (match_operand:SI 0 "register_operand" "")
11275         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11276                          (match_operand 2 "const_int_operand" "")
11277                          (match_operand 3 "const_int_operand" "")))]
11278   "TARGET_SH4A_ARCH"
11279 {
11280   if (TARGET_SH4A_ARCH
11281       && INTVAL (operands[2]) == 32
11282       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11283       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11284     {
11285       rtx src = adjust_address (operands[1], BLKmode, 0);
11286       set_mem_size (src, GEN_INT (4));
11287       emit_insn (gen_movua (operands[0], src));
11288       DONE;
11289     }
11290
11291   FAIL;
11292 })
11293
11294 \f
11295 ;; -------------------------------------------------------------------------
11296 ;; Peepholes
11297 ;; -------------------------------------------------------------------------
11298
11299 ;; This matches cases where a stack pointer increment at the start of the
11300 ;; epilogue combines with a stack slot read loading the return value.
11301
11302 (define_peephole
11303   [(set (match_operand:SI 0 "arith_reg_operand" "")
11304         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11305    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11306   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11307   "mov.l        @%1+,%0")
11308
11309 ;; See the comment on the dt combiner pattern above.
11310
11311 (define_peephole
11312   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11313         (plus:SI (match_dup 0)
11314                  (const_int -1)))
11315    (set (reg:SI T_REG)
11316         (eq:SI (match_dup 0)
11317                (const_int 0)))]
11318   "TARGET_SH2"
11319   "dt   %0")
11320
11321 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11322 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
11323 ;; reload when the constant is too large for a reg+offset address.
11324
11325 ;; ??? We would get much better code if this was done in reload.  This would
11326 ;; require modifying find_reloads_address to recognize that if the constant
11327 ;; is out-of-range for an immediate add, then we get better code by reloading
11328 ;; the constant into a register than by reloading the sum into a register,
11329 ;; since the former is one instruction shorter if the address does not need
11330 ;; to be offsettable.  Unfortunately this does not work, because there is
11331 ;; only one register, r0, that can be used as an index register.  This register
11332 ;; is also the function return value register.  So, if we try to force reload
11333 ;; to use double-reg addresses, then we end up with some instructions that
11334 ;; need to use r0 twice.  The only way to fix this is to change the calling
11335 ;; convention so that r0 is not used to return values.
11336
11337 (define_peephole
11338   [(set (match_operand:SI 0 "register_operand" "=r")
11339         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11340    (set (mem:SI (match_dup 0))
11341         (match_operand:SI 2 "general_movsrc_operand" ""))]
11342   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11343   "mov.l        %2,@(%0,%1)")
11344
11345 (define_peephole
11346   [(set (match_operand:SI 0 "register_operand" "=r")
11347         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11348    (set (match_operand:SI 2 "general_movdst_operand" "")
11349         (mem:SI (match_dup 0)))]
11350   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11351   "mov.l        @(%0,%1),%2")
11352
11353 (define_peephole
11354   [(set (match_operand:SI 0 "register_operand" "=r")
11355         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11356    (set (mem:HI (match_dup 0))
11357         (match_operand:HI 2 "general_movsrc_operand" ""))]
11358   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11359   "mov.w        %2,@(%0,%1)")
11360
11361 (define_peephole
11362   [(set (match_operand:SI 0 "register_operand" "=r")
11363         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11364    (set (match_operand:HI 2 "general_movdst_operand" "")
11365         (mem:HI (match_dup 0)))]
11366   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11367   "mov.w        @(%0,%1),%2")
11368
11369 (define_peephole
11370   [(set (match_operand:SI 0 "register_operand" "=r")
11371         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11372    (set (mem:QI (match_dup 0))
11373         (match_operand:QI 2 "general_movsrc_operand" ""))]
11374   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11375   "mov.b        %2,@(%0,%1)")
11376
11377 (define_peephole
11378   [(set (match_operand:SI 0 "register_operand" "=r")
11379         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11380    (set (match_operand:QI 2 "general_movdst_operand" "")
11381         (mem:QI (match_dup 0)))]
11382   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11383   "mov.b        @(%0,%1),%2")
11384
11385 (define_peephole
11386   [(set (match_operand:SI 0 "register_operand" "=r")
11387         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11388    (set (mem:SF (match_dup 0))
11389         (match_operand:SF 2 "general_movsrc_operand" ""))]
11390   "TARGET_SH1 && REGNO (operands[0]) == 0
11391    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11392        || (GET_CODE (operands[2]) == SUBREG
11393            && REGNO (SUBREG_REG (operands[2])) < 16))
11394    && reg_unused_after (operands[0], insn)"
11395   "mov.l        %2,@(%0,%1)")
11396
11397 (define_peephole
11398   [(set (match_operand:SI 0 "register_operand" "=r")
11399         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11400    (set (match_operand:SF 2 "general_movdst_operand" "")
11401
11402         (mem:SF (match_dup 0)))]
11403   "TARGET_SH1 && REGNO (operands[0]) == 0
11404    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11405        || (GET_CODE (operands[2]) == SUBREG
11406            && REGNO (SUBREG_REG (operands[2])) < 16))
11407    && reg_unused_after (operands[0], insn)"
11408   "mov.l        @(%0,%1),%2")
11409
11410 (define_peephole
11411   [(set (match_operand:SI 0 "register_operand" "=r")
11412         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11413    (set (mem:SF (match_dup 0))
11414         (match_operand:SF 2 "general_movsrc_operand" ""))]
11415   "TARGET_SH2E && REGNO (operands[0]) == 0
11416    && ((GET_CODE (operands[2]) == REG
11417         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11418        || (GET_CODE (operands[2]) == SUBREG
11419            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11420    && reg_unused_after (operands[0], insn)"
11421   "fmov{.s|}    %2,@(%0,%1)")
11422
11423 (define_peephole
11424   [(set (match_operand:SI 0 "register_operand" "=r")
11425         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11426    (set (match_operand:SF 2 "general_movdst_operand" "")
11427
11428         (mem:SF (match_dup 0)))]
11429   "TARGET_SH2E && REGNO (operands[0]) == 0
11430    && ((GET_CODE (operands[2]) == REG
11431         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11432        || (GET_CODE (operands[2]) == SUBREG
11433            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11434    && reg_unused_after (operands[0], insn)"
11435   "fmov{.s|}    @(%0,%1),%2")
11436
11437 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
11438 (define_insn "sp_switch_1"
11439   [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11440   "TARGET_SH1"
11441   "*
11442 {
11443   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11444   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11445   return \"mov r0,r15\";
11446 }"
11447   [(set_attr "length" "10")])
11448
11449 ;; Switch back to the original stack for interrupt functions with the
11450 ;; sp_switch attribute.  */
11451 (define_insn "sp_switch_2"
11452   [(const_int 2)]
11453   "TARGET_SH1"
11454   "mov.l @r15+,r15\;mov.l @r15+,r0"
11455   [(set_attr "length" "4")])
11456
11457 ;; Integer vector moves
11458
11459 (define_expand "movv8qi"
11460   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11461         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11462   "TARGET_SHMEDIA"
11463   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11464
11465 (define_insn "movv8qi_i"
11466   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11467         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11468   "TARGET_SHMEDIA
11469    && (register_operand (operands[0], V8QImode)
11470        || sh_register_operand (operands[1], V8QImode))"
11471   "@
11472         add     %1, r63, %0
11473         movi    %1, %0
11474         #
11475         ld%M1.q %m1, %0
11476         st%M0.q %m0, %N1"
11477   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11478    (set_attr "length" "4,4,16,4,4")])
11479
11480 (define_split
11481   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11482         (subreg:V8QI (const_int 0) 0))]
11483   "TARGET_SHMEDIA"
11484   [(set (match_dup 0)
11485         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11486                             (const_int 0) (const_int 0) (const_int 0)
11487                             (const_int 0) (const_int 0)]))])
11488
11489 (define_split
11490   [(set (match_operand 0 "arith_reg_dest" "")
11491         (match_operand 1 "sh_rep_vec" ""))]
11492   "TARGET_SHMEDIA && reload_completed
11493    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11494    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11495    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11496    && (XVECEXP (operands[1], 0, 0) != const0_rtx
11497        || XVECEXP (operands[1], 0, 1) != const0_rtx)
11498    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11499        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11500   [(set (match_dup 0) (match_dup 1))
11501    (match_dup 2)]
11502   "
11503 {
11504   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11505   rtx elt1 = XVECEXP (operands[1], 0, 1);
11506
11507   if (unit_size > 2)
11508     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11509   else
11510     {
11511       if (unit_size < 2)
11512         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11513       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11514     }
11515   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11516   operands[1] = XVECEXP (operands[1], 0, 0);
11517   if (unit_size < 2)
11518     {
11519       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
11520         operands[1]
11521           = GEN_INT (TARGET_LITTLE_ENDIAN
11522                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11523                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11524       else
11525         {
11526           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11527           operands[1]
11528             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11529         }
11530     }
11531 }")
11532
11533 (define_split
11534   [(set (match_operand 0 "arith_reg_dest" "")
11535         (match_operand 1 "sh_const_vec" ""))]
11536   "TARGET_SHMEDIA && reload_completed
11537    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11538    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11539   [(set (match_dup 0) (match_dup 1))]
11540   "
11541 {
11542   rtx v = operands[1];
11543   enum machine_mode new_mode
11544     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11545
11546   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11547   operands[1]
11548     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11549 }")
11550
11551 (define_expand "movv2hi"
11552   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11553         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
11554   "TARGET_SHMEDIA"
11555   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11556
11557 (define_insn "movv2hi_i"
11558   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11559         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11560   "TARGET_SHMEDIA
11561    && (register_operand (operands[0], V2HImode)
11562        || sh_register_operand (operands[1], V2HImode))"
11563   "@
11564         add.l   %1, r63, %0
11565         movi    %1, %0
11566         #
11567         ld%M1.l %m1, %0
11568         st%M0.l %m0, %N1"
11569   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11570    (set_attr "length" "4,4,16,4,4")
11571    (set (attr "highpart")
11572         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
11573                (const_string "user")]
11574               (const_string "ignore")))])
11575
11576 (define_expand "movv4hi"
11577   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11578         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
11579   "TARGET_SHMEDIA"
11580   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11581
11582 (define_insn "movv4hi_i"
11583   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11584         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11585   "TARGET_SHMEDIA
11586    && (register_operand (operands[0], V4HImode)
11587        || sh_register_operand (operands[1], V4HImode))"
11588   "@
11589         add     %1, r63, %0
11590         movi    %1, %0
11591         #
11592         ld%M1.q %m1, %0
11593         st%M0.q %m0, %N1"
11594   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11595    (set_attr "length" "4,4,16,4,4")
11596    (set_attr "highpart" "depend")])
11597
11598 (define_expand "movv2si"
11599   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11600         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
11601   "TARGET_SHMEDIA"
11602   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11603
11604 (define_insn "movv2si_i"
11605   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11606         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11607   "TARGET_SHMEDIA
11608    && (register_operand (operands[0], V2SImode)
11609        || sh_register_operand (operands[1], V2SImode))"
11610   "@
11611         add     %1, r63, %0
11612         #
11613         #
11614         ld%M1.q %m1, %0
11615         st%M0.q %m0, %N1"
11616   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11617    (set_attr "length" "4,4,16,4,4")
11618    (set_attr "highpart" "depend")])
11619
11620 ;; Multimedia Intrinsics
11621
11622 (define_insn "absv2si2"
11623   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11624         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11625   "TARGET_SHMEDIA"
11626   "mabs.l       %1, %0"
11627   [(set_attr "type" "mcmp_media")
11628    (set_attr "highpart" "depend")])
11629
11630 (define_insn "absv4hi2"
11631   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11632         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11633   "TARGET_SHMEDIA"
11634   "mabs.w       %1, %0"
11635   [(set_attr "type" "mcmp_media")
11636    (set_attr "highpart" "depend")])
11637
11638 (define_insn "addv2si3"
11639   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11640         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11641                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11642   "TARGET_SHMEDIA"
11643   "madd.l       %1, %2, %0"
11644   [(set_attr "type" "arith_media")
11645    (set_attr "highpart" "depend")])
11646
11647 (define_insn "addv4hi3"
11648   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11649         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11650                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11651   "TARGET_SHMEDIA"
11652   "madd.w       %1, %2, %0"
11653   [(set_attr "type" "arith_media")
11654    (set_attr "highpart" "depend")])
11655
11656 (define_insn_and_split "addv2hi3"
11657   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11658         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11659                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11660   "TARGET_SHMEDIA"
11661   "#"
11662   "TARGET_SHMEDIA"
11663   [(const_int 0)]
11664   "
11665 {
11666   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11667   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11668   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11669   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11670   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11671
11672   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11673   emit_insn (gen_truncdisi2 (si_dst, di_dst));
11674   DONE;
11675 }"
11676   [(set_attr "highpart" "must_split")])
11677
11678 (define_insn "ssaddv2si3"
11679   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11680         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11681                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11682   "TARGET_SHMEDIA"
11683   "madds.l      %1, %2, %0"
11684   [(set_attr "type" "mcmp_media")
11685    (set_attr "highpart" "depend")])
11686
11687 (define_insn "usaddv8qi3"
11688   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11689         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11690                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11691   "TARGET_SHMEDIA"
11692   "madds.ub     %1, %2, %0"
11693   [(set_attr "type" "mcmp_media")
11694    (set_attr "highpart" "depend")])
11695
11696 (define_insn "ssaddv4hi3"
11697   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11698         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11699                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11700   "TARGET_SHMEDIA"
11701   "madds.w      %1, %2, %0"
11702   [(set_attr "type" "mcmp_media")
11703    (set_attr "highpart" "depend")])
11704
11705 (define_insn "negcmpeqv8qi"
11706   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11707         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11708                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11709   "TARGET_SHMEDIA"
11710   "mcmpeq.b     %N1, %N2, %0"
11711   [(set_attr "type" "mcmp_media")
11712    (set_attr "highpart" "depend")])
11713
11714 (define_insn "negcmpeqv2si"
11715   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11716         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11717                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11718   "TARGET_SHMEDIA"
11719   "mcmpeq.l     %N1, %N2, %0"
11720   [(set_attr "type" "mcmp_media")
11721    (set_attr "highpart" "depend")])
11722
11723 (define_insn "negcmpeqv4hi"
11724   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11725         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11726                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11727   "TARGET_SHMEDIA"
11728   "mcmpeq.w     %N1, %N2, %0"
11729   [(set_attr "type" "mcmp_media")
11730    (set_attr "highpart" "depend")])
11731
11732 (define_insn "negcmpgtuv8qi"
11733   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11734         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11735                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11736   "TARGET_SHMEDIA"
11737   "mcmpgt.ub    %N1, %N2, %0"
11738   [(set_attr "type" "mcmp_media")
11739    (set_attr "highpart" "depend")])
11740
11741 (define_insn "negcmpgtv2si"
11742   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11743         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11744                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11745   "TARGET_SHMEDIA"
11746   "mcmpgt.l     %N1, %N2, %0"
11747   [(set_attr "type" "mcmp_media")
11748    (set_attr "highpart" "depend")])
11749
11750 (define_insn "negcmpgtv4hi"
11751   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11752         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11753                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11754   "TARGET_SHMEDIA"
11755   "mcmpgt.w     %N1, %N2, %0"
11756   [(set_attr "type" "mcmp_media")
11757    (set_attr "highpart" "depend")])
11758
11759 (define_insn "mcmv"
11760   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11761         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11762                         (match_operand:DI 2 "arith_reg_operand" "r"))
11763                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
11764                         (not:DI (match_dup 2)))))]
11765   "TARGET_SHMEDIA"
11766   "mcmv %N1, %2, %0"
11767   [(set_attr "type" "arith_media")
11768    (set_attr "highpart" "depend")])
11769
11770 (define_insn "mcnvs_lw"
11771   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11772         (vec_concat:V4HI
11773          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
11774          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11775   "TARGET_SHMEDIA"
11776   "mcnvs.lw     %N1, %N2, %0"
11777   [(set_attr "type" "mcmp_media")])
11778
11779 (define_insn "mcnvs_wb"
11780   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11781         (vec_concat:V8QI
11782          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11783          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11784   "TARGET_SHMEDIA"
11785   "mcnvs.wb     %N1, %N2, %0"
11786   [(set_attr "type" "mcmp_media")])
11787
11788 (define_insn "mcnvs_wub"
11789   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11790         (vec_concat:V8QI
11791          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11792          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11793   "TARGET_SHMEDIA"
11794   "mcnvs.wub    %N1, %N2, %0"
11795   [(set_attr "type" "mcmp_media")])
11796
11797 (define_insn "mextr_rl"
11798   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11799         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11800                              (match_operand:HI 3 "mextr_bit_offset" "i"))
11801                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11802                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11803   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11804   "*
11805 {
11806   static char templ[21];
11807
11808   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
11809            (int) INTVAL (operands[3]) >> 3);
11810   return templ;
11811 }"
11812   [(set_attr "type" "arith_media")])
11813
11814 (define_insn "*mextr_lr"
11815   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11816         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11817                            (match_operand:HI 3 "mextr_bit_offset" "i"))
11818                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11819                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11820   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11821   "*
11822 {
11823   static char templ[21];
11824
11825   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
11826            (int) INTVAL (operands[4]) >> 3);
11827   return templ;
11828 }"
11829   [(set_attr "type" "arith_media")])
11830
11831 ; mextrN can be modelled with vec_select / vec_concat, but the selection
11832 ; vector then varies depending on endianness.
11833 (define_expand "mextr1"
11834   [(match_operand:DI 0 "arith_reg_dest" "")
11835    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11836    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11837   "TARGET_SHMEDIA"
11838   "
11839 {
11840   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11841                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
11842   DONE;
11843 }")
11844
11845 (define_expand "mextr2"
11846   [(match_operand:DI 0 "arith_reg_dest" "")
11847    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11848    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11849   "TARGET_SHMEDIA"
11850   "
11851 {
11852   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11853                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
11854   DONE;
11855 }")
11856
11857 (define_expand "mextr3"
11858   [(match_operand:DI 0 "arith_reg_dest" "")
11859    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11860    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11861   "TARGET_SHMEDIA"
11862   "
11863 {
11864   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11865                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
11866   DONE;
11867 }")
11868
11869 (define_expand "mextr4"
11870   [(match_operand:DI 0 "arith_reg_dest" "")
11871    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11872    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11873   "TARGET_SHMEDIA"
11874   "
11875 {
11876   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11877                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
11878   DONE;
11879 }")
11880
11881 (define_expand "mextr5"
11882   [(match_operand:DI 0 "arith_reg_dest" "")
11883    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11884    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11885   "TARGET_SHMEDIA"
11886   "
11887 {
11888   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11889                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
11890   DONE;
11891 }")
11892
11893 (define_expand "mextr6"
11894   [(match_operand:DI 0 "arith_reg_dest" "")
11895    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11896    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11897   "TARGET_SHMEDIA"
11898   "
11899 {
11900   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11901                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
11902   DONE;
11903 }")
11904
11905 (define_expand "mextr7"
11906   [(match_operand:DI 0 "arith_reg_dest" "")
11907    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11908    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11909   "TARGET_SHMEDIA"
11910   "
11911 {
11912   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11913                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
11914   DONE;
11915 }")
11916
11917 (define_expand "mmacfx_wl"
11918   [(match_operand:V2SI 0 "arith_reg_dest" "")
11919    (match_operand:V2HI 1 "extend_reg_operand" "")
11920    (match_operand:V2HI 2 "extend_reg_operand" "")
11921    (match_operand:V2SI 3 "arith_reg_operand" "")]
11922   "TARGET_SHMEDIA"
11923   "
11924 {
11925   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
11926                               operands[1], operands[2]));
11927   DONE;
11928 }")
11929
11930 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
11931 ;; is depend
11932 (define_insn "mmacfx_wl_i"
11933   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11934         (ss_plus:V2SI
11935          (match_operand:V2SI 1 "arith_reg_operand" "0")
11936          (ss_truncate:V2SI
11937           (ashift:V2DI
11938            (sign_extend:V2DI
11939             (mult:V2SI
11940              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11941              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11942            (const_int 1)))))]
11943   "TARGET_SHMEDIA"
11944   "mmacfx.wl    %2, %3, %0"
11945   [(set_attr "type" "mac_media")
11946    (set_attr "highpart" "depend")])
11947
11948 (define_expand "mmacnfx_wl"
11949   [(match_operand:V2SI 0 "arith_reg_dest" "")
11950    (match_operand:V2HI 1 "extend_reg_operand" "")
11951    (match_operand:V2HI 2 "extend_reg_operand" "")
11952    (match_operand:V2SI 3 "arith_reg_operand" "")]
11953   "TARGET_SHMEDIA"
11954   "
11955 {
11956   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
11957                                operands[1], operands[2]));
11958   DONE;
11959 }")
11960
11961 (define_insn "mmacnfx_wl_i"
11962   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11963         (ss_minus:V2SI
11964          (match_operand:V2SI 1 "arith_reg_operand" "0")
11965          (ss_truncate:V2SI
11966           (ashift:V2DI
11967            (sign_extend:V2DI
11968             (mult:V2SI
11969              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11970              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11971            (const_int 1)))))]
11972   "TARGET_SHMEDIA"
11973   "mmacnfx.wl   %2, %3, %0"
11974   [(set_attr "type" "mac_media")
11975    (set_attr "highpart" "depend")])
11976
11977 (define_insn "mulv2si3"
11978   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11979         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
11980                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11981   "TARGET_SHMEDIA"
11982   "mmul.l       %1, %2, %0"
11983   [(set_attr "type" "d2mpy_media")
11984    (set_attr "highpart" "depend")])
11985
11986 (define_insn "mulv4hi3"
11987   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11988         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
11989                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11990   "TARGET_SHMEDIA"
11991   "mmul.w       %1, %2, %0"
11992   [(set_attr "type" "dmpy_media")
11993    (set_attr "highpart" "depend")])
11994
11995 (define_insn "mmulfx_l"
11996   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11997         (ss_truncate:V2SI
11998          (ashiftrt:V2DI
11999           (mult:V2DI
12000            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12001            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
12002           (const_int 31))))]
12003   "TARGET_SHMEDIA"
12004   "mmulfx.l     %1, %2, %0"
12005   [(set_attr "type" "d2mpy_media")
12006    (set_attr "highpart" "depend")])
12007
12008 (define_insn "mmulfx_w"
12009   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12010         (ss_truncate:V4HI
12011          (ashiftrt:V4SI
12012           (mult:V4SI
12013            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12014            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12015           (const_int 15))))]
12016   "TARGET_SHMEDIA"
12017   "mmulfx.w     %1, %2, %0"
12018   [(set_attr "type" "dmpy_media")
12019    (set_attr "highpart" "depend")])
12020
12021 (define_insn "mmulfxrp_w"
12022   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12023         (ss_truncate:V4HI
12024          (ashiftrt:V4SI
12025           (plus:V4SI
12026            (mult:V4SI
12027             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12028             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12029            (const_int 16384))
12030           (const_int 15))))]
12031   "TARGET_SHMEDIA"
12032   "mmulfxrp.w   %1, %2, %0"
12033   [(set_attr "type" "dmpy_media")
12034    (set_attr "highpart" "depend")])
12035
12036
12037 (define_expand "mmulhi_wl"
12038   [(match_operand:V2SI 0 "arith_reg_dest" "")
12039    (match_operand:V4HI 1 "arith_reg_operand" "")
12040    (match_operand:V4HI 2 "arith_reg_operand" "")]
12041   "TARGET_SHMEDIA"
12042   "
12043 {
12044   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12045              (operands[0], operands[1], operands[2]));
12046   DONE;
12047 }")
12048
12049 (define_expand "mmullo_wl"
12050   [(match_operand:V2SI 0 "arith_reg_dest" "")
12051    (match_operand:V4HI 1 "arith_reg_operand" "")
12052    (match_operand:V4HI 2 "arith_reg_operand" "")]
12053   "TARGET_SHMEDIA"
12054   "
12055 {
12056   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12057              (operands[0], operands[1], operands[2]));
12058   DONE;
12059 }")
12060
12061 (define_insn "mmul23_wl"
12062   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12063         (vec_select:V2SI
12064          (mult:V4SI
12065           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12066           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12067          (parallel [(const_int 2) (const_int 3)])))]
12068   "TARGET_SHMEDIA"
12069   "* return (TARGET_LITTLE_ENDIAN
12070              ? \"mmulhi.wl      %1, %2, %0\"
12071              : \"mmullo.wl      %1, %2, %0\");"
12072   [(set_attr "type" "dmpy_media")
12073    (set (attr "highpart")
12074         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12075          (const_string "user")))])
12076
12077 (define_insn "mmul01_wl"
12078   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12079         (vec_select:V2SI
12080          (mult:V4SI
12081           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12082           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12083          (parallel [(const_int 0) (const_int 1)])))]
12084   "TARGET_SHMEDIA"
12085   "* return (TARGET_LITTLE_ENDIAN
12086              ? \"mmullo.wl      %1, %2, %0\"
12087              : \"mmulhi.wl      %1, %2, %0\");"
12088   [(set_attr "type" "dmpy_media")
12089    (set (attr "highpart")
12090         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12091          (const_string "user")))])
12092
12093
12094 (define_expand "mmulsum_wq"
12095   [(match_operand:DI 0 "arith_reg_dest" "")
12096    (match_operand:V4HI 1 "arith_reg_operand" "")
12097    (match_operand:V4HI 2 "arith_reg_operand" "")
12098    (match_operand:DI 3 "arith_reg_operand" "")]
12099   "TARGET_SHMEDIA"
12100   "
12101 {
12102   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12103                                operands[1], operands[2]));
12104   DONE;
12105 }")
12106
12107 (define_insn "mmulsum_wq_i"
12108   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12109         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12110          (plus:DI
12111           (plus:DI
12112            (vec_select:DI
12113             (mult:V4DI
12114              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12115              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12116             (parallel [(const_int 0)]))
12117            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12118                                      (sign_extend:V4DI (match_dup 3)))
12119                           (parallel [(const_int 1)])))
12120           (plus:DI
12121            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12122                                      (sign_extend:V4DI (match_dup 3)))
12123                           (parallel [(const_int 2)]))
12124            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12125                                      (sign_extend:V4DI (match_dup 3)))
12126                           (parallel [(const_int 3)]))))))]
12127   "TARGET_SHMEDIA"
12128   "mmulsum.wq   %2, %3, %0"
12129   [(set_attr "type" "mac_media")])
12130
12131 (define_expand "mperm_w"
12132   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12133    (match_operand:V4HI 1 "arith_reg_operand" "r")
12134    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12135   "TARGET_SHMEDIA"
12136   "
12137 {
12138   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12139              (operands[0], operands[1], operands[2]));
12140   DONE;
12141 }")
12142
12143 ; This use of vec_select isn't exactly correct according to rtl.texi
12144 ; (because not constant), but it seems a straightforward extension.
12145 (define_insn "mperm_w_little"
12146   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12147         (vec_select:V4HI
12148          (match_operand:V4HI 1 "arith_reg_operand" "r")
12149          (parallel
12150           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12151                             (const_int 2) (const_int 0))
12152            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12153            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12154            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12155   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12156   "mperm.w      %1, %N2, %0"
12157   [(set_attr "type" "arith_media")])
12158
12159 (define_insn "mperm_w_big"
12160   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12161         (vec_select:V4HI
12162          (match_operand:V4HI 1 "arith_reg_operand" "r")
12163          (parallel
12164           [(zero_extract:QI (not:QI (match_operand:QI 2
12165                                      "extend_reg_or_0_operand" "rZ"))
12166                             (const_int 2) (const_int 0))
12167            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12168            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12169            (zero_extract:QI (not:QI (match_dup 2))
12170                             (const_int 2) (const_int 6))])))]
12171   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12172   "mperm.w      %1, %N2, %0"
12173   [(set_attr "type" "arith_media")])
12174
12175 (define_insn "mperm_w0"
12176   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12177         (vec_duplicate:V4HI (truncate:HI (match_operand 1
12178                                           "trunc_hi_operand" "r"))))]
12179   "TARGET_SHMEDIA"
12180   "mperm.w      %1, r63, %0"
12181   [(set_attr "type" "arith_media")
12182    (set_attr "highpart" "ignore")])
12183
12184 (define_expand "msad_ubq"
12185   [(match_operand:DI 0 "arith_reg_dest" "")
12186    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12187    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12188    (match_operand:DI 3 "arith_reg_operand" "")]
12189   "TARGET_SHMEDIA"
12190   "
12191 {
12192   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12193                              operands[1], operands[2]));
12194   DONE;
12195 }")
12196
12197 (define_insn "msad_ubq_i"
12198   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12199         (plus:DI
12200          (plus:DI
12201           (plus:DI
12202            (plus:DI
12203             (match_operand:DI 1 "arith_reg_operand" "0")
12204             (abs:DI (vec_select:DI
12205                      (minus:V8DI
12206                       (zero_extend:V8DI
12207                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12208                       (zero_extend:V8DI
12209                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12210                      (parallel [(const_int 0)]))))
12211            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12212                                               (zero_extend:V8DI (match_dup 3)))
12213                                   (parallel [(const_int 1)]))))
12214           (plus:DI
12215            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12216                                               (zero_extend:V8DI (match_dup 3)))
12217                                   (parallel [(const_int 2)])))
12218            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12219                                               (zero_extend:V8DI (match_dup 3)))
12220                                   (parallel [(const_int 3)])))))
12221          (plus:DI
12222           (plus:DI
12223            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12224                                               (zero_extend:V8DI (match_dup 3)))
12225                                   (parallel [(const_int 4)])))
12226            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12227                                               (zero_extend:V8DI (match_dup 3)))
12228                                   (parallel [(const_int 5)]))))
12229           (plus:DI
12230            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12231                                               (zero_extend:V8DI (match_dup 3)))
12232                                   (parallel [(const_int 6)])))
12233            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12234                                               (zero_extend:V8DI (match_dup 3)))
12235                                   (parallel [(const_int 7)])))))))]
12236   "TARGET_SHMEDIA"
12237   "msad.ubq     %N2, %N3, %0"
12238   [(set_attr "type" "mac_media")])
12239
12240 (define_insn "mshalds_l"
12241   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12242         (ss_truncate:V2SI
12243          (ashift:V2DI
12244           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12245           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12246                   (const_int 31)))))]
12247   "TARGET_SHMEDIA"
12248   "mshalds.l    %1, %2, %0"
12249   [(set_attr "type" "mcmp_media")
12250    (set_attr "highpart" "depend")])
12251
12252 (define_insn "mshalds_w"
12253   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12254         (ss_truncate:V4HI
12255          (ashift:V4SI
12256           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12257           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12258                   (const_int 15)))))]
12259   "TARGET_SHMEDIA"
12260   "mshalds.w    %1, %2, %0"
12261   [(set_attr "type" "mcmp_media")
12262    (set_attr "highpart" "depend")])
12263
12264 (define_insn "ashrv2si3"
12265   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12266         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12267                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12268   "TARGET_SHMEDIA"
12269   "mshard.l     %1, %2, %0"
12270   [(set_attr "type" "arith_media")
12271    (set_attr "highpart" "depend")])
12272
12273 (define_insn "ashrv4hi3"
12274   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12275         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12276                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12277   "TARGET_SHMEDIA"
12278   "mshard.w     %1, %2, %0"
12279   [(set_attr "type" "arith_media")
12280    (set_attr "highpart" "depend")])
12281
12282 (define_insn "mshards_q"
12283   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12284         (ss_truncate:HI
12285          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12286                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12287   "TARGET_SHMEDIA"
12288   "mshards.q    %1, %N2, %0"
12289   [(set_attr "type" "mcmp_media")])
12290
12291 (define_expand "mshfhi_b"
12292   [(match_operand:V8QI 0 "arith_reg_dest" "")
12293    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12294    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12295   "TARGET_SHMEDIA"
12296   "
12297 {
12298   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12299              (operands[0], operands[1], operands[2]));
12300   DONE;
12301 }")
12302
12303 (define_expand "mshflo_b"
12304   [(match_operand:V8QI 0 "arith_reg_dest" "")
12305    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12306    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12307   "TARGET_SHMEDIA"
12308   "
12309 {
12310   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12311              (operands[0], operands[1], operands[2]));
12312   DONE;
12313 }")
12314
12315 (define_insn "mshf4_b"
12316   [(set
12317     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12318     (vec_select:V8QI
12319      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12320                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12321      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12322                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12323   "TARGET_SHMEDIA"
12324   "* return (TARGET_LITTLE_ENDIAN
12325              ? \"mshfhi.b       %N1, %N2, %0\"
12326              : \"mshflo.b       %N1, %N2, %0\");"
12327   [(set_attr "type" "arith_media")
12328    (set (attr "highpart")
12329         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12330          (const_string "user")))])
12331
12332 (define_insn "mshf0_b"
12333   [(set
12334     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12335     (vec_select:V8QI
12336      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12337                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12338      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12339                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12340   "TARGET_SHMEDIA"
12341   "* return (TARGET_LITTLE_ENDIAN
12342              ? \"mshflo.b       %N1, %N2, %0\"
12343              : \"mshfhi.b       %N1, %N2, %0\");"
12344   [(set_attr "type" "arith_media")
12345    (set (attr "highpart")
12346         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12347          (const_string "user")))])
12348
12349 (define_expand "mshfhi_l"
12350   [(match_operand:V2SI 0 "arith_reg_dest" "")
12351    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12352    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12353   "TARGET_SHMEDIA"
12354   "
12355 {
12356   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12357              (operands[0], operands[1], operands[2]));
12358   DONE;
12359 }")
12360
12361 (define_expand "mshflo_l"
12362   [(match_operand:V2SI 0 "arith_reg_dest" "")
12363    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12364    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12365   "TARGET_SHMEDIA"
12366   "
12367 {
12368   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12369              (operands[0], operands[1], operands[2]));
12370   DONE;
12371 }")
12372
12373 (define_insn "mshf4_l"
12374   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12375         (vec_select:V2SI
12376          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12377                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12378          (parallel [(const_int 1) (const_int 3)])))]
12379   "TARGET_SHMEDIA"
12380   "* return (TARGET_LITTLE_ENDIAN
12381              ? \"mshfhi.l       %N1, %N2, %0\"
12382              : \"mshflo.l       %N1, %N2, %0\");"
12383   [(set_attr "type" "arith_media")
12384    (set (attr "highpart")
12385         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12386          (const_string "user")))])
12387
12388 (define_insn "mshf0_l"
12389   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12390         (vec_select:V2SI
12391          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12392                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12393          (parallel [(const_int 0) (const_int 2)])))]
12394   "TARGET_SHMEDIA"
12395   "* return (TARGET_LITTLE_ENDIAN
12396              ? \"mshflo.l       %N1, %N2, %0\"
12397              : \"mshfhi.l       %N1, %N2, %0\");"
12398   [(set_attr "type" "arith_media")
12399    (set (attr "highpart")
12400         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12401          (const_string "user")))])
12402
12403 (define_expand "mshfhi_w"
12404   [(match_operand:V4HI 0 "arith_reg_dest" "")
12405    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12406    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12407   "TARGET_SHMEDIA"
12408   "
12409 {
12410   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12411              (operands[0], operands[1], operands[2]));
12412   DONE;
12413 }")
12414
12415 (define_expand "mshflo_w"
12416   [(match_operand:V4HI 0 "arith_reg_dest" "")
12417    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12418    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12419   "TARGET_SHMEDIA"
12420   "
12421 {
12422   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12423              (operands[0], operands[1], operands[2]));
12424   DONE;
12425 }")
12426
12427 (define_insn "mshf4_w"
12428   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12429         (vec_select:V4HI
12430          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12431                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12432          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12433   "TARGET_SHMEDIA"
12434   "* return (TARGET_LITTLE_ENDIAN
12435              ? \"mshfhi.w       %N1, %N2, %0\"
12436              : \"mshflo.w       %N1, %N2, %0\");"
12437   [(set_attr "type" "arith_media")
12438    (set (attr "highpart")
12439         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12440          (const_string "user")))])
12441
12442 (define_insn "mshf0_w"
12443   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12444         (vec_select:V4HI
12445          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12446                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12447          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12448   "TARGET_SHMEDIA"
12449   "* return (TARGET_LITTLE_ENDIAN
12450              ? \"mshflo.w       %N1, %N2, %0\"
12451              : \"mshfhi.w       %N1, %N2, %0\");"
12452   [(set_attr "type" "arith_media")
12453    (set (attr "highpart")
12454         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12455          (const_string "user")))])
12456
12457 (define_insn "mshflo_w_x"
12458   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12459         (vec_select:V4HI
12460          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12461                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12462          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12463   "TARGET_SHMEDIA"
12464   "mshflo.w     %N1, %N2, %0"
12465   [(set_attr "type" "arith_media")
12466    (set_attr "highpart" "ignore")])
12467
12468 /* These are useful to expand ANDs and as combiner patterns.  */
12469 (define_insn_and_split "mshfhi_l_di"
12470   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12471         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12472                              (const_int 32))
12473                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12474                         (const_int -4294967296))))]
12475   "TARGET_SHMEDIA"
12476   "@
12477         mshfhi.l        %N1, %N2, %0
12478         #"
12479   "TARGET_SHMEDIA && reload_completed
12480    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12481   [(set (match_dup 3) (match_dup 4))
12482    (set (match_dup 5) (match_dup 6))]
12483   "
12484 {
12485   operands[3] = gen_lowpart (SImode, operands[0]);
12486   operands[4] = gen_highpart (SImode, operands[1]);
12487   operands[5] = gen_highpart (SImode, operands[0]);
12488   operands[6] = gen_highpart (SImode, operands[2]);
12489 }"
12490   [(set_attr "type" "arith_media")])
12491
12492 (define_insn "*mshfhi_l_di_rev"
12493   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12494         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12495                         (const_int -4294967296))
12496                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12497                              (const_int 32))))]
12498   "TARGET_SHMEDIA"
12499   "mshfhi.l     %N2, %N1, %0"
12500   [(set_attr "type" "arith_media")])
12501
12502 (define_split
12503   [(set (match_operand:DI 0 "arith_reg_dest" "")
12504         (ior:DI (zero_extend:DI (match_operand:SI 1
12505                                               "extend_reg_or_0_operand" ""))
12506                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12507                         (const_int -4294967296))))
12508    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12509   "TARGET_SHMEDIA"
12510   [(const_int 0)]
12511   "
12512 {
12513   emit_insn (gen_ashldi3_media (operands[3],
12514                                 simplify_gen_subreg (DImode, operands[1],
12515                                                      SImode, 0),
12516                                 GEN_INT (32)));
12517   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12518   DONE;
12519 }")
12520
12521 (define_insn "mshflo_l_di"
12522   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12523         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12524                         (const_int 4294967295))
12525                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12526                            (const_int 32))))]
12527
12528   "TARGET_SHMEDIA"
12529   "mshflo.l     %N1, %N2, %0"
12530   [(set_attr "type" "arith_media")
12531    (set_attr "highpart" "ignore")])
12532
12533 (define_insn "*mshflo_l_di_rev"
12534   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12535         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12536                            (const_int 32))
12537                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12538                         (const_int 4294967295))))]
12539
12540   "TARGET_SHMEDIA"
12541   "mshflo.l     %N2, %N1, %0"
12542   [(set_attr "type" "arith_media")
12543    (set_attr "highpart" "ignore")])
12544
12545 ;; Combiner pattern for trampoline initialization.
12546 (define_insn_and_split "*double_shori"
12547   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12548         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12549                            (const_int 32))
12550                 (match_operand:DI 2 "const_int_operand" "n")))]
12551   "TARGET_SHMEDIA
12552    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12553   "#"
12554   "rtx_equal_p (operands[0], operands[1])"
12555   [(const_int 0)]
12556   "
12557 {
12558   HOST_WIDE_INT v = INTVAL (operands[2]);
12559
12560   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12561   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12562   DONE;
12563 }"
12564   [(set_attr "highpart" "ignore")])
12565
12566
12567 (define_insn "*mshflo_l_di_x"
12568   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12569         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12570                                  "rZ"))
12571                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12572                            (const_int 32))))]
12573
12574   "TARGET_SHMEDIA"
12575   "mshflo.l     %N1, %N2, %0"
12576   [(set_attr "type" "arith_media")
12577    (set_attr "highpart" "ignore")])
12578
12579 (define_insn_and_split "concat_v2sf"
12580   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12581 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12582         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12583                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12584
12585   "TARGET_SHMEDIA"
12586   "@
12587         mshflo.l        %N1, %N2, %0
12588         #
12589         #"
12590   "TARGET_SHMEDIA && reload_completed
12591    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12592   [(set (match_dup 3) (match_dup 1))
12593    (set (match_dup 4) (match_dup 2))]
12594   "
12595 {
12596   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12597   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12598 }"
12599   [(set_attr "type" "arith_media")
12600    (set_attr "highpart" "ignore")])
12601
12602 (define_insn "*mshflo_l_di_x_rev"
12603   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12604         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12605                            (const_int 32))
12606                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12607
12608   "TARGET_SHMEDIA"
12609   "mshflo.l     %N2, %N1, %0"
12610   [(set_attr "type" "arith_media")
12611    (set_attr "highpart" "ignore")])
12612
12613 (define_insn "ashlv2si3"
12614   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12615         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12616                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12617   "TARGET_SHMEDIA"
12618   "mshlld.l     %1, %2, %0"
12619   [(set_attr "type" "arith_media")
12620    (set_attr "highpart" "depend")])
12621
12622 (define_split
12623   [(set (match_operand 0 "any_register_operand" "")
12624         (match_operator 3 "shift_operator"
12625           [(match_operand 1 "any_register_operand" "")
12626            (match_operand 2 "shift_count_reg_operand" "")]))]
12627   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12628   [(set (match_dup 0) (match_dup 3))]
12629   "
12630 {
12631   rtx count = operands[2];
12632   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12633
12634   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12635          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12636          || GET_CODE (count) == TRUNCATE)
12637     count = XEXP (count, 0);
12638   inner_mode = GET_MODE (count);
12639   count = simplify_gen_subreg (outer_mode, count, inner_mode,
12640                                subreg_lowpart_offset (outer_mode, inner_mode));
12641   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12642                                 operands[1], count);
12643 }")
12644
12645 (define_insn "ashlv4hi3"
12646   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12647         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12648                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12649   "TARGET_SHMEDIA"
12650   "mshlld.w     %1, %2, %0"
12651   [(set_attr "type" "arith_media")
12652    (set_attr "highpart" "depend")])
12653
12654 (define_insn "lshrv2si3"
12655   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12656         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12657                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12658   "TARGET_SHMEDIA"
12659   "mshlrd.l     %1, %2, %0"
12660   [(set_attr "type" "arith_media")
12661    (set_attr "highpart" "depend")])
12662
12663 (define_insn "lshrv4hi3"
12664   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12665         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12666                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12667   "TARGET_SHMEDIA"
12668   "mshlrd.w     %1, %2, %0"
12669   [(set_attr "type" "arith_media")
12670    (set_attr "highpart" "depend")])
12671
12672 (define_insn "subv2si3"
12673   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12674         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12675                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12676   "TARGET_SHMEDIA"
12677   "msub.l       %N1, %2, %0"
12678   [(set_attr "type" "arith_media")
12679    (set_attr "highpart" "depend")])
12680
12681 (define_insn "subv4hi3"
12682   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12683         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12684                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12685   "TARGET_SHMEDIA"
12686   "msub.w       %N1, %2, %0"
12687   [(set_attr "type" "arith_media")
12688    (set_attr "highpart" "depend")])
12689
12690 (define_insn_and_split "subv2hi3"
12691   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12692         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12693                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
12694   "TARGET_SHMEDIA"
12695   "#"
12696   "TARGET_SHMEDIA"
12697   [(const_int 0)]
12698   "
12699 {
12700   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12701   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12702   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12703   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12704   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12705
12706   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
12707   emit_insn (gen_truncdisi2 (si_dst, di_dst));
12708   DONE;
12709 }"
12710   [(set_attr "highpart" "must_split")])
12711
12712 (define_insn "sssubv2si3"
12713   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12714         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12715                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12716   "TARGET_SHMEDIA"
12717   "msubs.l      %N1, %2, %0"
12718   [(set_attr "type" "mcmp_media")
12719    (set_attr "highpart" "depend")])
12720
12721 (define_insn "ussubv8qi3"
12722   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12723         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12724                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12725   "TARGET_SHMEDIA"
12726   "msubs.ub     %N1, %2, %0"
12727   [(set_attr "type" "mcmp_media")
12728    (set_attr "highpart" "depend")])
12729
12730 (define_insn "sssubv4hi3"
12731   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12732         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12733                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12734   "TARGET_SHMEDIA"
12735   "msubs.w      %N1, %2, %0"
12736   [(set_attr "type" "mcmp_media")
12737    (set_attr "highpart" "depend")])
12738
12739 ;; Floating Point Intrinsics
12740
12741 (define_insn "fcosa_s"
12742   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12743         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12744                    UNSPEC_FCOSA))]
12745   "TARGET_SHMEDIA"
12746   "fcosa.s      %1, %0"
12747   [(set_attr "type" "atrans_media")])
12748
12749 (define_insn "fsina_s"
12750   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12751         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12752                    UNSPEC_FSINA))]
12753   "TARGET_SHMEDIA"
12754   "fsina.s      %1, %0"
12755   [(set_attr "type" "atrans_media")])
12756
12757 (define_insn "fipr"
12758   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12759         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
12760                                                     "fp_arith_reg_operand" "f")
12761                                                    (match_operand:V4SF 2
12762                                                     "fp_arith_reg_operand" "f"))
12763                                          (parallel [(const_int 0)]))
12764                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12765                                          (parallel [(const_int 1)])))
12766                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12767                                          (parallel [(const_int 2)]))
12768                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12769                                          (parallel [(const_int 3)])))))]
12770   "TARGET_SHMEDIA"
12771   "fipr.s       %1, %2, %0"
12772   [(set_attr "type" "fparith_media")])
12773
12774 (define_insn "fsrra_s"
12775   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12776         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
12777                    UNSPEC_FSRRA))]
12778   "TARGET_SHMEDIA"
12779   "fsrra.s      %1, %0"
12780   [(set_attr "type" "atrans_media")])
12781
12782 (define_insn "ftrv"
12783   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
12784         (plus:V4SF
12785          (plus:V4SF
12786           (mult:V4SF
12787            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
12788                             (parallel [(const_int 0) (const_int 5)
12789                                        (const_int 10) (const_int 15)]))
12790            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
12791           (mult:V4SF
12792            (vec_select:V4SF (match_dup 1)
12793                             (parallel [(const_int 4) (const_int 9)
12794                                        (const_int 14) (const_int 3)]))
12795            (vec_select:V4SF (match_dup 2)
12796                             (parallel [(const_int 1) (const_int 2)
12797                                        (const_int 3) (const_int 0)]))))
12798          (plus:V4SF
12799           (mult:V4SF
12800            (vec_select:V4SF (match_dup 1)
12801                             (parallel [(const_int 8) (const_int 13)
12802                                        (const_int 2) (const_int 7)]))
12803            (vec_select:V4SF (match_dup 2)
12804                             (parallel [(const_int 2) (const_int 3)
12805                                        (const_int 0) (const_int 1)])))
12806           (mult:V4SF
12807            (vec_select:V4SF (match_dup 1)
12808                             (parallel [(const_int 12) (const_int 1)
12809                                        (const_int 6) (const_int 11)]))
12810            (vec_select:V4SF (match_dup 2)
12811                             (parallel [(const_int 3) (const_int 0)
12812                                        (const_int 1) (const_int 2)]))))))]
12813   "TARGET_SHMEDIA"
12814   "ftrv.s %1, %2, %0"
12815   [(set_attr "type" "fparith_media")])
12816
12817 (define_insn "ldhi_l"
12818   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12819         (zero_extract:SI
12820          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12821                                   (const_int 3))
12822                           (const_int -3)))
12823          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
12824          (const_int 0)))]
12825   "TARGET_SHMEDIA32"
12826   "ldhi.l       %U1, %0"
12827   [(set_attr "type" "load_media")])
12828
12829 (define_insn "ldhi_q"
12830   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12831         (zero_extract:DI
12832          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12833                                   (const_int 7))
12834                           (const_int -7)))
12835          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
12836          (const_int 0)))]
12837   "TARGET_SHMEDIA32"
12838   "ldhi.q       %U1, %0"
12839   [(set_attr "type" "load_media")])
12840
12841 (define_insn_and_split "*ldhi_q_comb0"
12842   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12843         (zero_extract:DI
12844          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12845                                             "register_operand" "r")
12846                                            (match_operand:SI 2
12847                                             "ua_offset" "I06"))
12848                                   (const_int 7))
12849                           (const_int -7)))
12850          (plus:SI (and:SI (match_dup 1) (const_int 7))
12851                   (const_int 1))
12852          (const_int 0)))]
12853   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12854   "#"
12855   ""
12856   [(pc)]
12857   "emit_insn (gen_ldhi_q (operands[0],
12858                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12859    DONE;")
12860
12861
12862 (define_insn_and_split "*ldhi_q_comb1"
12863   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12864         (zero_extract:DI
12865          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12866                                             "register_operand" "r")
12867                                            (match_operand:SI 2
12868                                             "ua_offset" "I06"))
12869                                   (const_int 7))
12870                           (const_int -7)))
12871          (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
12872                                                    "ua_offset" "I06"))
12873                           (const_int 7))
12874                   (const_int 1))
12875          (const_int 0)))]
12876   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12877    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12878   "#"
12879   ""
12880   [(pc)]
12881   "emit_insn (gen_ldhi_q (operands[0],
12882                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12883    DONE;")
12884
12885
12886 (define_insn "ldlo_l"
12887   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12888         (zero_extract:SI
12889          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12890                          (const_int -4)))
12891          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
12892          (and:SI (match_dup 1) (const_int 3))))]
12893   "TARGET_SHMEDIA32"
12894   "ldlo.l       %U1, %0"
12895   [(set_attr "type" "load_media")])
12896
12897 (define_insn "ldlo_q"
12898   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12899         (zero_extract:DI
12900          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12901                          (const_int -8)))
12902          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12903          (and:SI (match_dup 1) (const_int 7))))]
12904   "TARGET_SHMEDIA32"
12905   "ldlo.q       %U1, %0"
12906   [(set_attr "type" "load_media")])
12907
12908 (define_insn_and_split "*ldlo_q_comb0"
12909   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12910         (zero_extract:DI
12911          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12912                                   (match_operand:SI 2 "ua_offset" "I06"))
12913                          (const_int -8)))
12914          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12915          (and:SI (match_dup 1) (const_int 7))))]
12916   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12917   "#"
12918   ""
12919   [(pc)]
12920   "emit_insn (gen_ldlo_q (operands[0],
12921                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12922    DONE;")
12923
12924 (define_insn_and_split "*ldlo_q_comb1"
12925   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12926         (zero_extract:DI
12927          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12928                                   (match_operand:SI 2 "ua_offset" "I06"))
12929                          (const_int -8)))
12930          (minus:SI (const_int 8)
12931                    (and:SI (plus:SI (match_dup 1)
12932                                     (match_operand:SI 3 "ua_offset" "I06"))
12933                            (const_int 7)))
12934          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
12935   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12936    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12937   "#"
12938   ""
12939   [(pc)]
12940   "emit_insn (gen_ldlo_q (operands[0],
12941                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12942    DONE;")
12943
12944 (define_insn "sthi_l"
12945   [(set (zero_extract:SI
12946          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12947                                   (const_int 3))
12948                           (const_int -3)))
12949          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
12950          (const_int 0))
12951         (match_operand:SI 1 "arith_reg_operand" "r"))]
12952   "TARGET_SHMEDIA32"
12953   "sthi.l       %U0, %1"
12954   [(set_attr "type" "ustore_media")])
12955
12956 ;; All unaligned stores are considered to be 'narrow' because they typically
12957 ;; operate on less that a quadword, and when they operate on a full quadword,
12958 ;; the vanilla store high / store low sequence will cause a stall if not
12959 ;; scheduled apart.
12960 (define_insn "sthi_q"
12961   [(set (zero_extract:DI
12962          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12963                                   (const_int 7))
12964                           (const_int -7)))
12965          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12966          (const_int 0))
12967         (match_operand:DI 1 "arith_reg_operand" "r"))]
12968   "TARGET_SHMEDIA32"
12969   "sthi.q       %U0, %1"
12970   [(set_attr "type" "ustore_media")])
12971
12972 (define_insn_and_split "*sthi_q_comb0"
12973   [(set (zero_extract:DI
12974          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12975                                             "register_operand" "r")
12976                                            (match_operand:SI 1 "ua_offset"
12977                                             "I06"))
12978                                   (const_int 7))
12979                           (const_int -7)))
12980          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12981          (const_int 0))
12982         (match_operand:DI 2 "arith_reg_operand" "r"))]
12983   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
12984   "#"
12985   ""
12986   [(pc)]
12987   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12988                           operands[2]));
12989    DONE;")
12990
12991 (define_insn_and_split "*sthi_q_comb1"
12992   [(set (zero_extract:DI
12993          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12994                                             "register_operand" "r")
12995                                            (match_operand:SI 1 "ua_offset"
12996                                             "I06"))
12997                                   (const_int 7))
12998                           (const_int -7)))
12999          (plus:SI (and:SI (plus:SI (match_dup 0)
13000                                    (match_operand:SI 2 "ua_offset" "I06"))
13001                           (const_int 7))
13002                   (const_int 1))
13003          (const_int 0))
13004         (match_operand:DI 3 "arith_reg_operand" "r"))]
13005   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13006    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13007   "#"
13008   ""
13009   [(pc)]
13010   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13011                           operands[3]));
13012    DONE;")
13013
13014 ;; This is highpart user because the address is used as full 64 bit.
13015 (define_insn "stlo_l"
13016   [(set (zero_extract:SI
13017          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13018                          (const_int -4)))
13019          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13020          (and:SI (match_dup 0) (const_int 3)))
13021         (match_operand:SI 1 "arith_reg_operand" "r"))]
13022   "TARGET_SHMEDIA32"
13023   "stlo.l       %U0, %1"
13024   [(set_attr "type" "ustore_media")])
13025
13026 (define_insn "stlo_q"
13027   [(set (zero_extract:DI
13028          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13029                          (const_int -8)))
13030          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13031          (and:SI (match_dup 0) (const_int 7)))
13032         (match_operand:DI 1 "arith_reg_operand" "r"))]
13033   "TARGET_SHMEDIA32"
13034   "stlo.q       %U0, %1"
13035   [(set_attr "type" "ustore_media")])
13036
13037 (define_insn_and_split "*stlo_q_comb0"
13038   [(set (zero_extract:DI
13039          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13040                                   (match_operand:SI 1 "ua_offset" "I06"))
13041                          (const_int -8)))
13042          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13043          (and:SI (match_dup 0) (const_int 7)))
13044         (match_operand:DI 2 "arith_reg_operand" "r"))]
13045   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13046   "#"
13047   ""
13048   [(pc)]
13049   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13050                           operands[2]));
13051    DONE;")
13052
13053 (define_insn_and_split "*stlo_q_comb1"
13054   [(set (zero_extract:DI
13055          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13056                                   (match_operand:SI 1 "ua_offset" "I06"))
13057                          (const_int -8)))
13058          (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13059                                                   (match_operand:SI 2
13060                                                    "ua_offset" "I06"))
13061                                          (const_int 7)))
13062          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13063         (match_operand:DI 3 "arith_reg_operand" "r"))]
13064   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13065   "#"
13066   ""
13067   [(pc)]
13068   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13069                           operands[3]));
13070    DONE;")
13071
13072 (define_insn "ldhi_l64"
13073   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13074         (zero_extract:SI
13075          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13076                                   (const_int 3))
13077                           (const_int -3)))
13078          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13079          (const_int 0)))]
13080   "TARGET_SHMEDIA64"
13081   "ldhi.l       %U1, %0"
13082   [(set_attr "type" "load_media")])
13083
13084 (define_insn "ldhi_q64"
13085   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13086         (zero_extract:DI
13087          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13088                                   (const_int 7))
13089                           (const_int -7)))
13090          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13091          (const_int 0)))]
13092   "TARGET_SHMEDIA64"
13093   "ldhi.q       %U1, %0"
13094   [(set_attr "type" "load_media")])
13095
13096 (define_insn "ldlo_l64"
13097   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13098         (zero_extract:SI
13099          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13100                          (const_int -4)))
13101          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13102          (and:DI (match_dup 1) (const_int 3))))]
13103   "TARGET_SHMEDIA64"
13104   "ldlo.l       %U1, %0"
13105   [(set_attr "type" "load_media")])
13106
13107 (define_insn "ldlo_q64"
13108   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13109         (zero_extract:DI
13110          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13111                          (const_int -8)))
13112          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13113          (and:DI (match_dup 1) (const_int 7))))]
13114   "TARGET_SHMEDIA64"
13115   "ldlo.q       %U1, %0"
13116   [(set_attr "type" "load_media")])
13117
13118 (define_insn "sthi_l64"
13119   [(set (zero_extract:SI
13120          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13121                                   (const_int 3))
13122                           (const_int -3)))
13123          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13124          (const_int 0))
13125         (match_operand:SI 1 "arith_reg_operand" "r"))]
13126   "TARGET_SHMEDIA64"
13127   "sthi.l       %U0, %1"
13128   [(set_attr "type" "ustore_media")])
13129
13130 (define_insn "sthi_q64"
13131   [(set (zero_extract:DI
13132          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13133                                   (const_int 7))
13134                           (const_int -7)))
13135          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13136          (const_int 0))
13137         (match_operand:DI 1 "arith_reg_operand" "r"))]
13138   "TARGET_SHMEDIA64"
13139   "sthi.q       %U0, %1"
13140   [(set_attr "type" "ustore_media")])
13141
13142 (define_insn "stlo_l64"
13143   [(set (zero_extract:SI
13144          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13145                          (const_int -4)))
13146          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13147          (and:DI (match_dup 0) (const_int 3)))
13148         (match_operand:SI 1 "arith_reg_operand" "r"))]
13149   "TARGET_SHMEDIA64"
13150   "stlo.l       %U0, %1"
13151   [(set_attr "type" "ustore_media")])
13152
13153 (define_insn "stlo_q64"
13154   [(set (zero_extract:DI
13155          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13156                          (const_int -8)))
13157          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13158          (and:DI (match_dup 0) (const_int 7)))
13159         (match_operand:DI 1 "arith_reg_operand" "r"))]
13160   "TARGET_SHMEDIA64"
13161   "stlo.q       %U0, %1"
13162   [(set_attr "type" "ustore_media")])
13163
13164 (define_insn "nsb"
13165   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13166         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13167                    UNSPEC_NSB))]
13168   "TARGET_SHMEDIA"
13169   "nsb  %1, %0"
13170   [(set_attr "type" "arith_media")])
13171
13172 (define_insn "nsbsi"
13173   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13174         (zero_extend:SI
13175          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13176                     UNSPEC_NSB)))]
13177   "TARGET_SHMEDIA"
13178   "nsb  %1, %0"
13179   [(set_attr "type" "arith_media")])
13180
13181 (define_insn "nsbdi"
13182   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13183         (zero_extend:DI
13184          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13185                     UNSPEC_NSB)))]
13186   "TARGET_SHMEDIA"
13187   "nsb  %1, %0"
13188   [(set_attr "type" "arith_media")])
13189
13190 (define_expand "ffsdi2"
13191   [(set (match_operand:DI 0 "arith_reg_dest" "")
13192         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13193   "TARGET_SHMEDIA"
13194   "
13195 {
13196   rtx scratch = gen_reg_rtx (DImode);
13197   rtx last;
13198
13199   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13200   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13201   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13202   emit_insn (gen_nsbdi (scratch, scratch));
13203   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13204   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13205   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13206   REG_NOTES (last)
13207     = gen_rtx_EXPR_LIST (REG_EQUAL,
13208                          gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
13209   DONE;
13210 }")
13211
13212 (define_expand "ffssi2"
13213   [(set (match_operand:SI 0 "arith_reg_dest" "")
13214         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13215   "TARGET_SHMEDIA"
13216   "
13217 {
13218   rtx scratch = gen_reg_rtx (SImode);
13219   rtx discratch = gen_reg_rtx (DImode);
13220   rtx last;
13221
13222   emit_insn (gen_adddi3 (discratch,
13223                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
13224                          constm1_rtx));
13225   emit_insn (gen_andcdi3 (discratch,
13226                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
13227                           discratch));
13228   emit_insn (gen_nsbsi (scratch, discratch));
13229   last = emit_insn (gen_subsi3 (operands[0],
13230                                 force_reg (SImode, GEN_INT (63)), scratch));
13231   REG_NOTES (last)
13232     = gen_rtx_EXPR_LIST (REG_EQUAL,
13233                          gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
13234   DONE;
13235 }")
13236
13237 (define_insn "byterev"
13238   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13239         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13240                          (parallel [(const_int 7) (const_int 6) (const_int 5)
13241                                     (const_int 4) (const_int 3) (const_int 2)
13242                                     (const_int 1) (const_int 0)])))]
13243   "TARGET_SHMEDIA"
13244   "byterev      %1, %0"
13245   [(set_attr "type" "arith_media")])
13246
13247 (define_insn "*prefetch_media"
13248   [(prefetch (match_operand:QI 0 "address_operand" "p")
13249              (match_operand:SI 1 "const_int_operand" "n")
13250              (match_operand:SI 2 "const_int_operand" "n"))]
13251   "TARGET_SHMEDIA"
13252   "*
13253 {
13254   operands[0] = gen_rtx_MEM (QImode, operands[0]);
13255   output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
13256   return \"\";
13257 }"
13258   [(set_attr "type" "other")])
13259
13260 (define_insn "*prefetch_i4"
13261   [(prefetch (match_operand:SI 0 "register_operand" "r")
13262              (match_operand:SI 1 "const_int_operand" "n")
13263              (match_operand:SI 2 "const_int_operand" "n"))]
13264   "TARGET_HARD_SH4 || TARGET_SHCOMPACT"
13265   "*
13266 {
13267   return \"pref @%0\";
13268 }"
13269   [(set_attr "type" "other")])
13270
13271 (define_expand "prefetch"
13272   [(prefetch (match_operand 0 "address_operand" "p")
13273              (match_operand:SI 1 "const_int_operand" "n")
13274              (match_operand:SI 2 "const_int_operand" "n"))]
13275   "TARGET_HARD_SH4 || TARGET_SH5"
13276   "
13277 {
13278   if (GET_MODE (operands[0]) != Pmode
13279       || GET_CODE (operands[1]) != CONST_INT
13280       || GET_CODE (operands[2]) != CONST_INT)
13281     FAIL;
13282   if (! TARGET_SHMEDIA)
13283     operands[0] = force_reg (Pmode, operands[0]);
13284 }")
13285
13286 (define_insn "alloco_i"
13287   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13288         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13289   "TARGET_SHMEDIA32"
13290   "*
13291 {
13292   rtx xops[2];
13293
13294   if (GET_CODE (operands[0]) == PLUS)
13295     {
13296       xops[0] = XEXP (operands[0], 0);
13297       xops[1] = XEXP (operands[0], 1);
13298     }
13299   else
13300     {
13301       xops[0] = operands[0];
13302       xops[1] = const0_rtx;
13303     }
13304   output_asm_insn (\"alloco   %0, %1\", xops);
13305   return \"\";
13306 }"
13307   [(set_attr "type" "other")])
13308
13309 (define_split
13310   [(set (match_operand 0 "any_register_operand" "")
13311         (match_operand 1 "" ""))]
13312   "TARGET_SHMEDIA && reload_completed"
13313   [(set (match_dup 0) (match_dup 1))]
13314   "
13315 {
13316   int n_changes = 0;
13317
13318   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13319   if (!n_changes)
13320     FAIL;
13321 }")
13322
13323 ; Stack Protector Patterns
13324
13325 (define_expand "stack_protect_set"
13326   [(set (match_operand 0 "memory_operand" "")
13327         (match_operand 1 "memory_operand" ""))]
13328   ""
13329 {
13330   if (TARGET_SHMEDIA)
13331     {
13332       if (TARGET_SHMEDIA64)
13333         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13334       else
13335         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13336     }
13337   else
13338     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13339
13340   DONE;
13341 })
13342
13343 (define_insn "stack_protect_set_si"
13344   [(set (match_operand:SI 0 "memory_operand" "=m")
13345         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13346    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13347   "!TARGET_SHMEDIA"
13348   "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13349   [(set_attr "type" "other")
13350    (set_attr "length" "6")])
13351
13352 (define_insn "stack_protect_set_si_media"
13353   [(set (match_operand:SI 0 "memory_operand" "=m")
13354         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13355    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13356   "TARGET_SHMEDIA"
13357   "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13358   [(set_attr "type" "other")
13359    (set_attr "length" "12")])
13360
13361 (define_insn "stack_protect_set_di_media"
13362   [(set (match_operand:DI 0 "memory_operand" "=m")
13363         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13364    (set (match_scratch:DI 2 "=&r") (const_int 0))]
13365   "TARGET_SHMEDIA64"
13366   "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13367   [(set_attr "type" "other")
13368    (set_attr "length" "12")])
13369
13370 (define_expand "stack_protect_test"
13371   [(match_operand 0 "memory_operand" "")
13372    (match_operand 1 "memory_operand" "")
13373    (match_operand 2 "" "")]
13374   ""
13375 {
13376   if (TARGET_SHMEDIA)
13377     {
13378       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13379
13380       if (TARGET_SHMEDIA64)
13381         emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13382                                                     operands[1]));
13383       else
13384         emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13385                                                     operands[1]));
13386
13387       emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx));
13388     }
13389   else
13390     {
13391       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13392       emit_jump_insn (gen_branch_true (operands[2]));
13393     }
13394
13395   DONE;
13396 })
13397
13398 (define_insn "stack_protect_test_si"
13399   [(set (reg:SI T_REG)
13400         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13401                     (match_operand:SI 1 "memory_operand" "m")]
13402                    UNSPEC_SP_TEST))
13403   (set (match_scratch:SI 2 "=&r") (const_int 0))
13404   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13405   "!TARGET_SHMEDIA"
13406   "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13407   [(set_attr "type" "other")
13408    (set_attr "length" "10")])
13409
13410 (define_insn "stack_protect_test_si_media"
13411   [(set (match_operand:SI 0 "register_operand" "=&r")
13412         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13413                     (match_operand:SI 2 "memory_operand" "m")]
13414                    UNSPEC_SP_TEST))
13415   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13416   "TARGET_SHMEDIA"
13417   "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13418   [(set_attr "type" "other")
13419    (set_attr "length" "16")])
13420
13421 (define_insn "stack_protect_test_di_media"
13422   [(set (match_operand:DI 0 "register_operand" "=&r")
13423         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13424                     (match_operand:DI 2 "memory_operand" "m")]
13425                    UNSPEC_SP_TEST))
13426   (set (match_scratch:DI 3 "=&r") (const_int 0))]
13427   "TARGET_SHMEDIA64"
13428   "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13429   [(set_attr "type" "other")
13430    (set_attr "length" "16")])