OSDN Git Service

8b295bc85d813c6eab00c6278b355e968d72e47f
[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, 2007 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_TLSGD         20)
139   (UNSPEC_TLSLDM        21)
140   (UNSPEC_TLSIE         22)
141   (UNSPEC_DTPOFF        23)
142   (UNSPEC_GOTTPOFF      24)
143   (UNSPEC_TPOFF         25)
144   (UNSPEC_RA            26)
145   (UNSPEC_DIV_INV_M0    30)
146   (UNSPEC_DIV_INV_M1    31)
147   (UNSPEC_DIV_INV_M2    32)
148   (UNSPEC_DIV_INV_M3    33)
149   (UNSPEC_DIV_INV20     34)
150   (UNSPEC_DIV_INV_TABLE 37)
151   (UNSPEC_ASHIFTRT      35)
152   (UNSPEC_THUNK         36)
153   (UNSPEC_SP_SET        40)
154   (UNSPEC_SP_TEST       41)
155   (UNSPEC_MOVUA         42)
156
157   ;; These are used with unspec_volatile.
158   (UNSPECV_BLOCKAGE     0)
159   (UNSPECV_ALIGN        1)
160   (UNSPECV_CONST2       2)
161   (UNSPECV_CONST4       4)
162   (UNSPECV_CONST8       6)
163   (UNSPECV_WINDOW_END   10)
164   (UNSPECV_CONST_END    11)
165   (UNSPECV_EH_RETURN    12)
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 (ne (symbol_ref "prev_nonnote_insn (insn)")
424                          (const_int 0))
425                      (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
426                               (symbol_ref "INSN"))
427                           (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
428                               (symbol_ref "code_for_indirect_jump_scratch"))))
429                 (cond [(eq_attr "braf_branch_p" "yes")
430                        (const_int 6)
431                        (eq (symbol_ref "flag_pic") (const_int 0))
432                        (const_int 10)
433                        (ne (symbol_ref "TARGET_SH2") (const_int 0))
434                        (const_int 10)] (const_int 18))
435                 (eq_attr "braf_branch_p" "yes")
436                 (const_int 10)
437 ;; ??? using pc is not computed transitively.
438                 (ne (match_dup 0) (match_dup 0))
439                 (const_int 12)
440                 (ne (symbol_ref ("flag_pic")) (const_int 0))
441                 (const_int 22)
442                 ] (const_int 14))
443          (eq_attr "type" "pt_media")
444          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
445                        (const_int 20) (const_int 12))
446          (and (eq_attr "type" "jump_media")
447               (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
448          (const_int 8)
449          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
450                          (const_int 4)
451                          (const_int 2))))
452
453 ;; DFA descriptions for the pipelines
454
455 (include "sh1.md")
456 (include "shmedia.md")
457 (include "sh4.md")
458
459 (include "predicates.md")
460 (include "constraints.md")
461
462 ;; Definitions for filling delay slots
463
464 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
465
466 (define_attr "banked" "yes,no" 
467         (cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)")
468                    (const_int 1))
469                (const_string "yes")]
470               (const_string "no")))
471
472 ;; ??? This should be (nil) instead of (const_int 0)
473 (define_attr "hit_stack" "yes,no"
474         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
475                    (const_int 0))
476                (const_string "no")]
477               (const_string "yes")))
478
479 (define_attr "interrupt_function" "no,yes"
480   (const (symbol_ref "current_function_interrupt")))
481
482 (define_attr "in_delay_slot" "yes,no"
483   (cond [(eq_attr "type" "cbranch") (const_string "no")
484          (eq_attr "type" "pcload,pcload_si") (const_string "no")
485          (eq_attr "needs_delay_slot" "yes") (const_string "no")
486          (eq_attr "length" "2") (const_string "yes")
487          ] (const_string "no")))
488
489 (define_attr "cond_delay_slot" "yes,no"
490   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
491          ] (const_string "no")))
492
493 (define_attr "is_sfunc" ""
494   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
495
496 (define_attr "is_mac_media" ""
497   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
498
499 (define_attr "branch_zero" "yes,no"
500   (cond [(eq_attr "type" "!cbranch") (const_string "no")
501          (ne (symbol_ref "(next_active_insn (insn)\
502                            == (prev_active_insn\
503                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
504                           && get_attr_length (next_active_insn (insn)) == 2")
505              (const_int 0))
506          (const_string "yes")]
507         (const_string "no")))
508
509 ;; SH4 Double-precision computation with double-precision result -
510 ;; the two halves are ready at different times.
511 (define_attr "dfp_comp" "yes,no"
512   (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
513         (const_string "no")))
514
515 ;; Insns for which the latency of a preceding fp insn is decreased by one.
516 (define_attr "late_fp_use" "yes,no" (const_string "no"))
517 ;; And feeding insns for which this relevant.
518 (define_attr "any_fp_comp" "yes,no"
519   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
520          (const_string "yes")]
521         (const_string "no")))
522
523 (define_attr "any_int_load" "yes,no"
524   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
525          (const_string "yes")]
526         (const_string "no")))
527
528 (define_attr "highpart" "user, ignore, extend, depend, must_split"
529   (const_string "user"))
530
531 (define_delay
532   (eq_attr "needs_delay_slot" "yes")
533   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
534
535 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
536 ;; and thus we can't put a pop instruction in its delay slot.
537 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
538 ;; instruction can go in the delay slot.
539
540 ;; Since a normal return (rts) implicitly uses the PR register,
541 ;; we can't allow PR register loads in an rts delay slot.
542
543 (define_delay
544   (eq_attr "type" "return")
545   [(and (eq_attr "in_delay_slot" "yes")
546         (ior (and (eq_attr "interrupt_function" "no")
547                   (eq_attr "type" "!pload,prset"))
548              (and (eq_attr "interrupt_function" "yes")
549                   (ior
550                    (eq (symbol_ref "TARGET_SH3") (const_int 0))
551                    (eq_attr "hit_stack" "no")
552                    (eq_attr "banked" "no"))))) (nil) (nil)])
553
554 ;; Since a call implicitly uses the PR register, we can't allow
555 ;; a PR register store in a jsr delay slot.
556
557 (define_delay
558   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
559   [(and (eq_attr "in_delay_slot" "yes")
560         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
561
562 ;; Say that we have annulled true branches, since this gives smaller and
563 ;; faster code when branches are predicted as not taken.
564
565 ;; ??? The non-annulled condition should really be "in_delay_slot",
566 ;; but insns that can be filled in non-annulled get priority over insns
567 ;; that can only be filled in anulled.
568
569 (define_delay
570   (and (eq_attr "type" "cbranch")
571        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
572   ;; SH2e has a hardware bug that pretty much prohibits the use of
573   ;; annuled delay slots.
574   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
575                                           (not (eq_attr "cpu" "sh2e"))) (nil)])
576 \f
577 ;; -------------------------------------------------------------------------
578 ;; SImode signed integer comparisons
579 ;; -------------------------------------------------------------------------
580
581 (define_insn ""
582   [(set (reg:SI T_REG)
583         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
584                        (match_operand:SI 1 "arith_operand" "K08,r"))
585                (const_int 0)))]
586   "TARGET_SH1"
587   "tst  %1,%0"
588   [(set_attr "type" "mt_group")])
589
590 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
591 ;; That would still allow reload to create cmpi instructions, but would
592 ;; perhaps allow forcing the constant into a register when that is better.
593 ;; Probably should use r0 for mem/imm compares, but force constant into a
594 ;; register for pseudo/imm compares.
595
596 (define_insn "cmpeqsi_t"
597   [(set (reg:SI T_REG)
598         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
599                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
600   "TARGET_SH1"
601   "@
602         tst     %0,%0
603         cmp/eq  %1,%0
604         cmp/eq  %1,%0"
605    [(set_attr "type" "mt_group")])
606
607 (define_insn "cmpgtsi_t"
608   [(set (reg:SI T_REG)
609         (gt: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/gt  %1,%0
614         cmp/pl  %0"
615    [(set_attr "type" "mt_group")])
616
617 (define_insn "cmpgesi_t"
618   [(set (reg:SI T_REG)
619         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
620                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
621   "TARGET_SH1"
622   "@
623         cmp/ge  %1,%0
624         cmp/pz  %0"
625    [(set_attr "type" "mt_group")])
626
627 ;; -------------------------------------------------------------------------
628 ;; SImode compare and branch
629 ;; -------------------------------------------------------------------------
630
631 (define_expand "cbranchsi4"
632   [(set (pc)
633         (if_then_else (match_operator 0 "comparison_operator"
634                         [(match_operand:SI 1 "arith_operand" "")
635                          (match_operand:SI 2 "arith_operand" "")])
636                       (label_ref (match_operand 3 "" ""))
637                       (pc)))
638    (clobber (reg:SI T_REG))]
639   "TARGET_CBRANCHDI4"
640   "expand_cbranchsi4 (operands, CODE_FOR_nothing, -1); DONE;")
641
642 ;; -------------------------------------------------------------------------
643 ;; SImode unsigned integer comparisons
644 ;; -------------------------------------------------------------------------
645
646 (define_insn_and_split "cmpgeusi_t"
647   [(set (reg:SI T_REG)
648         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
649                 (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
650   "TARGET_SH1"
651   "cmp/hs       %1,%0"
652   "&& operands[0] == CONST0_RTX (SImode)"
653   [(pc)]
654   "
655 {
656   emit_insn (gen_sett ());
657   DONE;
658 }"
659    [(set_attr "type" "mt_group")])
660
661 (define_insn "cmpgtusi_t"
662   [(set (reg:SI T_REG)
663         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
664                 (match_operand:SI 1 "arith_reg_operand" "r")))]
665   "TARGET_SH1"
666   "cmp/hi       %1,%0"
667    [(set_attr "type" "mt_group")])
668
669 ;; We save the compare operands in the cmpxx patterns and use them when
670 ;; we generate the branch.
671
672 (define_expand "cmpsi"
673   [(set (reg:SI T_REG)
674         (compare (match_operand:SI 0 "cmpsi_operand" "")
675                  (match_operand:SI 1 "arith_operand" "")))]
676   "TARGET_SH1 || TARGET_SHMEDIA"
677   "
678 {
679   if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
680       && GET_CODE (operands[1]) != CONST_INT)
681     operands[0] = copy_to_mode_reg (SImode, operands[0]);
682   sh_compare_op0 = operands[0];
683   sh_compare_op1 = operands[1];
684   DONE;
685 }")
686 \f
687 ;; -------------------------------------------------------------------------
688 ;; DImode compare and branch
689 ;; -------------------------------------------------------------------------
690
691
692 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
693 ;; Therefore, we aim to have a set of three branches that go straight to the
694 ;; destination, i.e. only one of them is taken at any one time.
695 ;; This mechanism should also be slightly better for the sh4-200.
696
697 (define_expand "cbranchdi4"
698   [(set (pc)
699         (if_then_else (match_operator 0 "comparison_operator"
700                         [(match_operand:DI 1 "arith_operand" "")
701                          (match_operand:DI 2 "arith_operand" "")])
702                       (label_ref (match_operand 3 "" ""))
703                       (pc)))
704    (clobber (match_dup 4))
705    (clobber (reg:SI T_REG))]
706   "TARGET_CBRANCHDI4"
707   "
708 {
709   enum rtx_code comparison;
710
711   if (TARGET_EXPAND_CBRANCHDI4)
712     {
713       if (expand_cbranchdi4 (operands, CODE_FOR_nothing))
714         DONE;
715     }
716   comparison = prepare_cbranch_operands (operands, DImode, CODE_FOR_nothing);
717   if (comparison != GET_CODE (operands[0]))
718     operands[0]
719       = gen_rtx_fmt_ee (VOIDmode, comparison, operands[1], operands[2]);
720    operands[4] = gen_rtx_SCRATCH (SImode);
721 }")
722
723 (define_insn_and_split "cbranchdi4_i"
724   [(set (pc)
725         (if_then_else (match_operator 0 "comparison_operator"
726                         [(match_operand:DI 1 "arith_operand" "r,r")
727                          (match_operand:DI 2 "arith_operand" "rN,i")])
728                       (label_ref (match_operand 3 "" ""))
729                       (pc)))
730    (clobber (match_scratch:SI 4 "=X,&r"))
731    (clobber (reg:SI T_REG))]
732   "TARGET_CBRANCHDI4"
733   "#"
734   "&& reload_completed"
735   [(pc)]
736   "
737 {
738   if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
739     FAIL;
740   DONE;
741 }")
742
743 ;; -------------------------------------------------------------------------
744 ;; DImode signed integer comparisons
745 ;; -------------------------------------------------------------------------
746
747 (define_insn ""
748   [(set (reg:SI T_REG)
749         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
750                        (match_operand:DI 1 "arith_operand" "r"))
751                (const_int 0)))]
752   "TARGET_SH1"
753   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
754                                  insn, operands);"
755   [(set_attr "length" "6")
756    (set_attr "type" "arith3b")])
757
758 (define_insn "cmpeqdi_t"
759   [(set (reg:SI T_REG)
760         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
761                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
762   "TARGET_SH1"
763   "@
764         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
765         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
766   [(set_attr "length" "6")
767    (set_attr "type" "arith3b")])
768
769 (define_split
770   [(set (reg:SI T_REG)
771         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
772                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
773 ;; If we applied this split when not optimizing, it would only be
774 ;; applied during the machine-dependent reorg, when no new basic blocks
775 ;; may be created.
776   "TARGET_SH1 && reload_completed && optimize"
777   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
778    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
779                            (label_ref (match_dup 6))
780                            (pc)))
781    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
782    (match_dup 6)]
783   "
784 {
785   operands[2]
786     = gen_rtx_REG (SImode,
787                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
788   operands[3]
789     = (operands[1] == const0_rtx
790        ? const0_rtx
791        : gen_rtx_REG (SImode,
792                       true_regnum (operands[1])
793                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
794   operands[4] = gen_lowpart (SImode, operands[0]);
795   operands[5] = gen_lowpart (SImode, operands[1]);
796   operands[6] = gen_label_rtx ();
797 }")
798
799 (define_insn "cmpgtdi_t"
800   [(set (reg:SI T_REG)
801         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
802                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
803   "TARGET_SH2"
804   "@
805         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
806         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
807   [(set_attr "length" "8")
808    (set_attr "type" "arith3")])
809
810 (define_insn "cmpgedi_t"
811   [(set (reg:SI T_REG)
812         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
813                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
814   "TARGET_SH2"
815   "@
816         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
817         cmp/pz\\t%S0"
818   [(set_attr "length" "8,2")
819    (set_attr "type" "arith3,mt_group")])
820 \f
821 ;; -------------------------------------------------------------------------
822 ;; DImode unsigned integer comparisons
823 ;; -------------------------------------------------------------------------
824
825 (define_insn "cmpgeudi_t"
826   [(set (reg:SI T_REG)
827         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
828                 (match_operand:DI 1 "arith_reg_operand" "r")))]
829   "TARGET_SH2"
830   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
831   [(set_attr "length" "8")
832    (set_attr "type" "arith3")])
833
834 (define_insn "cmpgtudi_t"
835   [(set (reg:SI T_REG)
836         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
837                 (match_operand:DI 1 "arith_reg_operand" "r")))]
838   "TARGET_SH2"
839   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
840   [(set_attr "length" "8")
841    (set_attr "type" "arith3")])
842
843 (define_insn "cmpeqsi_media"
844   [(set (match_operand:SI 0 "register_operand" "=r")
845         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
846                (match_operand:SI 2 "cmp_operand" "Nr")))]
847   "TARGET_SHMEDIA"
848   "cmpeq        %1, %N2, %0"
849   [(set_attr "type" "cmp_media")])
850
851 (define_insn "cmpeqdi_media"
852   [(set (match_operand:SI 0 "register_operand" "=r")
853         (eq:SI (match_operand:DI 1 "register_operand" "%r")
854                (match_operand:DI 2 "cmp_operand" "Nr")))]
855   "TARGET_SHMEDIA"
856   "cmpeq        %1, %N2, %0"
857   [(set_attr "type" "cmp_media")])
858
859 (define_insn "cmpgtsi_media"
860   [(set (match_operand:SI 0 "register_operand" "=r")
861         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
862                (match_operand:SI 2 "cmp_operand" "rN")))]
863   "TARGET_SHMEDIA"
864   "cmpgt        %N1, %N2, %0"
865   [(set_attr "type" "cmp_media")])
866
867 (define_insn "cmpgtdi_media"
868   [(set (match_operand:SI 0 "register_operand" "=r")
869         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
870                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
871   "TARGET_SHMEDIA"
872   "cmpgt        %N1, %N2, %0"
873   [(set_attr "type" "cmp_media")])
874
875 (define_insn "cmpgtusi_media"
876   [(set (match_operand:SI 0 "register_operand" "=r")
877         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
878                 (match_operand:SI 2 "cmp_operand" "rN")))]
879   "TARGET_SHMEDIA"
880   "cmpgtu       %N1, %N2, %0"
881   [(set_attr "type" "cmp_media")])
882
883 (define_insn "cmpgtudi_media"
884   [(set (match_operand:SI 0 "register_operand" "=r")
885         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
886                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
887   "TARGET_SHMEDIA"
888   "cmpgtu       %N1, %N2, %0"
889   [(set_attr "type" "cmp_media")])
890
891 ; These two patterns are for combine.
892 (define_insn "*cmpne0sisi_media"
893   [(set (match_operand:SI 0 "register_operand" "=r")
894         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
895   "TARGET_SHMEDIA"
896   "cmpgtu       %1,r63,%0"
897   [(set_attr "type" "cmp_media")])
898
899 ;; We save the compare operands in the cmpxx patterns and use them when
900 ;; we generate the branch.
901
902 (define_expand "cmpdi"
903   [(set (reg:SI T_REG)
904         (compare (match_operand:DI 0 "arith_operand" "")
905                  (match_operand:DI 1 "arith_operand" "")))]
906   "TARGET_SH2 || TARGET_SHMEDIA"
907   "
908 {
909   sh_compare_op0 = operands[0];
910   sh_compare_op1 = operands[1];
911   DONE;
912 }")
913 ;; -------------------------------------------------------------------------
914 ;; Conditional move instructions
915 ;; -------------------------------------------------------------------------
916
917 ;; The insn names may seem reversed, but note that cmveq performs the move
918 ;; if op1 == 0, and cmvne does it if op1 != 0.
919
920 (define_insn "movdicc_false"
921   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
922         (if_then_else:DI (eq (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   "cmveq        %1, %N2, %0"
928   [(set_attr "type" "arith_media")])
929
930 (define_insn "movdicc_true"
931   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
932         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
933                              (const_int 0))
934          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
935          (match_operand:DI 3 "arith_reg_operand" "0")))]
936   "TARGET_SHMEDIA"
937   "cmvne        %1, %N2, %0"
938   [(set_attr "type" "arith_media")])
939
940 (define_peephole2
941   [(set (match_operand:DI 0 "arith_reg_dest" "")
942         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
943                            [(match_operand:DI 1 "arith_reg_operand" "")
944                             (const_int 0)])
945          (match_operand:DI 2 "arith_reg_dest" "")
946          (match_dup 0)))
947    (set (match_dup 2) (match_dup 0))]
948   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
949   [(set (match_dup 2)
950         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
951   "
952 {
953   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
954                                 VOIDmode, operands[1], CONST0_RTX (DImode));
955 }")
956
957 (define_peephole2
958   [(set (match_operand:DI 0 "general_movdst_operand" "")
959         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
960    (set (match_operand:DI 2 "arith_reg_dest" "")
961         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
962                            [(match_operand:DI 3 "arith_reg_operand" "")
963                             (const_int 0)])
964          (match_dup 0)
965          (match_dup 2)))]
966   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
967   [(set (match_dup 2)
968         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
969   "")
970
971 (define_expand "movdicc"
972   [(set (match_operand:DI 0 "register_operand" "")
973         (if_then_else:DI (match_operand 1 "comparison_operator" "")
974                          (match_operand:DI 2 "register_operand" "")
975                          (match_operand:DI 3 "register_operand" "")))]
976   "TARGET_SHMEDIA"
977   "
978 {
979   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
980       && GET_MODE (sh_compare_op0) == DImode
981       && sh_compare_op1 == const0_rtx)
982     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
983                                   sh_compare_op0, sh_compare_op1);
984   else
985     {
986       rtx tmp;
987
988       if (no_new_pseudos)
989         FAIL;
990
991       tmp = gen_reg_rtx (DImode);
992
993       switch (GET_CODE (operands[1]))
994         {
995         case EQ:
996           emit_insn (gen_seq (tmp));
997           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
998           break;
999
1000         case NE:
1001           emit_insn (gen_seq (tmp));
1002           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1003           break;
1004
1005         case GT:
1006           emit_insn (gen_sgt (tmp));
1007           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1008           break;
1009
1010         case LT:
1011           emit_insn (gen_slt (tmp));
1012           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1013           break;
1014
1015         case GE:
1016           emit_insn (gen_slt (tmp));
1017           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1018           break;
1019
1020         case LE:
1021           emit_insn (gen_sgt (tmp));
1022           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1023           break;
1024
1025         case GTU:
1026           emit_insn (gen_sgtu (tmp));
1027           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1028           break;
1029
1030         case LTU:
1031           emit_insn (gen_sltu (tmp));
1032           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1033           break;
1034
1035         case GEU:
1036           emit_insn (gen_sltu (tmp));
1037           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1038           break;
1039
1040         case LEU:
1041           emit_insn (gen_sgtu (tmp));
1042           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1043           break;
1044
1045         case UNORDERED:
1046           emit_insn (gen_sunordered (tmp));
1047           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1048           break;
1049
1050         case ORDERED:
1051           emit_insn (gen_sunordered (tmp));
1052           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1053           break;
1054
1055         case UNEQ:
1056         case UNGE:
1057         case UNGT:
1058         case UNLE:
1059         case UNLT:
1060         case LTGT:
1061           FAIL;
1062
1063         default:
1064           gcc_unreachable ();
1065         }
1066     }
1067 }")
1068
1069 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1070 ;; SImode to DImode.
1071 (define_insn "movsicc_false"
1072   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1073         (if_then_else:SI (eq (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   "cmveq        %1, %N2, %0"
1079   [(set_attr "type" "arith_media")])
1080
1081 (define_insn "movsicc_true"
1082   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1083         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1084                           (const_int 0))
1085          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1086          (match_operand:SI 3 "arith_reg_operand" "0")))]
1087   "TARGET_SHMEDIA"
1088   "cmvne        %1, %N2, %0"
1089   [(set_attr "type" "arith_media")])
1090
1091 (define_peephole2
1092   [(set (match_operand:SI 0 "arith_reg_dest" "")
1093         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1094                            [(match_operand:SI 1 "arith_reg_operand" "")
1095                             (const_int 0)])
1096          (match_operand:SI 2 "arith_reg_dest" "")
1097          (match_dup 0)))
1098    (set (match_dup 2) (match_dup 0))]
1099   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1100   [(set (match_dup 2)
1101         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1102   "
1103 {
1104   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1105                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1106 }")
1107
1108 (define_peephole2
1109   [(set (match_operand:SI 0 "general_movdst_operand" "")
1110         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1111    (set (match_operand:SI 2 "arith_reg_dest" "")
1112         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1113                            [(match_operand:SI 3 "arith_reg_operand" "")
1114                             (const_int 0)])
1115          (match_dup 0)
1116          (match_dup 2)))]
1117   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1118    && (GET_CODE (operands[1]) != REG || GENERAL_REGISTER_P (REGNO (operands[1])))"
1119   [(set (match_dup 2)
1120         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1121   "
1122 {
1123   replace_rtx (operands[4], operands[0], operands[1]);
1124 }")
1125
1126 (define_peephole2
1127   [(set (match_operand 0 "any_register_operand" "")
1128         (match_operand 1 "any_register_operand" ""))
1129    (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1130    (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1131   "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1132     <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1133    && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1134    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1135    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1136    && ! reg_overlap_mentioned_p (operands[0], operands[3])
1137    && ! reg_overlap_mentioned_p (operands[2], operands[0])
1138    && ! reg_overlap_mentioned_p (operands[0], operands[1])
1139    && (REGNO_REG_CLASS (REGNO (operands[0]))
1140        == REGNO_REG_CLASS (REGNO (operands[2])))
1141    && (REGNO_REG_CLASS (REGNO (operands[1]))
1142        == REGNO_REG_CLASS (REGNO (operands[0])))"
1143   [(set (match_dup 0) (match_dup 3))
1144    (set (match_dup 4) (match_dup 5))]
1145   "
1146 {
1147   rtx set1, set2;
1148   rtx replacements[4];
1149
1150   /* We want to replace occurrences of operands[0] with operands[1] and
1151      operands[2] with operands[0] in operands[4]/operands[5].
1152      Doing just two replace_rtx calls naively would result in the second
1153      replacement undoing all that the first did if operands[1] and operands[2]
1154      are identical, so we must do this simultaneously.  */
1155   replacements[0] = operands[0];
1156   replacements[1] = operands[1];
1157   replacements[2] = operands[2];
1158   replacements[3] = operands[0];
1159   if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1160       || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1161       || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1162     FAIL;
1163
1164   operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1165   replace_n_hard_rtx (operands[4], replacements, 2, 1);
1166   operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1167   /* The operands array is aliased to recog_data.operand, which gets
1168      clobbered by extract_insn, so finish with it now.  */
1169   set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1170   set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1171   /* ??? The last insn might be a jump insn, but the generic peephole2 code
1172      always uses emit_insn.  */
1173   /* Check that we don't violate matching constraints or earlyclobbers.  */
1174   extract_insn (emit_insn (set1));
1175   if (! constrain_operands (1))
1176     goto failure;
1177   extract_insn (emit (set2));
1178   if (! constrain_operands (1))
1179     {
1180       rtx tmp;
1181     failure:
1182       tmp = replacements[0];
1183       replacements[0] = replacements[1];
1184       replacements[1] = tmp;
1185       tmp = replacements[2];
1186       replacements[2] = replacements[3];
1187       replacements[3] = tmp;
1188       replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1189       replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1190       replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1191       FAIL;
1192     }
1193   DONE;
1194 }")
1195
1196 ;; The register allocator is rather clumsy in handling multi-way conditional
1197 ;; moves, so allow the combiner to make them, and we split them up after
1198 ;; reload.  */
1199 (define_insn_and_split "*movsicc_umin"
1200   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1201         (umin:SI (if_then_else:SI
1202                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1203                        (const_int 0))
1204                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1205                    (match_operand:SI 3 "register_operand" "0"))
1206                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1207    (clobber (match_scratch:SI 5 "=&r"))]
1208   "TARGET_SHMEDIA && no_new_pseudos"
1209   "#"
1210   "TARGET_SHMEDIA && reload_completed"
1211   [(pc)]
1212   "
1213 {
1214   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1215                                 operands[3]));
1216   emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1217   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1218                                 operands[0]));
1219   DONE;
1220 }")
1221
1222 (define_insn "*movsicc_t_false"
1223   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1224         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1225                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1226                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1227   "TARGET_PRETEND_CMOVE
1228    && (arith_reg_operand (operands[1], SImode)
1229        || (immediate_operand (operands[1], SImode)
1230            && satisfies_constraint_I08 (operands[1])))"
1231   "bt 0f\;mov %1,%0\\n0:"
1232   [(set_attr "type" "mt_group,arith") ;; poor approximation
1233    (set_attr "length" "4")])
1234
1235 (define_insn "*movsicc_t_true"
1236   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1237         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1238                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1239                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1240   "TARGET_PRETEND_CMOVE
1241    && (arith_reg_operand (operands[1], SImode)
1242        || (immediate_operand (operands[1], SImode)
1243            && satisfies_constraint_I08 (operands[1])))"
1244   "bf 0f\;mov %1,%0\\n0:"
1245   [(set_attr "type" "mt_group,arith") ;; poor approximation
1246    (set_attr "length" "4")])
1247
1248 (define_expand "movsicc"
1249   [(set (match_operand:SI 0 "arith_reg_dest" "")
1250         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1251                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1252                          (match_operand:SI 3 "arith_reg_operand" "")))]
1253   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1254   "
1255 {
1256   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1257       && GET_MODE (sh_compare_op0) == SImode
1258       && (TARGET_SHMEDIA
1259           || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG))
1260       && sh_compare_op1 == const0_rtx)
1261     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
1262                                   sh_compare_op0, sh_compare_op1);
1263   else if (TARGET_PRETEND_CMOVE)
1264     {
1265       enum rtx_code code = GET_CODE (operands[1]);
1266       enum rtx_code new_code = code;
1267       rtx tmp;
1268
1269       if (! currently_expanding_to_rtl)
1270         FAIL;
1271       switch (code)
1272         {
1273         case LT: case LE: case LEU: case LTU:
1274           if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT)
1275             break;
1276         case NE:
1277           new_code = reverse_condition (code);
1278           break;
1279         case EQ: case GT: case GE: case GEU: case GTU:
1280           break;
1281         default:
1282           FAIL;
1283         }
1284       tmp = prepare_scc_operands (new_code);
1285       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1286                                     tmp, const0_rtx);
1287     }
1288   else
1289     {
1290       rtx tmp;
1291
1292       if (no_new_pseudos)
1293         FAIL;
1294
1295       tmp = gen_reg_rtx (SImode);
1296
1297       switch (GET_CODE (operands[1]))
1298         {
1299         case EQ:
1300           emit_insn (gen_seq (tmp));
1301           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1302           break;
1303
1304         case NE:
1305           emit_insn (gen_seq (tmp));
1306           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1307           break;
1308
1309         case GT:
1310           emit_insn (gen_sgt (tmp));
1311           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1312           break;
1313
1314         case LT:
1315           emit_insn (gen_slt (tmp));
1316           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1317           break;
1318
1319         case GE:
1320           emit_insn (gen_slt (tmp));
1321           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1322           break;
1323
1324         case LE:
1325           emit_insn (gen_sgt (tmp));
1326           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1327           break;
1328
1329         case GTU:
1330           emit_insn (gen_sgtu (tmp));
1331           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1332           break;
1333
1334         case LTU:
1335           emit_insn (gen_sltu (tmp));
1336           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1337           break;
1338
1339         case GEU:
1340           emit_insn (gen_sltu (tmp));
1341           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1342           break;
1343
1344         case LEU:
1345           emit_insn (gen_sgtu (tmp));
1346           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1347           break;
1348
1349         case UNORDERED:
1350           emit_insn (gen_sunordered (tmp));
1351           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1352           break;
1353
1354         case ORDERED:
1355           emit_insn (gen_sunordered (tmp));
1356           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1357           break;
1358
1359         case UNEQ:
1360         case UNGE:
1361         case UNGT:
1362         case UNLE:
1363         case UNLT:
1364         case LTGT:
1365           FAIL;
1366
1367         default:
1368           abort ();
1369         }
1370     }
1371 }")
1372
1373 (define_expand "movqicc"
1374   [(set (match_operand:QI 0 "register_operand" "")
1375         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1376                          (match_operand:QI 2 "register_operand" "")
1377                          (match_operand:QI 3 "register_operand" "")))]
1378   "TARGET_SHMEDIA"
1379   "
1380 {
1381   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1382   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1383   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1384   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1385   DONE;
1386 }")
1387 \f
1388 ;; -------------------------------------------------------------------------
1389 ;; Addition instructions
1390 ;; -------------------------------------------------------------------------
1391
1392 (define_expand "adddi3"
1393   [(set (match_operand:DI 0 "arith_reg_operand" "")
1394         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1395                  (match_operand:DI 2 "arith_operand" "")))]
1396   ""
1397   "
1398 {
1399   if (TARGET_SH1)
1400     {
1401       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
1402         FAIL;
1403       operands[2] = force_reg (DImode, operands[2]);
1404       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1405       DONE;
1406     }
1407 }")
1408
1409 (define_insn "*adddi3_media"
1410   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
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     %1, %2, %0
1416         addi    %1, %2, %0"
1417   [(set_attr "type" "arith_media")])
1418
1419 (define_insn "*adddisi3_media"
1420   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1421         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1422                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1423   "TARGET_SHMEDIA"
1424   "@
1425         add.l   %1, %2, %0
1426         addi.l  %1, %2, %0"
1427   [(set_attr "type" "arith_media")
1428    (set_attr "highpart" "ignore")])
1429
1430 (define_insn "adddi3z_media"
1431   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1432         (zero_extend:DI
1433          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1434                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1435   "TARGET_SHMEDIA"
1436   "addz.l       %1, %N2, %0"
1437   [(set_attr "type" "arith_media")
1438    (set_attr "highpart" "ignore")])
1439
1440 (define_insn "adddi3_compact"
1441   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1442         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1443                  (match_operand:DI 2 "arith_reg_operand" "r")))
1444    (clobber (reg:SI T_REG))]
1445   "TARGET_SH1"
1446   "#"
1447   [(set_attr "length" "6")])
1448
1449 (define_split
1450   [(set (match_operand:DI 0 "arith_reg_dest" "")
1451         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1452                  (match_operand:DI 2 "arith_reg_operand" "")))
1453    (clobber (reg:SI T_REG))]
1454   "TARGET_SH1 && reload_completed"
1455   [(const_int 0)]
1456   "
1457 {
1458   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1459   high0 = gen_rtx_REG (SImode,
1460                        true_regnum (operands[0])
1461                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1462   high2 = gen_rtx_REG (SImode,
1463                        true_regnum (operands[2])
1464                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1465   emit_insn (gen_clrt ());
1466   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1467   emit_insn (gen_addc1 (high0, high0, high2));
1468   DONE;
1469 }")
1470
1471 (define_insn "addc"
1472   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1473         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1474                           (match_operand:SI 2 "arith_reg_operand" "r"))
1475                  (reg:SI T_REG)))
1476    (set (reg:SI T_REG)
1477         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1478   "TARGET_SH1"
1479   "addc %2,%0"
1480   [(set_attr "type" "arith")])
1481
1482 (define_insn "addc1"
1483   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1484         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1485                           (match_operand:SI 2 "arith_reg_operand" "r"))
1486                  (reg:SI T_REG)))
1487    (clobber (reg:SI T_REG))]
1488   "TARGET_SH1"
1489   "addc %2,%0"
1490   [(set_attr "type" "arith")])
1491
1492 (define_expand "addsi3"
1493   [(set (match_operand:SI 0 "arith_reg_operand" "")
1494         (plus:SI (match_operand:SI 1 "arith_operand" "")
1495                  (match_operand:SI 2 "arith_operand" "")))]
1496   ""
1497   "
1498 {
1499   if (TARGET_SHMEDIA)
1500     operands[1] = force_reg (SImode, operands[1]);
1501 }")
1502
1503 (define_insn "addsi3_media"
1504   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1505         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1506                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1507   "TARGET_SHMEDIA"
1508   "@
1509         add.l   %1, %2, %0
1510         addi.l  %1, %2, %0"
1511   [(set_attr "type" "arith_media")
1512    (set_attr "highpart" "ignore")])
1513
1514 (define_insn "addsidi3_media"
1515   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1516         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1517                                   "%r,r")
1518                                  (match_operand:SI 2 "arith_operand"
1519                                   "r,I10"))))]
1520   "TARGET_SHMEDIA"
1521   "@
1522         add.l   %1, %2, %0
1523         addi.l  %1, %2, %0"
1524   [(set_attr "type" "arith_media")
1525    (set_attr "highpart" "ignore")])
1526
1527 (define_insn "*addsi3_compact"
1528   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1529         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1530                  (match_operand:SI 2 "arith_operand" "rI08")))]
1531   "TARGET_SH1"
1532   "add  %2,%0"
1533   [(set_attr "type" "arith")])
1534
1535 ;; -------------------------------------------------------------------------
1536 ;; Subtraction instructions
1537 ;; -------------------------------------------------------------------------
1538
1539 (define_expand "subdi3"
1540   [(set (match_operand:DI 0 "arith_reg_operand" "")
1541         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1542                   (match_operand:DI 2 "arith_reg_operand" "")))]
1543   ""
1544   "
1545 {
1546   if (TARGET_SH1)
1547     {
1548       operands[1] = force_reg (DImode, operands[1]);
1549       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1550       DONE;
1551     }
1552 }")
1553
1554 (define_insn "*subdi3_media"
1555   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1556         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1557                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1558   "TARGET_SHMEDIA"
1559   "sub  %N1, %2, %0"
1560   [(set_attr "type" "arith_media")])
1561   
1562 (define_insn "subdisi3_media"
1563   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1564         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1565                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1566   "TARGET_SHMEDIA"
1567   "sub.l        %N1, %2, %0"
1568   [(set_attr "type" "arith_media")
1569    (set_attr "highpart" "ignore")])
1570
1571 (define_insn "subdi3_compact"
1572   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1573         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1574                  (match_operand:DI 2 "arith_reg_operand" "r")))
1575    (clobber (reg:SI T_REG))]
1576   "TARGET_SH1"
1577   "#"
1578   [(set_attr "length" "6")])
1579
1580 (define_split
1581   [(set (match_operand:DI 0 "arith_reg_dest" "")
1582         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1583                   (match_operand:DI 2 "arith_reg_operand" "")))
1584    (clobber (reg:SI T_REG))]
1585   "TARGET_SH1 && reload_completed"
1586   [(const_int 0)]
1587   "
1588 {
1589   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1590   high0 = gen_rtx_REG (SImode,
1591                        true_regnum (operands[0])
1592                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1593   high2 = gen_rtx_REG (SImode,
1594                        true_regnum (operands[2])
1595                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1596   emit_insn (gen_clrt ());
1597   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1598   emit_insn (gen_subc1 (high0, high0, high2));
1599   DONE;
1600 }")
1601
1602 (define_insn "subc"
1603   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1604         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1605                             (match_operand:SI 2 "arith_reg_operand" "r"))
1606                   (reg:SI T_REG)))
1607    (set (reg:SI T_REG)
1608         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1609                           (reg:SI T_REG))
1610                 (match_dup 1)))]
1611   "TARGET_SH1"
1612   "subc %2,%0"
1613   [(set_attr "type" "arith")])
1614
1615 (define_insn "subc1"
1616   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1617         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1618                             (match_operand:SI 2 "arith_reg_operand" "r"))
1619                   (reg:SI T_REG)))
1620    (clobber (reg:SI T_REG))]
1621   "TARGET_SH1"
1622   "subc %2,%0"
1623   [(set_attr "type" "arith")])
1624
1625 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1626 ;; pattern for this case.  This helps multimedia applications that compute
1627 ;; the sum of absolute differences.
1628 (define_insn "mov_neg_si_t"
1629   [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1630   "TARGET_SH1"
1631   "subc %0,%0"
1632   [(set_attr "type" "arith")])
1633
1634 (define_insn "*subsi3_internal"
1635   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1636         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1637                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1638   "TARGET_SH1"
1639   "sub  %2,%0"
1640   [(set_attr "type" "arith")])
1641
1642 (define_insn_and_split "*subsi3_media"
1643   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1644         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1645                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1646   "TARGET_SHMEDIA
1647    && (operands[1] != constm1_rtx
1648        || (GET_CODE (operands[2]) != TRUNCATE
1649            && GET_CODE (operands[2]) != SUBREG))"
1650   "sub.l        %N1, %2, %0"
1651   "operands[1] == constm1_rtx"
1652   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1653   ""
1654   [(set_attr "type" "arith_media")
1655    (set_attr "highpart" "ignore")])
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)) 0)))]
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
1667 (define_split
1668   [(set (match_operand:SI 0 "arith_reg_dest" "")
1669         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1670                                                        "general_extend_operand"
1671                                                        "") 0)) 3)))]
1672   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1673   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1674    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1675   "")
1676 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1677 ;; will sometimes save one instruction.  Otherwise we might get
1678 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1679 ;; are the same.
1680
1681 (define_expand "subsi3"
1682   [(set (match_operand:SI 0 "arith_reg_operand" "")
1683         (minus:SI (match_operand:SI 1 "arith_operand" "")
1684                   (match_operand:SI 2 "arith_reg_operand" "")))]
1685   ""
1686   "
1687 {
1688   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1689     {
1690       emit_insn (gen_negsi2 (operands[0], operands[2]));
1691       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1692       DONE;
1693     }
1694   if (TARGET_SHMEDIA)
1695     {
1696       if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1697         FAIL;
1698       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1699         operands[1] = force_reg (SImode, operands[1]);
1700     }
1701 }")
1702 \f
1703 ;; -------------------------------------------------------------------------
1704 ;; Division instructions
1705 ;; -------------------------------------------------------------------------
1706
1707 ;; We take advantage of the library routines which don't clobber as many
1708 ;; registers as a normal function call would.
1709
1710 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1711 ;; also has an effect on the register that holds the address of the sfunc.
1712 ;; To make this work, we have an extra dummy insn that shows the use
1713 ;; of this register for reorg.
1714
1715 (define_insn "use_sfunc_addr"
1716   [(set (reg:SI PR_REG)
1717         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1718   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1719   ""
1720   [(set_attr "length" "0")])
1721
1722 (define_insn "udivsi3_sh2a"
1723   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1724         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1725                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1726   "TARGET_SH2A"
1727   "divu %2,%1"
1728   [(set_attr "type" "arith")
1729    (set_attr "in_delay_slot" "no")])
1730
1731 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1732 ;; hard register 0.  If we used hard register 0, then the next instruction
1733 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1734 ;; gets allocated to a stack slot that needs its address reloaded, then
1735 ;; there is nothing to prevent reload from using r0 to reload the address.
1736 ;; This reload would clobber the value in r0 we are trying to store.
1737 ;; If we let reload allocate r0, then this problem can never happen.
1738
1739 (define_insn "udivsi3_i1"
1740   [(set (match_operand:SI 0 "register_operand" "=z")
1741         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1742    (clobber (reg:SI T_REG))
1743    (clobber (reg:SI PR_REG))
1744    (clobber (reg:SI R4_REG))
1745    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1746   "TARGET_SH1 && ! TARGET_SH4"
1747   "jsr  @%1%#"
1748   [(set_attr "type" "sfunc")
1749    (set_attr "needs_delay_slot" "yes")])
1750
1751 ; Since shmedia-nofpu code could be linked against shcompact code, and
1752 ; the udivsi3 libcall has the same name, we must consider all registers
1753 ; clobbered that are in the union of the registers clobbered by the
1754 ; shmedia and the shcompact implementation.  Note, if the shcompact
1755 ; implementation actually used shcompact code, we'd need to clobber
1756 ; also r23 and fr23.
1757 (define_insn "udivsi3_i1_media"
1758   [(set (match_operand:SI 0 "register_operand" "=z")
1759         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1760    (clobber (reg:SI T_MEDIA_REG))
1761    (clobber (reg:SI PR_MEDIA_REG))
1762    (clobber (reg:SI R20_REG))
1763    (clobber (reg:SI R21_REG))
1764    (clobber (reg:SI R22_REG))
1765    (clobber (reg:DI TR0_REG))
1766    (clobber (reg:DI TR1_REG))
1767    (clobber (reg:DI TR2_REG))
1768    (use (match_operand 1 "target_operand" "b"))]
1769   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1770   "blink        %1, r18"
1771   [(set_attr "type" "sfunc")
1772    (set_attr "needs_delay_slot" "yes")])
1773
1774 (define_expand "udivsi3_i4_media"
1775   [(set (match_dup 3)
1776         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1777    (set (match_dup 4)
1778         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1779    (set (match_dup 5) (float:DF (match_dup 3)))
1780    (set (match_dup 6) (float:DF (match_dup 4)))
1781    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1782    (set (match_dup 8) (fix:DI (match_dup 7)))
1783    (set (match_operand:SI 0 "register_operand" "")
1784         (truncate:SI (match_dup 8)))]
1785   "TARGET_SHMEDIA_FPU"
1786   "
1787 {
1788   operands[3] = gen_reg_rtx (DImode);
1789   operands[4] = gen_reg_rtx (DImode);
1790   operands[5] = gen_reg_rtx (DFmode);
1791   operands[6] = gen_reg_rtx (DFmode);
1792   operands[7] = gen_reg_rtx (DFmode);
1793   operands[8] = gen_reg_rtx (DImode);
1794 }")
1795
1796 (define_insn "udivsi3_i4"
1797   [(set (match_operand:SI 0 "register_operand" "=y")
1798         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1799    (clobber (reg:SI T_REG))
1800    (clobber (reg:SI PR_REG))
1801    (clobber (reg:DF DR0_REG))
1802    (clobber (reg:DF DR2_REG))
1803    (clobber (reg:DF DR4_REG))
1804    (clobber (reg:SI R0_REG))
1805    (clobber (reg:SI R1_REG))
1806    (clobber (reg:SI R4_REG))
1807    (clobber (reg:SI R5_REG))
1808    (use (reg:PSI FPSCR_REG))
1809    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1810   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1811   "jsr  @%1%#"
1812   [(set_attr "type" "sfunc")
1813    (set_attr "fp_mode" "double")
1814    (set_attr "needs_delay_slot" "yes")])
1815
1816 (define_insn "udivsi3_i4_single"
1817   [(set (match_operand:SI 0 "register_operand" "=y")
1818         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1819    (clobber (reg:SI T_REG))
1820    (clobber (reg:SI PR_REG))
1821    (clobber (reg:DF DR0_REG))
1822    (clobber (reg:DF DR2_REG))
1823    (clobber (reg:DF DR4_REG))
1824    (clobber (reg:SI R0_REG))
1825    (clobber (reg:SI R1_REG))
1826    (clobber (reg:SI R4_REG))
1827    (clobber (reg:SI R5_REG))
1828    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1829   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1830   "jsr  @%1%#"
1831   [(set_attr "type" "sfunc")
1832    (set_attr "needs_delay_slot" "yes")])
1833
1834 (define_insn "udivsi3_i4_int"
1835   [(set (match_operand:SI 0 "register_operand" "=z")
1836         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1837    (clobber (reg:SI T_REG))
1838    (clobber (reg:SI R1_REG))
1839    (clobber (reg:SI PR_REG))
1840    (clobber (reg:SI MACH_REG))
1841    (clobber (reg:SI MACL_REG))
1842    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1843   "TARGET_SH1"
1844   "jsr  @%1%#"
1845   [(set_attr "type" "sfunc")
1846    (set_attr "needs_delay_slot" "yes")])
1847
1848
1849 (define_expand "udivsi3"
1850   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1851    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1852    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1853    (parallel [(set (match_operand:SI 0 "register_operand" "")
1854                    (udiv:SI (reg:SI R4_REG)
1855                             (reg:SI R5_REG)))
1856               (clobber (reg:SI T_REG))
1857               (clobber (reg:SI PR_REG))
1858               (clobber (reg:SI R4_REG))
1859               (use (match_dup 3))])]
1860   ""
1861   "
1862 {
1863   rtx last;
1864
1865   operands[3] = gen_reg_rtx (Pmode);
1866   /* Emit the move of the address to a pseudo outside of the libcall.  */
1867   if (TARGET_DIVIDE_CALL_TABLE)
1868     {
1869       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1870          that causes problems when the divide code is supposed to come from a
1871          separate library.  Division by zero is undefined, so dividing 1 can be
1872          implemented by comparing with the divisor.  */
1873       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1874         {
1875           emit_insn (gen_cmpsi (operands[1], operands[2]));
1876           emit_insn (gen_sgeu (operands[0]));
1877           DONE;
1878         }
1879       else if (operands[2] == const0_rtx)
1880         {
1881           emit_move_insn (operands[0], operands[2]);
1882           DONE;
1883         }
1884       function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1885       last = gen_udivsi3_i4_int (operands[0], operands[3]);
1886     }
1887   else if (TARGET_DIVIDE_CALL_FP)
1888     {
1889       function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1890       if (TARGET_FPU_SINGLE)
1891         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1892       else
1893         last = gen_udivsi3_i4 (operands[0], operands[3]);
1894     }
1895   else if (TARGET_SHMEDIA_FPU)
1896     {
1897       operands[1] = force_reg (SImode, operands[1]);
1898       operands[2] = force_reg (SImode, operands[2]);
1899       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1900       DONE;
1901     }
1902   else if (TARGET_SH2A)
1903     {
1904       operands[1] = force_reg (SImode, operands[1]);
1905       operands[2] = force_reg (SImode, operands[2]);
1906       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1907       DONE;
1908     }
1909   else if (TARGET_SH5)
1910     {
1911       function_symbol (operands[3],
1912                        TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1913                        SFUNC_STATIC);
1914
1915       if (TARGET_SHMEDIA)
1916         last = gen_udivsi3_i1_media (operands[0], operands[3]);
1917       else if (TARGET_FPU_ANY)
1918         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1919       else
1920         last = gen_udivsi3_i1 (operands[0], operands[3]);
1921     }
1922   else
1923     {
1924       function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1925       last = gen_udivsi3_i1 (operands[0], operands[3]);
1926     }
1927   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1928   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1929   emit_insn (last);
1930   DONE;
1931 }")
1932
1933 (define_insn "divsi3_sh2a"
1934   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1935         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1936                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1937   "TARGET_SH2A"
1938   "divs %2,%1"
1939   [(set_attr "type" "arith")
1940    (set_attr "in_delay_slot" "no")])
1941
1942 (define_insn "divsi3_i1"
1943   [(set (match_operand:SI 0 "register_operand" "=z")
1944         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1945    (clobber (reg:SI T_REG))
1946    (clobber (reg:SI PR_REG))
1947    (clobber (reg:SI R1_REG))
1948    (clobber (reg:SI R2_REG))
1949    (clobber (reg:SI R3_REG))
1950    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1951   "TARGET_SH1 && ! TARGET_SH4"
1952   "jsr  @%1%#"
1953   [(set_attr "type" "sfunc")
1954    (set_attr "needs_delay_slot" "yes")])
1955
1956 (define_insn "divsi3_i1_media"
1957   [(set (match_operand:SI 0 "register_operand" "=z")
1958         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1959    (clobber (reg:SI T_MEDIA_REG))
1960    (clobber (reg:SI PR_MEDIA_REG))
1961    (clobber (reg:SI R1_REG))
1962    (clobber (reg:SI R20_REG))
1963    (clobber (reg:SI R21_REG))
1964    (clobber (reg:SI TR0_REG))
1965    (use (match_operand 1 "target_operand" "b"))]
1966   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1967   "blink        %1, r18"
1968   [(set_attr "type" "sfunc")])
1969
1970 (define_insn "divsi3_media_2"
1971   [(set (match_operand:SI 0 "register_operand" "=z")
1972         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1973    (clobber (reg:SI T_MEDIA_REG))
1974    (clobber (reg:SI PR_MEDIA_REG))
1975    (clobber (reg:SI R1_REG))
1976    (clobber (reg:SI R21_REG))
1977    (clobber (reg:SI TR0_REG))
1978    (use (reg:SI R20_REG))
1979    (use (match_operand 1 "target_operand" "b"))]
1980   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1981   "blink        %1, r18"
1982   [(set_attr "type" "sfunc")])
1983
1984 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1985 ;; hard reg clobbers and data dependencies that we need when we want
1986 ;; to rematerialize the division into a call.
1987 (define_insn_and_split "divsi_inv_call"
1988   [(set (match_operand:SI 0 "register_operand" "=r")
1989         (div:SI (match_operand:SI 1 "register_operand" "r")
1990                 (match_operand:SI 2 "register_operand" "r")))
1991    (clobber (reg:SI R4_REG))
1992    (clobber (reg:SI R5_REG))
1993    (clobber (reg:SI T_MEDIA_REG))
1994    (clobber (reg:SI PR_MEDIA_REG))
1995    (clobber (reg:SI R1_REG))
1996    (clobber (reg:SI R21_REG))
1997    (clobber (reg:SI TR0_REG))
1998    (clobber (reg:SI R20_REG))
1999    (use (match_operand:SI 3 "register_operand" "r"))]
2000   "TARGET_SHMEDIA"
2001   "#"
2002   "&& (high_life_started || reload_completed)"
2003   [(set (match_dup 0) (match_dup 3))]
2004   ""
2005   [(set_attr "highpart" "must_split")])
2006
2007 ;; This is the combiner pattern for -mdiv=inv:call .
2008 (define_insn_and_split "*divsi_inv_call_combine"
2009   [(set (match_operand:SI 0 "register_operand" "=z")
2010         (div:SI (match_operand:SI 1 "register_operand" "r")
2011                 (match_operand:SI 2 "register_operand" "r")))
2012    (clobber (reg:SI R4_REG))
2013    (clobber (reg:SI R5_REG))
2014    (clobber (reg:SI T_MEDIA_REG))
2015    (clobber (reg:SI PR_MEDIA_REG))
2016    (clobber (reg:SI R1_REG))
2017    (clobber (reg:SI R21_REG))
2018    (clobber (reg:SI TR0_REG))
2019    (clobber (reg:SI R20_REG))
2020    (use (unspec:SI [(match_dup 1)
2021                     (match_operand:SI 3 "" "")
2022                     (unspec:SI [(match_operand:SI 4 "" "")
2023                                 (match_dup 3)
2024                                 (match_operand:DI 5 "" "")]
2025                      UNSPEC_DIV_INV_M2)
2026                     (match_operand:DI 6 "" "")
2027                     (const_int 0)
2028                     (const_int 0)]
2029          UNSPEC_DIV_INV_M3))]
2030   "TARGET_SHMEDIA"
2031   "#"
2032   "&& (high_life_started || reload_completed)"
2033   [(pc)]
2034   "
2035 {
2036   const char *name = sh_divsi3_libfunc;
2037   enum sh_function_kind kind = SFUNC_GOT;
2038   rtx sym;
2039
2040   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2041   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2042   while (TARGET_DIVIDE_INV_CALL2)
2043     {
2044       rtx x = operands[3];
2045
2046       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2047         break;
2048       x = XVECEXP (x, 0, 0);
2049       name = \"__sdivsi3_2\";
2050       kind = SFUNC_STATIC;
2051       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2052       break;
2053     }
2054   sym = function_symbol (NULL, name, kind);
2055   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2056   DONE;
2057 }"
2058   [(set_attr "highpart" "must_split")])
2059
2060 (define_expand "divsi3_i4_media"
2061   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2062    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2063    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2064    (set (match_operand:SI 0 "register_operand" "=r")
2065         (fix:SI (match_dup 5)))]
2066   "TARGET_SHMEDIA_FPU"
2067   "
2068 {
2069   operands[3] = gen_reg_rtx (DFmode);
2070   operands[4] = gen_reg_rtx (DFmode);
2071   operands[5] = gen_reg_rtx (DFmode);
2072 }")
2073
2074 (define_insn "divsi3_i4"
2075   [(set (match_operand:SI 0 "register_operand" "=y")
2076         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2077    (clobber (reg:SI PR_REG))
2078    (clobber (reg:DF DR0_REG))
2079    (clobber (reg:DF DR2_REG))
2080    (use (reg:PSI FPSCR_REG))
2081    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2082   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2083   "jsr  @%1%#"
2084   [(set_attr "type" "sfunc")
2085    (set_attr "fp_mode" "double")
2086    (set_attr "needs_delay_slot" "yes")])
2087
2088 (define_insn "divsi3_i4_single"
2089   [(set (match_operand:SI 0 "register_operand" "=y")
2090         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2091    (clobber (reg:SI PR_REG))
2092    (clobber (reg:DF DR0_REG))
2093    (clobber (reg:DF DR2_REG))
2094    (clobber (reg:SI R2_REG))
2095    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2096   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2097   "jsr  @%1%#"
2098   [(set_attr "type" "sfunc")
2099    (set_attr "needs_delay_slot" "yes")])
2100
2101 (define_insn "divsi3_i4_int"
2102   [(set (match_operand:SI 0 "register_operand" "=z")
2103         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2104    (clobber (reg:SI T_REG))
2105    (clobber (reg:SI PR_REG))
2106    (clobber (reg:SI R1_REG))
2107    (clobber (reg:SI MACH_REG))
2108    (clobber (reg:SI MACL_REG))
2109    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2110   "TARGET_SH1"
2111   "jsr  @%1%#"
2112   [(set_attr "type" "sfunc")
2113    (set_attr "needs_delay_slot" "yes")])
2114
2115 (define_expand "divsi3"
2116   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2117    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2118    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2119    (parallel [(set (match_operand:SI 0 "register_operand" "")
2120                    (div:SI (reg:SI R4_REG)
2121                            (reg:SI R5_REG)))
2122               (clobber (reg:SI T_REG))
2123               (clobber (reg:SI PR_REG))
2124               (clobber (reg:SI R1_REG))
2125               (clobber (reg:SI R2_REG))
2126               (clobber (reg:SI R3_REG))
2127               (use (match_dup 3))])]
2128   ""
2129   "
2130 {
2131   rtx last;
2132
2133   operands[3] = gen_reg_rtx (Pmode);
2134   /* Emit the move of the address to a pseudo outside of the libcall.  */
2135   if (TARGET_DIVIDE_CALL_TABLE)
2136     {
2137       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2138       last = gen_divsi3_i4_int (operands[0], operands[3]);
2139     }
2140   else if (TARGET_DIVIDE_CALL_FP)
2141     {
2142       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2143       if (TARGET_FPU_SINGLE)
2144         last = gen_divsi3_i4_single (operands[0], operands[3]);
2145       else
2146         last = gen_divsi3_i4 (operands[0], operands[3]);
2147     }
2148   else if (TARGET_SH2A)
2149     {
2150       operands[1] = force_reg (SImode, operands[1]);
2151       operands[2] = force_reg (SImode, operands[2]);
2152       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2153       DONE;
2154     }
2155   else if (TARGET_DIVIDE_INV)
2156     {
2157       rtx dividend = operands[1];
2158       rtx divisor = operands[2];
2159       rtx tab_base;
2160       rtx nsb_res = gen_reg_rtx (DImode);
2161       rtx norm64 = gen_reg_rtx (DImode);
2162       rtx tab_ix = gen_reg_rtx (DImode);
2163       rtx norm32 = gen_reg_rtx (SImode);
2164       rtx i92 = force_reg (DImode, GEN_INT (92));
2165       rtx scratch0a = gen_reg_rtx (DImode);
2166       rtx scratch0b = gen_reg_rtx (DImode);
2167       rtx inv0 = gen_reg_rtx (SImode);
2168       rtx scratch1a = gen_reg_rtx (DImode);
2169       rtx scratch1b = gen_reg_rtx (DImode);
2170       rtx shift = gen_reg_rtx (DImode);
2171       rtx i2p27, i43;
2172       rtx inv1 = gen_reg_rtx (SImode);
2173       rtx scratch2a = gen_reg_rtx (DImode);
2174       rtx scratch2b = gen_reg_rtx (SImode);
2175       rtx inv2 = gen_reg_rtx (SImode);
2176       rtx scratch3a = gen_reg_rtx (DImode);
2177       rtx scratch3b = gen_reg_rtx (DImode);
2178       rtx scratch3c = gen_reg_rtx (DImode);
2179       rtx scratch3d = gen_reg_rtx (SImode);
2180       rtx scratch3e = gen_reg_rtx (DImode);
2181       rtx result = gen_reg_rtx (SImode);
2182
2183       if (! arith_reg_or_0_operand (dividend, SImode))
2184         dividend = force_reg (SImode, dividend);
2185       if (! arith_reg_operand (divisor, SImode))
2186         divisor = force_reg (SImode, divisor);
2187       if (flag_pic && Pmode != DImode)
2188         {
2189           tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2190           tab_base = gen_datalabel_ref (tab_base);
2191           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2192         }
2193       else
2194         {
2195           tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2196           tab_base = gen_datalabel_ref (tab_base);
2197           tab_base = force_reg (DImode, tab_base);
2198         }
2199       if (TARGET_DIVIDE_INV20U)
2200         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2201       else
2202         i2p27 = GEN_INT (0);
2203       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2204         i43 = force_reg (DImode, GEN_INT (43));
2205       else
2206         i43 = GEN_INT (0);
2207       emit_insn (gen_nsbdi (nsb_res,
2208                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2209       emit_insn (gen_ashldi3_media (norm64,
2210                                     gen_rtx_SUBREG (DImode, divisor, 0),
2211                                     nsb_res));
2212       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2213       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2214       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2215                                    inv0, scratch0a, scratch0b,
2216                                    scratch1a, scratch1b));
2217       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2218       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2219                                    scratch2a));
2220       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2221                                    i2p27, i43,
2222                                    scratch3a, scratch3b, scratch3c,
2223                                    scratch2a, scratch2b, scratch3d, scratch3e));
2224       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2225         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2226       else if (TARGET_DIVIDE_INV_FP)
2227         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2228                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2229                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2230                                      gen_reg_rtx (DFmode)));
2231       else
2232         emit_move_insn (operands[0], result);
2233       DONE;
2234     }
2235   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2236     {
2237       operands[1] = force_reg (SImode, operands[1]);
2238       operands[2] = force_reg (SImode, operands[2]);
2239       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2240       DONE;
2241     }
2242   else if (TARGET_SH5)
2243     {
2244       if (TARGET_DIVIDE_CALL2)
2245         {
2246           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2247           tab_base = gen_datalabel_ref (tab_base);
2248           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2249         }
2250       if (TARGET_FPU_ANY && TARGET_SH1)
2251         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2252       else if (TARGET_DIVIDE_CALL2)
2253         function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2254       else
2255         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2256
2257       if (TARGET_SHMEDIA)
2258         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2259                 (operands[0], operands[3]));
2260       else if (TARGET_FPU_ANY)
2261         last = gen_divsi3_i4_single (operands[0], operands[3]);
2262       else
2263         last = gen_divsi3_i1 (operands[0], operands[3]);
2264     }
2265   else
2266     {
2267       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2268       last = gen_divsi3_i1 (operands[0], operands[3]);
2269     }
2270   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2271   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2272   emit_insn (last);
2273   DONE;
2274 }")
2275
2276 ;; operands: scratch, tab_base, tab_ix
2277 ;; These are unspecs because we could generate an indexed addressing mode
2278 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2279 ;; confuse reload.  See PR27117.
2280
2281 (define_insn "divsi_inv_qitable"
2282   [(set (match_operand:DI 0 "register_operand" "=r")
2283         (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2284                                     (match_operand:DI 2 "register_operand" "r")]
2285                          UNSPEC_DIV_INV_TABLE)))]
2286   "TARGET_SHMEDIA"
2287   "@
2288         ldx.ub  %1, %2, %0"
2289   [(set_attr "type" "load_media")
2290    (set_attr "highpart" "user")])
2291
2292 ;; operands: scratch, tab_base, tab_ix
2293 (define_insn "divsi_inv_hitable"
2294   [(set (match_operand:DI 0 "register_operand" "=r")
2295         (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2296                                     (match_operand:DI 2 "register_operand" "r")]
2297                          UNSPEC_DIV_INV_TABLE)))]
2298   "TARGET_SHMEDIA"
2299   "@
2300         ldx.w   %1, %2, %0"
2301   [(set_attr "type" "load_media")
2302    (set_attr "highpart" "user")])
2303
2304 ;; operands: inv0, tab_base, tab_ix, norm32
2305 ;; scratch equiv in sdivsi3_2: r19, r21
2306 (define_expand "divsi_inv_m0"
2307   [(set (match_operand:SI 0 "register_operand" "=r")
2308         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2309                     (match_operand:DI 2 "register_operand" "r")
2310                     (match_operand:SI 3 "register_operand" "r")]
2311          UNSPEC_DIV_INV_M0))
2312    (clobber (match_operand:DI 4 "register_operand" "=r"))
2313    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2314   "TARGET_SHMEDIA"
2315   "
2316 {
2317 /*
2318 tab_base: r20
2319 tab_ix: r21
2320 norm32: r25
2321  ldx.ub r20, r21, r19 // u0.8
2322  shlli r21, 1, r21
2323  muls.l r25, r19, r19 // s2.38
2324  ldx.w r20, r21, r21  // s2.14
2325  shari r19, 24, r19   // truncate to s2.14
2326  sub r21, r19, r19    // some 11 bit inverse in s1.14
2327 */
2328
2329   rtx inv0 = operands[0];
2330   rtx tab_base = operands[1];
2331   rtx tab_ix = operands[2];
2332   rtx norm32 = operands[3];
2333   rtx scratch0 = operands[4];
2334   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2335   rtx scratch1 = operands[5];
2336
2337   emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2338   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2339   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2340   emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2341   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2342   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2343   DONE;
2344 }")
2345
2346 ;; operands: inv1, tab_base, tab_ix, norm32
2347 (define_insn_and_split "divsi_inv_m1"
2348   [(set (match_operand:SI 0 "register_operand" "=r")
2349         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2350                     (match_operand:DI 2 "register_operand" "r")
2351                     (match_operand:SI 3 "register_operand" "r")]
2352          UNSPEC_DIV_INV_M1))
2353    (clobber (match_operand:SI 4 "register_operand" "=r"))
2354    (clobber (match_operand:DI 5 "register_operand" "=r"))
2355    (clobber (match_operand:DI 6 "register_operand" "=r"))
2356    (clobber (match_operand:DI 7 "register_operand" "=r"))
2357    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2358   "TARGET_SHMEDIA"
2359   "#"
2360   "&& no_new_pseudos"
2361   [(pc)]
2362   "
2363 {
2364 /* inv0: r19
2365  muls.l r19, r19, r18 // u0.28
2366  muls.l r25, r18, r18 // s2.58
2367  shlli r19, 45, r0    // multiply by two and convert to s2.58
2368  sub r0, r18, r18
2369  shari r18, 28, r18   // some 18 bit inverse in s1.30
2370 */
2371
2372   rtx inv1 = operands[0];
2373   rtx tab_base = operands[1];
2374   rtx tab_ix = operands[2];
2375   rtx norm32 = operands[3];
2376   rtx inv0 = operands[4];
2377   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2378   rtx scratch0a = operands[5];
2379   rtx scratch0b = operands[6];
2380   rtx scratch0 = operands[7];
2381   rtx scratch1 = operands[8];
2382   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2383
2384   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2385                                scratch0a, scratch0b));
2386   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2387   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2388   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2389   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2390   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2391   DONE;
2392 }")
2393
2394 ;; operands: inv2, norm32, inv1, i92
2395 (define_insn_and_split "divsi_inv_m2"
2396   [(set (match_operand:SI 0 "register_operand" "=r")
2397         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2398                     (match_operand:SI 2 "register_operand" "r")
2399                     (match_operand:DI 3 "register_operand" "r")]
2400          UNSPEC_DIV_INV_M2))
2401    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2402   "TARGET_SHMEDIA"
2403   "#"
2404   "&& no_new_pseudos"
2405   [(pc)]
2406   "
2407 {
2408 /*
2409  muls.l r18, r25, r0  // s2.60
2410  shari r0, 16, r0     // s-16.44
2411   sub
2412  muls.l r0, r18, r19  // s-16.74
2413  shari r19, 30, r19   // s-16.44
2414 */
2415   rtx inv2 = operands[0];
2416   rtx norm32 = operands[1];
2417   rtx inv1 = operands[2];
2418   rtx i92 = operands[3];
2419   rtx scratch0 = operands[4];
2420   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2421
2422   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2423   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2424   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2425   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2426   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2427   DONE;
2428 }")
2429
2430 (define_insn_and_split "divsi_inv_m3"
2431   [(set (match_operand:SI 0 "register_operand" "=r")
2432         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2433                     (match_operand:SI 2 "register_operand" "r")
2434                     (match_operand:SI 3 "register_operand" "r")
2435                     (match_operand:DI 4 "register_operand" "r")
2436                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2437                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2438          UNSPEC_DIV_INV_M3))
2439    (clobber (match_operand:DI 7 "register_operand" "=r"))
2440    (clobber (match_operand:DI 8 "register_operand" "=r"))
2441    (clobber (match_operand:DI 9 "register_operand" "=r"))
2442    (clobber (match_operand:DI 10 "register_operand" "=r"))
2443    (clobber (match_operand:SI 11 "register_operand" "=r"))
2444    (clobber (match_operand:SI 12 "register_operand" "=r"))
2445    (clobber (match_operand:DI 13 "register_operand" "=r"))]
2446   "TARGET_SHMEDIA"
2447   "#"
2448   "&& no_new_pseudos"
2449   [(pc)]
2450   "
2451 {
2452 /*
2453   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2454   r0: scratch0  r19: scratch1 r21: scratch2
2455
2456   muls.l r18, r4, r25 // s32.30
2457  muls.l r19, r4, r19  // s15.30
2458  shari r25, 63, r21
2459   shari r19, 14, r19  // s18.-14
2460  sub r25, r19, r0
2461  shard r0, r1, r0
2462  sub r0, r21, r0
2463 */
2464
2465   rtx result = operands[0];
2466   rtx dividend = operands[1];
2467   rtx inv1 = operands[2];
2468   rtx inv2 = operands[3];
2469   rtx shift = operands[4];
2470   rtx scratch0 = operands[7];
2471   rtx scratch1 = operands[8];
2472   rtx scratch2 = operands[9];
2473
2474   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2475   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2476   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2477   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2478   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2479   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2480   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2481   DONE;
2482 }")
2483
2484 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2485 ;; inv1: tab_base, tab_ix, norm32
2486 ;; inv2: norm32, inv1, i92
2487 (define_insn_and_split "divsi_inv_m1_3"
2488   [(set (match_operand:SI 0 "register_operand" "=r")
2489         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2490                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2491                                 (match_operand:DI 3 "register_operand" "r")
2492                                 (match_operand:SI 4 "register_operand" "r")]
2493                      UNSPEC_DIV_INV_M1)
2494                     (unspec:SI [(match_dup 4)
2495                                 (unspec:SI [(match_dup 2)
2496                                             (match_dup 3)
2497                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
2498                                 (match_operand:SI 5 "" "")]
2499                      UNSPEC_DIV_INV_M2)
2500                     (match_operand:DI 6 "register_operand" "r")
2501                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2502                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2503          UNSPEC_DIV_INV_M3))
2504    (clobber (match_operand:DI 9 "register_operand" "=r"))
2505    (clobber (match_operand:DI 10 "register_operand" "=r"))
2506    (clobber (match_operand:DI 11 "register_operand" "=r"))
2507    (clobber (match_operand:DI 12 "register_operand" "=r"))
2508    (clobber (match_operand:SI 13 "register_operand" "=r"))
2509    (clobber (match_operand:SI 14 "register_operand" "=r"))
2510    (clobber (match_operand:DI 15 "register_operand" "=r"))]
2511   "TARGET_SHMEDIA
2512    && (TARGET_DIVIDE_INV_MINLAT
2513        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2514   "#"
2515   "&& no_new_pseudos"
2516   [(pc)]
2517   "
2518 {
2519   rtx result = operands[0];
2520   rtx dividend = operands[1];
2521   rtx tab_base = operands[2];
2522   rtx tab_ix = operands[3];
2523   rtx norm32 = operands[4];
2524   /* rtx i92 = operands[5]; */
2525   rtx shift = operands[6];
2526   rtx i2p27 = operands[7];
2527   rtx i43 = operands[8];
2528   rtx scratch0 = operands[9];
2529   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2530   rtx scratch1 = operands[10];
2531   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2532   rtx scratch2 = operands[11];
2533   rtx scratch3 = operands[12];
2534   rtx scratch4 = operands[13];
2535   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2536   rtx scratch5 = operands[14];
2537   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2538   rtx scratch6 = operands[15];
2539
2540   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2541                                scratch0, scratch1));
2542   /* inv0 == scratch4 */
2543   if (! TARGET_DIVIDE_INV20U)
2544     {
2545       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2546       i2p27 = scratch0;
2547       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2548     }
2549   else
2550     {
2551       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2552       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2553     }
2554   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2555   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2556   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2557   /* inv1 == scratch4 */
2558
2559   if (TARGET_DIVIDE_INV_MINLAT)
2560     {
2561       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2562       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2563       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2564       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2565       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2566       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2567       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2568       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2569       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2570       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2571       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2572     }
2573   else
2574     {
2575       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2576       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2577       emit_insn (gen_nsbdi (scratch6,
2578                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
2579       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2580       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2581       emit_insn (gen_divsi_inv20 (scratch2,
2582                                   norm32, scratch4, dividend,
2583                                   scratch6, scratch3, i43,
2584                                   /* scratch0 may be shared with i2p27.  */
2585                                   scratch0, scratch1, scratch5,
2586                                   label, label, i2p27));
2587     }
2588   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2589   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2590   DONE;
2591 }")
2592
2593 (define_insn "divsi_inv20"
2594   [(set (match_operand:DI 0 "register_operand" "=&r")
2595         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2596                     (match_operand:SI 2 "register_operand" "r")
2597                     (match_operand:SI 3 "register_operand" "r")
2598                     (match_operand:DI 4 "register_operand" "r")
2599                     (match_operand:DI 5 "register_operand" "r")
2600                     (match_operand:DI 6 "register_operand" "r")
2601                     (match_operand:DI 12 "register_operand" "r")
2602                     (match_operand 10 "target_operand" "b")
2603                     (match_operand 11 "immediate_operand" "i")]
2604          UNSPEC_DIV_INV20))
2605    (clobber (match_operand:DI 7 "register_operand" "=&r"))
2606    (clobber (match_operand:DI 8 "register_operand" "=&r"))
2607    (clobber (match_operand:SI 9 "register_operand" "=r"))]
2608   "TARGET_SHMEDIA
2609    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2610   "*
2611 {
2612 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2613              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2614              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2615              %10 label (tr), %11 label (imm)
2616
2617  muls.l inv1, norm32, scratch0  // s2.60
2618   muls.l inv1, dividend, result // s32.30
2619   xor i2p27, result_sign, round_scratch
2620  bge/u dividend_nsb, i43, tr.. (label)
2621  shari scratch0, 16, scratch0   // s-16.44
2622  muls.l sratch0_si, inv1, scratch0 // s-16.74
2623   sub result, round_scratch, result
2624   shari dividend, 14, scratch1   // s19.-14
2625  shari scratch0, 30, scratch0   // s-16.44
2626  muls.l scratch0, scratch1, round_scratch // s15.30
2627 label:
2628  sub result, round_scratch, result */
2629
2630   int likely = TARGET_DIVIDE_INV20L;
2631
2632   if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2633   output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2634   output_asm_insn (likely
2635                    ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2636                    : \"bge/u\t%4, %6, %10\", operands);
2637   output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2638   if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2639   output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2640   return (likely
2641           ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2642           : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2643 }")
2644
2645 (define_insn_and_split "divsi_inv_fp"
2646   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2647         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2648                 (match_operand:SI 2 "register_operand" "rf")))
2649    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2650    (clobber (match_operand:SI 4 "register_operand" "=r"))
2651    (clobber (match_operand:SI 5 "register_operand" "=r"))
2652    (clobber (match_operand:DF 6 "register_operand" "=r"))
2653    (clobber (match_operand:DF 7 "register_operand" "=r"))
2654    (clobber (match_operand:DF 8 "register_operand" "=r"))]
2655   "TARGET_SHMEDIA_FPU"
2656   "#"
2657   "&& (high_life_started || reload_completed)"
2658   [(set (match_dup 0) (match_dup 3))]
2659   ""
2660   [(set_attr "highpart" "must_split")])
2661
2662 ;; If a matching group of divide-by-inverse instructions is in the same
2663 ;; basic block after gcse & loop optimizations, we want to transform them
2664 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2665 (define_insn_and_split "*divsi_inv_fp_combine"
2666   [(set (match_operand:SI 0 "register_operand" "=f")
2667         (div:SI (match_operand:SI 1 "register_operand" "f")
2668                 (match_operand:SI 2 "register_operand" "f")))
2669    (use (unspec:SI [(match_dup 1)
2670                     (match_operand:SI 3 "" "")
2671                     (unspec:SI [(match_operand:SI 4 "" "")
2672                                 (match_dup 3)
2673                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2674                     (match_operand:DI 6 "" "")
2675                     (const_int 0)
2676                     (const_int 0)] UNSPEC_DIV_INV_M3))
2677    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2678    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2679    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2680    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2681    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2682   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos"
2683   "#"
2684   "&& 1"
2685   [(set (match_dup 9) (float:DF (match_dup 1)))
2686    (set (match_dup 10) (float:DF (match_dup 2)))
2687    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2688    (set (match_dup 8)
2689         (fix:SI (match_dup 11)))
2690    (set (match_dup 0) (match_dup 8))]
2691   "
2692 {
2693   if (! fp_arith_reg_operand (operands[1], SImode))
2694     {
2695       emit_move_insn (operands[7], operands[1]);
2696       operands[1] = operands[7];
2697     }
2698   if (! fp_arith_reg_operand (operands[2], SImode))
2699     {
2700       emit_move_insn (operands[8], operands[2]);
2701       operands[2] = operands[8];
2702     }
2703 }"
2704   [(set_attr "highpart" "must_split")])
2705 \f
2706 ;; -------------------------------------------------------------------------
2707 ;; Multiplication instructions
2708 ;; -------------------------------------------------------------------------
2709
2710 (define_insn "umulhisi3_i"
2711   [(set (reg:SI MACL_REG)
2712         (mult:SI (zero_extend:SI
2713                   (match_operand:HI 0 "arith_reg_operand" "r"))
2714                  (zero_extend:SI
2715                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2716   "TARGET_SH1"
2717   "mulu.w       %1,%0"
2718   [(set_attr "type" "smpy")])
2719
2720 (define_insn "mulhisi3_i"
2721   [(set (reg:SI MACL_REG)
2722         (mult:SI (sign_extend:SI
2723                   (match_operand:HI 0 "arith_reg_operand" "r"))
2724                  (sign_extend:SI
2725                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2726   "TARGET_SH1"
2727   "muls.w       %1,%0"
2728   [(set_attr "type" "smpy")])
2729
2730 (define_expand "mulhisi3"
2731   [(set (reg:SI MACL_REG)
2732         (mult:SI (sign_extend:SI
2733                   (match_operand:HI 1 "arith_reg_operand" ""))
2734                  (sign_extend:SI
2735                   (match_operand:HI 2 "arith_reg_operand" ""))))
2736    (set (match_operand:SI 0 "arith_reg_operand" "")
2737         (reg:SI MACL_REG))]
2738   "TARGET_SH1"
2739   "
2740 {
2741   rtx insn, macl;
2742
2743   macl = gen_rtx_REG (SImode, MACL_REG);
2744   start_sequence ();
2745   emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2746   insn = get_insns ();  
2747   end_sequence ();
2748   /* expand_binop can't find a suitable code in umul_widen_optab to
2749      make a REG_EQUAL note from, so make one here.
2750      See also smulsi3_highpart.
2751      ??? Alternatively, we could put this at the calling site of expand_binop,
2752      i.e. expand_expr.  */
2753   /* Use emit_libcall_block for loop invariant code motion and to make
2754      a REG_EQUAL note.  */
2755   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2756
2757   DONE;
2758 }")
2759
2760 (define_expand "umulhisi3"
2761   [(set (reg:SI MACL_REG)
2762         (mult:SI (zero_extend:SI
2763                   (match_operand:HI 1 "arith_reg_operand" ""))
2764                  (zero_extend:SI
2765                   (match_operand:HI 2 "arith_reg_operand" ""))))
2766    (set (match_operand:SI 0 "arith_reg_operand" "")
2767         (reg:SI MACL_REG))]
2768   "TARGET_SH1"
2769   "
2770 {
2771   rtx insn, macl;
2772
2773   macl = gen_rtx_REG (SImode, MACL_REG);
2774   start_sequence ();
2775   emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2776   insn = get_insns ();  
2777   end_sequence ();
2778   /* expand_binop can't find a suitable code in umul_widen_optab to
2779      make a REG_EQUAL note from, so make one here.
2780      See also smulsi3_highpart.
2781      ??? Alternatively, we could put this at the calling site of expand_binop,
2782      i.e. expand_expr.  */
2783   /* Use emit_libcall_block for loop invariant code motion and to make
2784      a REG_EQUAL note.  */
2785   emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2786
2787   DONE;
2788 }")
2789
2790 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2791 ;; a call to a routine which clobbers known registers.
2792
2793 (define_insn ""
2794   [(set (match_operand:SI 1 "register_operand" "=z")
2795         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2796    (clobber (reg:SI MACL_REG))
2797    (clobber (reg:SI T_REG))
2798    (clobber (reg:SI PR_REG))
2799    (clobber (reg:SI R3_REG))
2800    (clobber (reg:SI R2_REG))
2801    (clobber (reg:SI R1_REG))
2802    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2803   "TARGET_SH1"
2804   "jsr  @%0%#"
2805   [(set_attr "type" "sfunc")
2806    (set_attr "needs_delay_slot" "yes")])
2807
2808 (define_expand "mulsi3_call"
2809   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2810    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2811    (parallel[(set (match_operand:SI 0 "register_operand" "")
2812                   (mult:SI (reg:SI R4_REG)
2813                            (reg:SI R5_REG)))
2814              (clobber (reg:SI MACL_REG))
2815              (clobber (reg:SI T_REG))
2816              (clobber (reg:SI PR_REG))
2817              (clobber (reg:SI R3_REG))
2818              (clobber (reg:SI R2_REG))
2819              (clobber (reg:SI R1_REG))
2820              (use (match_operand:SI 3 "register_operand" ""))])]
2821   "TARGET_SH1"
2822   "")
2823
2824 (define_insn "mul_r"
2825   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2826         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2827                  (match_operand:SI 2 "arith_reg_operand" "z")))]
2828   "TARGET_SH2A"
2829   "mulr %2,%0"
2830   [(set_attr "type" "dmpy")])
2831
2832 (define_insn "mul_l"
2833   [(set (reg:SI MACL_REG)
2834         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2835                  (match_operand:SI 1 "arith_reg_operand" "r")))]
2836   "TARGET_SH2"
2837   "mul.l        %1,%0"
2838   [(set_attr "type" "dmpy")])
2839
2840 (define_expand "mulsi3"
2841   [(set (reg:SI MACL_REG)
2842         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
2843                   (match_operand:SI 2 "arith_reg_operand" "")))
2844    (set (match_operand:SI 0 "arith_reg_operand" "")
2845         (reg:SI MACL_REG))]
2846   "TARGET_SH1"
2847   "
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       emit_insn (insns);
2858     }
2859   else
2860     {
2861       rtx macl = gen_rtx_REG (SImode, MACL_REG);
2862
2863       emit_insn (gen_mul_l (operands[1], operands[2]));
2864       /* consec_sets_giv can only recognize the first insn that sets a
2865          giv as the giv insn.  So we must tag this also with a REG_EQUAL
2866          note.  */
2867       emit_insn (gen_movsi_i ((operands[0]), macl));
2868     }
2869   DONE;
2870 }")
2871
2872 (define_insn "mulsidi3_i"
2873   [(set (reg:SI MACH_REG)
2874         (truncate:SI
2875          (lshiftrt:DI
2876           (mult:DI
2877            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2878            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2879           (const_int 32))))
2880    (set (reg:SI MACL_REG)
2881         (mult:SI (match_dup 0)
2882                  (match_dup 1)))]
2883   "TARGET_SH2"
2884   "dmuls.l      %1,%0"
2885   [(set_attr "type" "dmpy")])
2886
2887 (define_expand "mulsidi3"
2888   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2889         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2890                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2891   "TARGET_SH2 || TARGET_SHMEDIA"
2892   "
2893 {
2894   if (TARGET_SH2)
2895     {
2896        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2897                                         operands[2]));
2898        DONE;
2899     }
2900 }")
2901
2902 (define_insn "mulsidi3_media"
2903   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2904         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2905                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2906   "TARGET_SHMEDIA"
2907   "muls.l       %1, %2, %0"
2908   [(set_attr "type" "dmpy_media")
2909    (set_attr "highpart" "ignore")])
2910
2911 (define_insn "mulsidi3_compact"
2912   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2913         (mult:DI
2914          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2915          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2916    (clobber (reg:SI MACH_REG))
2917    (clobber (reg:SI MACL_REG))]
2918   "TARGET_SH2"
2919   "#")
2920
2921 (define_split
2922   [(set (match_operand:DI 0 "arith_reg_dest" "")
2923         (mult:DI
2924          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2925          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2926    (clobber (reg:SI MACH_REG))
2927    (clobber (reg:SI MACL_REG))]
2928   "TARGET_SH2"
2929   [(const_int 0)]
2930   "
2931 {
2932   rtx low_dst = gen_lowpart (SImode, operands[0]);
2933   rtx high_dst = gen_highpart (SImode, operands[0]);
2934
2935   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2936
2937   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2938   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2939   /* We need something to tag the possible REG_EQUAL notes on to.  */
2940   emit_move_insn (operands[0], operands[0]);
2941   DONE;
2942 }")
2943
2944 (define_insn "umulsidi3_i"
2945   [(set (reg:SI MACH_REG)
2946         (truncate:SI
2947          (lshiftrt:DI
2948           (mult:DI
2949            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2950            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2951           (const_int 32))))
2952    (set (reg:SI MACL_REG)
2953         (mult:SI (match_dup 0)
2954                  (match_dup 1)))]
2955   "TARGET_SH2"
2956   "dmulu.l      %1,%0"
2957   [(set_attr "type" "dmpy")])
2958
2959 (define_expand "umulsidi3"
2960   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2961         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2962                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2963   "TARGET_SH2 || TARGET_SHMEDIA"
2964   "
2965 {
2966   if (TARGET_SH2)
2967     {
2968        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2969                                          operands[2]));
2970        DONE;
2971     }
2972 }")
2973
2974 (define_insn "umulsidi3_media"
2975   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2976         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2977                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2978   "TARGET_SHMEDIA"
2979   "mulu.l       %1, %2, %0"
2980   [(set_attr "type" "dmpy_media")
2981    (set_attr "highpart" "ignore")])
2982
2983 (define_insn "umulsidi3_compact"
2984   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2985         (mult:DI
2986          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2987          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2988    (clobber (reg:SI MACH_REG))
2989    (clobber (reg:SI MACL_REG))]
2990   "TARGET_SH2"
2991   "#")
2992
2993 (define_split
2994   [(set (match_operand:DI 0 "arith_reg_dest" "")
2995         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2996                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2997    (clobber (reg:SI MACH_REG))
2998    (clobber (reg:SI MACL_REG))]
2999   "TARGET_SH2"
3000   [(const_int 0)]
3001   "
3002 {
3003   rtx low_dst = gen_lowpart (SImode, operands[0]);
3004   rtx high_dst = gen_highpart (SImode, operands[0]);
3005
3006   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3007
3008   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3009   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3010   /* We need something to tag the possible REG_EQUAL notes on to.  */
3011   emit_move_insn (operands[0], operands[0]);
3012   DONE;
3013 }")
3014
3015 (define_insn "smulsi3_highpart_i"
3016   [(set (reg:SI MACH_REG)
3017         (truncate:SI
3018          (lshiftrt:DI
3019           (mult:DI
3020            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3021            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3022           (const_int 32))))
3023    (clobber (reg:SI MACL_REG))]
3024   "TARGET_SH2"
3025   "dmuls.l      %1,%0"
3026   [(set_attr "type" "dmpy")])
3027
3028 (define_expand "smulsi3_highpart"
3029   [(parallel
3030     [(set (reg:SI MACH_REG)
3031           (truncate:SI
3032            (lshiftrt:DI
3033             (mult:DI
3034              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3035              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3036             (const_int 32))))
3037     (clobber (reg:SI MACL_REG))])
3038    (set (match_operand:SI 0 "arith_reg_operand" "")
3039         (reg:SI MACH_REG))]
3040   "TARGET_SH2"
3041   "
3042 {
3043   rtx insn, mach;
3044
3045   mach = gen_rtx_REG (SImode, MACH_REG);
3046   start_sequence ();
3047   emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3048   insn = get_insns ();  
3049   end_sequence ();
3050   /* expand_binop can't find a suitable code in mul_highpart_optab to
3051      make a REG_EQUAL note from, so make one here.
3052      See also {,u}mulhisi.
3053      ??? Alternatively, we could put this at the calling site of expand_binop,
3054      i.e. expand_mult_highpart.  */
3055   /* Use emit_libcall_block for loop invariant code motion and to make
3056      a REG_EQUAL note.  */
3057   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3058
3059   DONE;
3060 }")
3061
3062 (define_insn "umulsi3_highpart_i"
3063   [(set (reg:SI MACH_REG)
3064         (truncate:SI
3065          (lshiftrt:DI
3066           (mult:DI
3067            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3068            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3069           (const_int 32))))
3070    (clobber (reg:SI MACL_REG))]
3071   "TARGET_SH2"
3072   "dmulu.l      %1,%0"
3073   [(set_attr "type" "dmpy")])
3074
3075 (define_expand "umulsi3_highpart"
3076   [(parallel
3077     [(set (reg:SI MACH_REG)
3078           (truncate:SI
3079            (lshiftrt:DI
3080             (mult:DI
3081              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3082              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3083             (const_int 32))))
3084     (clobber (reg:SI MACL_REG))])
3085    (set (match_operand:SI 0 "arith_reg_operand" "")
3086         (reg:SI MACH_REG))]
3087   "TARGET_SH2"
3088   "
3089 {
3090   rtx insn, mach;
3091
3092   mach = gen_rtx_REG (SImode, MACH_REG);
3093   start_sequence ();
3094   emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3095   insn = get_insns ();  
3096   end_sequence ();
3097   /* Use emit_libcall_block for loop invariant code motion and to make
3098      a REG_EQUAL note.  */
3099   emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3100
3101   DONE;
3102 }")
3103
3104 (define_insn_and_split "muldi3"
3105   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3106         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3107                  (match_operand:DI 2 "arith_reg_operand" "r")))
3108    (clobber (match_scratch:DI 3 "=&r"))
3109    (clobber (match_scratch:DI 4 "=r"))]
3110   "TARGET_SHMEDIA"
3111   "#"
3112   "reload_completed"
3113   [(const_int 0)]
3114   "
3115 {
3116   rtx op3_v2si, op2_v2si;
3117
3118   op3_v2si = operands[3];
3119   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3120     {
3121       op3_v2si = XEXP (op3_v2si, 0);
3122       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3123     }
3124   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3125   op2_v2si = operands[2];
3126   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3127     {
3128       op2_v2si = XEXP (op2_v2si, 0);
3129       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3130     }
3131   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3132   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3133   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3134   emit_insn (gen_umulsidi3_media (operands[4],
3135                                  sh_gen_truncate (SImode, operands[1], 0),
3136                                  sh_gen_truncate (SImode, operands[2], 0)));
3137   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3138   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3139   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3140   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3141   DONE;
3142 }")
3143
3144 \f
3145 ;; -------------------------------------------------------------------------
3146 ;; Logical operations
3147 ;; -------------------------------------------------------------------------
3148
3149 (define_insn "*andsi3_compact"
3150   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3151         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3152                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3153   "TARGET_SH1"
3154   "and  %2,%0"
3155   [(set_attr "type" "arith")])
3156
3157 (define_insn "*andsi3_media"
3158   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3159         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3160                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3161   "TARGET_SHMEDIA"
3162   "@
3163         and     %1, %2, %0
3164         andi    %1, %2, %0"
3165   [(set_attr "type" "arith_media")])
3166
3167 ;; If the constant is 255, then emit an extu.b instruction instead of an
3168 ;; and, since that will give better code.
3169
3170 (define_expand "andsi3"
3171   [(set (match_operand:SI 0 "arith_reg_operand" "")
3172         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3173                 (match_operand:SI 2 "logical_operand" "")))]
3174   ""
3175   "
3176 {
3177   if (TARGET_SH1
3178       && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
3179     {
3180       emit_insn (gen_zero_extendqisi2 (operands[0],
3181                                        gen_lowpart (QImode, operands[1])));
3182       DONE;
3183     }
3184 }")
3185
3186 (define_insn_and_split "anddi3"
3187   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3188         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3189                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3190   "TARGET_SHMEDIA"
3191   "@
3192         and     %1, %2, %0
3193         andi    %1, %2, %0
3194         #"
3195   "reload_completed
3196    && ! logical_operand (operands[2], DImode)"
3197   [(const_int 0)]
3198   "
3199 {
3200   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3201     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3202   else
3203     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3204   DONE;
3205 }"
3206   [(set_attr "type" "arith_media")])
3207
3208 (define_insn "andcsi3"
3209   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3210         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3211                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3212   "TARGET_SHMEDIA"
3213   "andc %1,%2,%0"
3214   [(set_attr "type" "arith_media")])
3215
3216 (define_insn "andcdi3"
3217   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3218         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3219                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3220   "TARGET_SHMEDIA"
3221   "andc %1,%2,%0"
3222   [(set_attr "type" "arith_media")])
3223
3224 (define_expand "iorsi3"
3225   [(set (match_operand:SI 0 "arith_reg_operand" "")
3226         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3227                 (match_operand:SI 2 "logical_operand" "")))]
3228   ""
3229   "")
3230
3231 (define_insn "*iorsi3_compact"
3232   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3233         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3234                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3235   "TARGET_SH1"
3236   "or   %2,%0"
3237   [(set_attr "type" "arith")])
3238
3239 (define_insn "*iorsi3_media"
3240   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3241         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3242                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3243   "TARGET_SHMEDIA"
3244   "@
3245         or      %1, %2, %0
3246         ori     %1, %2, %0"
3247   [(set_attr "type" "arith_media")])
3248
3249 (define_insn "iordi3"
3250   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3251         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3252                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3253   "TARGET_SHMEDIA"
3254   "@
3255         or      %1, %2, %0
3256         ori     %1, %2, %0"
3257   [(set_attr "type" "arith_media")])
3258
3259 (define_insn_and_split "*logical_sidi3"
3260   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3261         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3262                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3263                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3264   "TARGET_SHMEDIA"
3265   "#"
3266   "&& reload_completed"
3267   [(set (match_dup 0) (match_dup 3))]
3268   "
3269 {
3270   operands[3]
3271     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3272                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3273                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3274 }")
3275
3276 (define_insn_and_split "*logical_sidisi3"
3277   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3278         (truncate:SI (sign_extend:DI
3279                         (match_operator:SI 3 "logical_operator"
3280                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3281                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3282   "TARGET_SHMEDIA"
3283   "#"
3284   "&& 1"
3285   [(set (match_dup 0) (match_dup 3))])
3286
3287 (define_insn_and_split "*logical_sidi3_2"
3288   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3289         (sign_extend:DI (truncate:SI (sign_extend:DI
3290                         (match_operator:SI 3 "logical_operator"
3291                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3292                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3293   "TARGET_SHMEDIA"
3294   "#"
3295   "&& 1"
3296   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3297
3298 (define_expand "xorsi3"
3299   [(set (match_operand:SI 0 "arith_reg_operand" "")
3300         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3301                 (match_operand:SI 2 "xor_operand" "")))]
3302   ""
3303   "")
3304
3305 (define_insn "*xorsi3_compact"
3306   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3307         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3308                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3309   "TARGET_SH1"
3310   "xor  %2,%0"
3311   [(set_attr "type" "arith")])
3312
3313 (define_insn "*xorsi3_media"
3314   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3315         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3316                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3317   "TARGET_SHMEDIA"
3318   "@
3319         xor     %1, %2, %0
3320         xori    %1, %2, %0"
3321   [(set_attr "type" "arith_media")])
3322
3323 (define_insn "xordi3"
3324   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3325         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3326                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3327   "TARGET_SHMEDIA"
3328   "@
3329         xor     %1, %2, %0
3330         xori    %1, %2, %0"
3331   [(set_attr "type" "arith_media")])
3332
3333 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3334 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3335 (define_split
3336   [(set (match_operand:DI 0 "arith_reg_dest" "")
3337         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3338                           [(match_operand 1 "any_register_operand" "")
3339                            (match_operand 2 "any_register_operand" "")])))]
3340   "TARGET_SHMEDIA"
3341   [(set (match_dup 5) (match_dup 4))
3342    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3343 "
3344 {
3345   enum machine_mode inmode = GET_MODE (operands[1]);
3346   int offset = 0;
3347
3348   if (GET_CODE (operands[0]) == SUBREG)
3349     {
3350       offset = SUBREG_BYTE (operands[0]);
3351       operands[0] = SUBREG_REG (operands[0]);
3352     }
3353   gcc_assert (GET_CODE (operands[0]) == REG);
3354   if (! TARGET_LITTLE_ENDIAN)
3355     offset += 8 - GET_MODE_SIZE (inmode);
3356   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3357 }")
3358 \f
3359 ;; -------------------------------------------------------------------------
3360 ;; Shifts and rotates
3361 ;; -------------------------------------------------------------------------
3362
3363 (define_expand "rotldi3"
3364   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3365         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3366                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3367   "TARGET_SHMEDIA"
3368   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3369
3370 (define_insn "rotldi3_mextr"
3371   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3372         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3373                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3374   "TARGET_SHMEDIA"
3375   "*
3376 {
3377   static char templ[16];
3378
3379   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3380            8 - (int) (INTVAL (operands[2]) >> 3));
3381   return templ;
3382 }"
3383   [(set_attr "type" "arith_media")])
3384
3385 (define_expand "rotrdi3"
3386   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3387         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3388                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3389   "TARGET_SHMEDIA"
3390   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3391
3392 (define_insn "rotrdi3_mextr"
3393   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3394         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3395                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3396   "TARGET_SHMEDIA"
3397   "*
3398 {
3399   static char templ[16];
3400
3401   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3402   return templ;
3403 }"
3404   [(set_attr "type" "arith_media")])
3405
3406 (define_split
3407   [(set (match_operand:DI 0 "arith_reg_dest" "")
3408         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3409                                          "ua_address_operand" "")))
3410                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3411                            (const_int 8))))
3412    (clobber (match_operand:DI 3 "register_operand" ""))]
3413   "TARGET_SHMEDIA"
3414   [(match_dup 4) (match_dup 5)]
3415   "
3416 {
3417   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3418                  (operands[3], operands[1]));
3419   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3420                               GEN_INT (56), GEN_INT (8));
3421 }")
3422
3423 (define_insn "rotlsi3_1"
3424   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3425         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3426                    (const_int 1)))
3427    (set (reg:SI T_REG)
3428         (lshiftrt:SI (match_dup 1) (const_int 31)))]
3429   "TARGET_SH1"
3430   "rotl %0"
3431   [(set_attr "type" "arith")])
3432
3433 (define_insn "rotlsi3_31"
3434   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3435         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3436                    (const_int 31)))
3437    (clobber (reg:SI T_REG))]
3438   "TARGET_SH1"
3439   "rotr %0"
3440   [(set_attr "type" "arith")])
3441
3442 (define_insn "rotlsi3_16"
3443   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3444         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3445                    (const_int 16)))]
3446   "TARGET_SH1"
3447   "swap.w       %1,%0"
3448   [(set_attr "type" "arith")])
3449
3450 (define_expand "rotlsi3"
3451   [(set (match_operand:SI 0 "arith_reg_dest" "")
3452         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3453                    (match_operand:SI 2 "immediate_operand" "")))]
3454   "TARGET_SH1"
3455   "
3456 {
3457   static const char rot_tab[] = {
3458     000, 000, 000, 000, 000, 000, 010, 001,
3459     001, 001, 011, 013, 003, 003, 003, 003,
3460     003, 003, 003, 003, 003, 013, 012, 002,
3461     002, 002, 010, 000, 000, 000, 000, 000,
3462   };
3463
3464   int count, choice;
3465
3466   if (GET_CODE (operands[2]) != CONST_INT)
3467     FAIL;
3468   count = INTVAL (operands[2]);
3469   choice = rot_tab[count];
3470   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3471     FAIL;
3472   choice &= 7;
3473   switch (choice)
3474     {
3475     case 0:
3476       emit_move_insn (operands[0], operands[1]);
3477       count -= (count & 16) * 2;
3478       break;
3479     case 3:
3480      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3481      count -= 16;
3482      break;
3483     case 1:
3484     case 2:
3485       {
3486         rtx parts[2];
3487         parts[0] = gen_reg_rtx (SImode);
3488         parts[1] = gen_reg_rtx (SImode);
3489         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3490         emit_move_insn (parts[choice-1], operands[1]);
3491         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3492         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3493         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3494         count = (count & ~16) - 8;
3495       }
3496     }
3497
3498   for (; count > 0; count--)
3499     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3500   for (; count < 0; count++)
3501     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3502
3503   DONE;
3504 }")
3505
3506 (define_insn "*rotlhi3_8"
3507   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3508         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3509                    (const_int 8)))]
3510   "TARGET_SH1"
3511   "swap.b       %1,%0"
3512   [(set_attr "type" "arith")])
3513
3514 (define_expand "rotlhi3"
3515   [(set (match_operand:HI 0 "arith_reg_operand" "")
3516         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3517                    (match_operand:HI 2 "immediate_operand" "")))]
3518   "TARGET_SH1"
3519   "
3520 {
3521   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
3522     FAIL;
3523 }")
3524
3525 ;;
3526 ;; shift left
3527
3528 (define_insn "ashlsi3_sh2a"
3529   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3530         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3531                    (match_operand:SI 2 "arith_reg_operand" "r")))]
3532   "TARGET_SH2A"
3533   "shad %2,%0"
3534   [(set_attr "type" "arith")
3535    (set_attr "length" "4")])
3536
3537 ;; This pattern is used by init_expmed for computing the costs of shift
3538 ;; insns.
3539
3540 (define_insn_and_split "ashlsi3_std"
3541   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3542         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3543                    (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3544    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3545   "TARGET_SH3
3546    || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
3547   "@
3548    shld %2,%0
3549    add  %0,%0
3550    shll%O2      %0
3551    #"
3552   "TARGET_SH3
3553    && reload_completed
3554    && GET_CODE (operands[2]) == CONST_INT
3555    && ! satisfies_constraint_P27 (operands[2])"
3556   [(set (match_dup 3) (match_dup 2))
3557    (parallel
3558     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3559      (clobber (match_dup 4))])]
3560   "operands[4] = gen_rtx_SCRATCH (SImode);"
3561   [(set_attr "length" "*,*,*,4")
3562    (set_attr "type" "dyn_shift,arith,arith,arith")])
3563
3564 (define_insn "ashlhi3_k"
3565   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3566         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3567                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
3568   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
3569   "@
3570         add     %0,%0
3571         shll%O2 %0"
3572   [(set_attr "type" "arith")])
3573
3574 (define_insn "ashlsi3_n"
3575   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3576         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3577                    (match_operand:SI 2 "const_int_operand" "n")))
3578    (clobber (reg:SI T_REG))]
3579   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3580   "#"
3581   [(set (attr "length")
3582         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3583                (const_string "2")
3584                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3585                (const_string "4")
3586                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3587                (const_string "6")]
3588               (const_string "8")))
3589    (set_attr "type" "arith")])
3590
3591 (define_split
3592   [(set (match_operand:SI 0 "arith_reg_dest" "")
3593         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3594                    (match_operand:SI 2 "const_int_operand" "")))
3595    (clobber (reg:SI T_REG))]
3596   "TARGET_SH1 && reload_completed"
3597   [(use (reg:SI R0_REG))]
3598   "
3599 {
3600   gen_shifty_op (ASHIFT, operands);
3601   DONE;
3602 }")
3603
3604 (define_insn "ashlsi3_media"
3605   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3606         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3607                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
3608   "TARGET_SHMEDIA"
3609   "@
3610         shlld.l %1, %2, %0
3611         shlli.l %1, %2, %0"
3612   [(set_attr "type" "arith_media")
3613    (set_attr "highpart" "ignore")])
3614
3615 (define_expand "ashlsi3"
3616   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3617                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3618                               (match_operand:SI 2 "nonmemory_operand" "")))
3619               (clobber (reg:SI T_REG))])]
3620   ""
3621   "
3622 {
3623   if (TARGET_SHMEDIA)
3624     {
3625       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3626       DONE;
3627     }
3628   if (GET_CODE (operands[2]) == CONST_INT
3629       && sh_dynamicalize_shift_p (operands[2]))
3630     operands[2] = force_reg (SImode, operands[2]);
3631   if (TARGET_SH3)
3632     {
3633       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3634       DONE;
3635     }
3636   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3637     FAIL;
3638 }")
3639
3640 (define_insn "*ashlhi3_n"
3641   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3642         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3643                    (match_operand:HI 2 "const_int_operand" "n")))
3644    (clobber (reg:SI T_REG))]
3645   "TARGET_SH1"
3646   "#"
3647   [(set (attr "length")
3648         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3649                (const_string "2")
3650                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3651                (const_string "4")]
3652               (const_string "6")))
3653    (set_attr "type" "arith")])
3654
3655 (define_expand "ashlhi3"
3656   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3657                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3658                               (match_operand:SI 2 "nonmemory_operand" "")))
3659               (clobber (reg:SI T_REG))])]
3660   "TARGET_SH1"
3661   "
3662 {
3663   if (GET_CODE (operands[2]) != CONST_INT)
3664     FAIL;
3665   /* It may be possible to call gen_ashlhi3 directly with more generic
3666      operands.  Make sure operands[1] is a HImode register here.  */
3667   if (!arith_reg_operand (operands[1], HImode))
3668     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3669 }")
3670
3671 (define_split
3672   [(set (match_operand:HI 0 "arith_reg_dest" "")
3673         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3674                    (match_operand:HI 2 "const_int_operand" "")))
3675    (clobber (reg:SI T_REG))]
3676   "TARGET_SH1 && reload_completed"
3677   [(use (reg:SI R0_REG))]
3678   "
3679 {
3680   gen_shifty_hi_op (ASHIFT, operands);
3681   DONE;
3682 }")
3683
3684 ;
3685 ; arithmetic shift right
3686 ;
3687
3688 (define_insn "ashrsi3_sh2a"
3689   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3690         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3691                    (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3692   "TARGET_SH2A"
3693   "shad %2,%0"
3694   [(set_attr "type" "dyn_shift")
3695    (set_attr "length" "4")])
3696
3697 (define_insn "ashrsi3_k"
3698   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3699         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3700                      (match_operand:SI 2 "const_int_operand" "M")))
3701    (clobber (reg:SI T_REG))]
3702   "TARGET_SH1 && INTVAL (operands[2]) == 1"
3703   "shar %0"
3704   [(set_attr "type" "arith")])
3705
3706 ;; We can't do HImode right shifts correctly unless we start out with an
3707 ;; explicit zero / sign extension; doing that would result in worse overall
3708 ;; code, so just let the machine independent code widen the mode.
3709 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3710
3711
3712 ;; ??? This should be a define expand.
3713
3714 (define_insn "ashrsi2_16"
3715   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3716         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3717                      (const_int 16)))]
3718   "TARGET_SH1"
3719   "#"
3720   [(set_attr "length" "4")])
3721
3722 (define_split
3723   [(set (match_operand:SI 0 "arith_reg_dest" "")
3724         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3725                      (const_int 16)))]
3726   "TARGET_SH1"
3727   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3728    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3729   "operands[2] = gen_lowpart (HImode, operands[0]);")
3730
3731 ;; ??? This should be a define expand.
3732
3733 (define_insn "ashrsi2_31"
3734   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3735         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3736                      (const_int 31)))
3737    (clobber (reg:SI T_REG))]
3738   "TARGET_SH1"
3739   "#"
3740   [(set_attr "length" "4")])
3741
3742 (define_split
3743   [(set (match_operand:SI 0 "arith_reg_dest" "")
3744         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3745                      (const_int 31)))
3746    (clobber (reg:SI T_REG))]
3747   "TARGET_SH1"
3748   [(const_int 0)]
3749   "
3750 {
3751   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3752   emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3753   DONE;
3754 }")
3755
3756 (define_peephole2
3757   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3758    (set (reg:SI T_REG)
3759         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3760   "TARGET_SH1
3761    && peep2_reg_dead_p (2, operands[0])
3762    && peep2_reg_dead_p (2, operands[1])"
3763   [(const_int 0)]
3764   "
3765 {
3766   emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3767   DONE;
3768 }")
3769
3770 (define_insn "ashlsi_c"
3771   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3772         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3773    (set (reg:SI T_REG)
3774         (lt:SI (match_dup 1) (const_int 0)))]
3775   "TARGET_SH1"
3776   "shll %0"
3777   [(set_attr "type" "arith")])
3778
3779 (define_insn "*ashlsi_c_void"
3780   [(set (reg:SI T_REG)
3781         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3782    (clobber (match_scratch:SI 1 "=0"))]
3783   "TARGET_SH1 && cse_not_expected"
3784   "shll %0"
3785   [(set_attr "type" "arith")])
3786
3787 (define_insn "ashrsi3_d"
3788   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3789         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3790                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3791   "TARGET_SH3"
3792   "shad %2,%0"
3793   [(set_attr "type" "dyn_shift")])
3794
3795 (define_insn "ashrsi3_n"
3796   [(set (reg:SI R4_REG)
3797         (ashiftrt:SI (reg:SI R4_REG)
3798                      (match_operand:SI 0 "const_int_operand" "i")))
3799    (clobber (reg:SI T_REG))
3800    (clobber (reg:SI PR_REG))
3801    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3802   "TARGET_SH1"
3803   "jsr  @%1%#"
3804   [(set_attr "type" "sfunc")
3805    (set_attr "needs_delay_slot" "yes")])
3806
3807 (define_insn "ashrsi3_media"
3808   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3809         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3810                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3811   "TARGET_SHMEDIA"
3812   "@
3813         shard.l %1, %2, %0
3814         shari.l %1, %2, %0"
3815   [(set_attr "type" "arith_media")
3816    (set_attr "highpart" "ignore")])
3817
3818 (define_expand "ashrsi3"
3819   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3820                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3821                                 (match_operand:SI 2 "nonmemory_operand" "")))
3822               (clobber (reg:SI T_REG))])]
3823   ""
3824   "
3825 {
3826   if (TARGET_SHMEDIA)
3827     {
3828       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3829       DONE;
3830     }
3831   if (expand_ashiftrt (operands))
3832     DONE;
3833   else
3834     FAIL;
3835 }")
3836
3837 ;; logical shift right
3838
3839 (define_insn "lshrsi3_sh2a"
3840   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3841         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3842                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3843   "TARGET_SH2A"
3844   "shld %2,%0"
3845   [(set_attr "type" "dyn_shift")
3846    (set_attr "length" "4")])
3847
3848 (define_insn "lshrsi3_d"
3849   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3850         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3851                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3852   "TARGET_SH3"
3853   "shld %2,%0"
3854   [(set_attr "type" "dyn_shift")])
3855
3856 ;;  Only the single bit shift clobbers the T bit.
3857
3858 (define_insn "lshrsi3_m"
3859   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3860         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3861                      (match_operand:SI 2 "const_int_operand" "M")))
3862    (clobber (reg:SI T_REG))]
3863   "TARGET_SH1 && satisfies_constraint_M (operands[2])"
3864   "shlr %0"
3865   [(set_attr "type" "arith")])
3866
3867 (define_insn "lshrsi3_k"
3868   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3869         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3870                      (match_operand:SI 2 "const_int_operand" "P27")))]
3871   "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
3872    && ! satisfies_constraint_M (operands[2])"
3873   "shlr%O2      %0"
3874   [(set_attr "type" "arith")])
3875
3876 (define_insn "lshrsi3_n"
3877   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3878         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3879                      (match_operand:SI 2 "const_int_operand" "n")))
3880    (clobber (reg:SI T_REG))]
3881   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3882   "#"
3883   [(set (attr "length")
3884         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3885                (const_string "2")
3886                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3887                (const_string "4")
3888                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3889                (const_string "6")]
3890               (const_string "8")))
3891    (set_attr "type" "arith")])
3892
3893 (define_split
3894   [(set (match_operand:SI 0 "arith_reg_dest" "")
3895         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3896                      (match_operand:SI 2 "const_int_operand" "")))
3897    (clobber (reg:SI T_REG))]
3898   "TARGET_SH1 && reload_completed"
3899   [(use (reg:SI R0_REG))]
3900   "
3901 {
3902   gen_shifty_op (LSHIFTRT, operands);
3903   DONE;
3904 }")
3905
3906 (define_insn "lshrsi3_media"
3907   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3908         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3909                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3910   "TARGET_SHMEDIA"
3911   "@
3912         shlrd.l %1, %2, %0
3913         shlri.l %1, %2, %0"
3914   [(set_attr "type" "arith_media")
3915    (set_attr "highpart" "ignore")])
3916
3917 (define_expand "lshrsi3"
3918   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3919                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3920                                 (match_operand:SI 2 "nonmemory_operand" "")))
3921               (clobber (reg:SI T_REG))])]
3922   ""
3923   "
3924 {
3925   if (TARGET_SHMEDIA)
3926     {
3927       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3928       DONE;
3929     }
3930   if (GET_CODE (operands[2]) == CONST_INT
3931       && sh_dynamicalize_shift_p (operands[2]))
3932     operands[2] = force_reg (SImode, operands[2]);
3933   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3934     {
3935       rtx count = copy_to_mode_reg (SImode, operands[2]);
3936       emit_insn (gen_negsi2 (count, count));
3937       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3938       DONE;
3939     }
3940   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3941     FAIL;
3942 }")
3943
3944 ;; ??? This should be a define expand.
3945
3946 (define_insn "ashldi3_k"
3947   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3948         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3949                    (const_int 1)))
3950    (clobber (reg:SI T_REG))]
3951   "TARGET_SH1"
3952   "shll %R0\;rotcl      %S0"
3953   [(set_attr "length" "4")
3954    (set_attr "type" "arith")])
3955
3956 (define_insn "ashldi3_media"
3957   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3958         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3959                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
3960   "TARGET_SHMEDIA"
3961   "@
3962         shlld   %1, %2, %0
3963         shlli   %1, %2, %0"
3964   [(set_attr "type" "arith_media")])
3965
3966 (define_insn "*ashldisi3_media"
3967   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3968         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3969                    (match_operand:DI 2 "const_int_operand" "n")))]
3970   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3971   "shlli.l      %1, %2, %0"
3972   [(set_attr "type" "arith_media")
3973    (set_attr "highpart" "ignore")])
3974
3975 (define_expand "ashldi3"
3976   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3977                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3978                               (match_operand:DI 2 "immediate_operand" "")))
3979               (clobber (reg:SI T_REG))])]
3980   ""
3981   "
3982 {
3983   if (TARGET_SHMEDIA)
3984     {
3985       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3986       DONE;
3987     }
3988   if (GET_CODE (operands[2]) != CONST_INT
3989       || INTVAL (operands[2]) != 1)
3990     FAIL;
3991 }")
3992
3993 ;; ??? This should be a define expand.
3994
3995 (define_insn "lshrdi3_k"
3996   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3997         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3998                      (const_int 1)))
3999    (clobber (reg:SI T_REG))]
4000   "TARGET_SH1"
4001   "shlr %S0\;rotcr      %R0"
4002   [(set_attr "length" "4")
4003    (set_attr "type" "arith")])
4004
4005 (define_insn "lshrdi3_media"
4006   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4007         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4008                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4009   "TARGET_SHMEDIA
4010    && (arith_reg_dest (operands[0], DImode)
4011        || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 32))"
4012   "@
4013         shlrd   %1, %2, %0
4014         shlri   %1, %2, %0"
4015   [(set_attr "type" "arith_media")])
4016
4017 (define_insn "*lshrdisi3_media"
4018   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4019         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4020                      (match_operand:DI 2 "const_int_operand" "n")))]
4021   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4022   "shlri.l      %1, %2, %0"
4023   [(set_attr "type" "arith_media")
4024    (set_attr "highpart" "ignore")])
4025
4026 (define_expand "lshrdi3"
4027   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4028                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4029                                (match_operand:DI 2 "immediate_operand" "")))
4030              (clobber (reg:SI T_REG))])]
4031   ""
4032   "
4033 {
4034   if (TARGET_SHMEDIA)
4035     {
4036       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
4037       DONE;
4038     }
4039   if (GET_CODE (operands[2]) != CONST_INT
4040       || INTVAL (operands[2]) != 1)
4041     FAIL;
4042 }")
4043
4044 ;; ??? This should be a define expand.
4045
4046 (define_insn "ashrdi3_k"
4047   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4048         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4049                      (const_int 1)))
4050    (clobber (reg:SI T_REG))]
4051   "TARGET_SH1"
4052   "shar %S0\;rotcr      %R0"
4053   [(set_attr "length" "4")
4054    (set_attr "type" "arith")])
4055
4056 (define_insn "ashrdi3_media"
4057   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4058         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4059                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4060   "TARGET_SHMEDIA
4061    && (arith_reg_dest (operands[0], DImode)
4062        || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32))"
4063   "@
4064         shard   %1, %2, %0
4065         shari   %1, %2, %0"
4066   [(set_attr "type" "arith_media")])
4067
4068 (define_insn "*ashrdisi3_media"
4069   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4070         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4071                      (match_operand:DI 2 "const_int_operand" "n")))]
4072   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4073   "shari.l      %1, %2, %0"
4074   [(set_attr "type" "arith_media")
4075    (set_attr "highpart" "ignore")])
4076
4077 (define_insn "ashrdisi3_media_high"
4078   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4079         (truncate:SI
4080            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4081                         (match_operand:DI 2 "const_int_operand" "n"))))]
4082   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4083   "shari        %1, %2, %0"
4084   [(set_attr "type" "arith_media")])
4085
4086 (define_insn "ashrdisi3_media_opaque"
4087   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4088         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4089                     (match_operand:DI 2 "const_int_operand" "n")]
4090          UNSPEC_ASHIFTRT))]
4091   "TARGET_SHMEDIA"
4092   "shari        %1, %2, %0"
4093   [(set_attr "type" "arith_media")])
4094
4095 (define_expand "ashrdi3"
4096   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4097                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4098                                 (match_operand:DI 2 "immediate_operand" "")))
4099               (clobber (reg:SI T_REG))])]
4100   ""
4101   "
4102 {
4103   if (TARGET_SHMEDIA)
4104     {
4105       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4106       DONE;
4107     }
4108   if (GET_CODE (operands[2]) != CONST_INT
4109       || INTVAL (operands[2]) != 1)
4110     FAIL;
4111 }")
4112
4113 ;; combined left/right shift
4114
4115 (define_split
4116   [(set (match_operand:SI 0 "register_operand" "")
4117         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4118                            (match_operand:SI 2 "const_int_operand" ""))
4119                 (match_operand:SI 3 "const_int_operand" "")))]
4120   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4121   [(use (reg:SI R0_REG))]
4122   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4123    DONE;")
4124
4125 (define_split
4126   [(set (match_operand:SI 0 "register_operand" "")
4127         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4128                            (match_operand:SI 2 "const_int_operand" ""))
4129                 (match_operand:SI 3 "const_int_operand" "")))
4130    (clobber (reg:SI T_REG))]
4131   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4132   [(use (reg:SI R0_REG))]
4133   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4134    DONE;")
4135
4136 (define_insn ""
4137   [(set (match_operand:SI 0 "register_operand" "=r")
4138         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4139                            (match_operand:SI 2 "const_int_operand" "n"))
4140                 (match_operand:SI 3 "const_int_operand" "n")))
4141    (clobber (reg:SI T_REG))]
4142   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4143  "#"
4144   [(set (attr "length")
4145         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4146                (const_string "4")
4147                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4148                (const_string "6")
4149                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4150                (const_string "8")
4151                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4152                (const_string "10")
4153                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4154                (const_string "12")
4155                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4156                (const_string "14")
4157                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4158                (const_string "16")]
4159               (const_string "18")))
4160    (set_attr "type" "arith")])
4161
4162 (define_insn ""
4163   [(set (match_operand:SI 0 "register_operand" "=z")
4164         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4165                            (match_operand:SI 2 "const_int_operand" "n"))
4166                 (match_operand:SI 3 "const_int_operand" "n")))
4167    (clobber (reg:SI T_REG))]
4168   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4169  "#"
4170   [(set (attr "length")
4171         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4172                (const_string "4")
4173                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4174                (const_string "6")
4175                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4176                (const_string "8")]
4177               (const_string "10")))
4178    (set_attr "type" "arith")])
4179
4180 ;; shift left / and combination with a scratch register: The combine pass
4181 ;; does not accept the individual instructions, even though they are
4182 ;; cheap.  But it needs a precise description so that it is usable after
4183 ;; reload.
4184 (define_insn "and_shl_scratch"
4185   [(set (match_operand:SI 0 "register_operand" "=r,&r")
4186         (lshiftrt:SI
4187          (ashift:SI
4188           (and:SI
4189            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4190                         (match_operand:SI 2 "const_int_operand" "N,n"))
4191            (match_operand:SI 3 "" "0,r"))
4192           (match_operand:SI 4 "const_int_operand" "n,n"))
4193          (match_operand:SI 5 "const_int_operand" "n,n")))
4194    (clobber (reg:SI T_REG))]
4195   "TARGET_SH1"
4196   "#"
4197   [(set (attr "length")
4198         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4199                (const_string "4")
4200                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4201                (const_string "6")
4202                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4203                (const_string "8")
4204                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4205                (const_string "10")]
4206               (const_string "12")))
4207    (set_attr "type" "arith")])
4208
4209 (define_split
4210   [(set (match_operand:SI 0 "register_operand" "")
4211         (lshiftrt:SI
4212          (ashift:SI
4213           (and:SI
4214            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4215                         (match_operand:SI 2 "const_int_operand" ""))
4216            (match_operand:SI 3 "register_operand" ""))
4217           (match_operand:SI 4 "const_int_operand" ""))
4218          (match_operand:SI 5 "const_int_operand" "")))
4219    (clobber (reg:SI T_REG))]
4220   "TARGET_SH1"
4221   [(use (reg:SI R0_REG))]
4222   "
4223 {
4224   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4225
4226   if (INTVAL (operands[2]))
4227     {
4228       gen_shifty_op (LSHIFTRT, operands);
4229     }
4230   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4231   operands[2] = operands[4];
4232   gen_shifty_op (ASHIFT, operands);
4233   if (INTVAL (operands[5]))
4234     {
4235       operands[2] = operands[5];
4236       gen_shifty_op (LSHIFTRT, operands);
4237     }
4238   DONE;
4239 }")
4240
4241 ;; signed left/right shift combination.
4242 (define_split
4243   [(set (match_operand:SI 0 "register_operand" "")
4244         (sign_extract:SI
4245          (ashift:SI (match_operand:SI 1 "register_operand" "")
4246                     (match_operand:SI 2 "const_int_operand" ""))
4247          (match_operand:SI 3 "const_int_operand" "")
4248          (const_int 0)))
4249    (clobber (reg:SI T_REG))]
4250   "TARGET_SH1"
4251   [(use (reg:SI R0_REG))]
4252   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4253    DONE;")
4254
4255 (define_insn "shl_sext_ext"
4256   [(set (match_operand:SI 0 "register_operand" "=r")
4257         (sign_extract:SI
4258          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4259                     (match_operand:SI 2 "const_int_operand" "n"))
4260          (match_operand:SI 3 "const_int_operand" "n")
4261          (const_int 0)))
4262    (clobber (reg:SI T_REG))]
4263   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4264   "#"
4265   [(set (attr "length")
4266         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
4267                (const_string "2")
4268                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4269                (const_string "4")
4270                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4271                (const_string "6")
4272                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4273                (const_string "8")
4274                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4275                (const_string "10")
4276                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4277                (const_string "12")
4278                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4279                (const_string "14")
4280                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4281                (const_string "16")]
4282               (const_string "18")))
4283     (set_attr "type" "arith")])
4284
4285 (define_insn "shl_sext_sub"
4286   [(set (match_operand:SI 0 "register_operand" "=z")
4287         (sign_extract:SI
4288          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4289                     (match_operand:SI 2 "const_int_operand" "n"))
4290          (match_operand:SI 3 "const_int_operand" "n")
4291          (const_int 0)))
4292    (clobber (reg:SI T_REG))]
4293   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4294   "#"
4295   [(set (attr "length")
4296         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4297                (const_string "6")
4298                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4299                (const_string "8")
4300                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4301                (const_string "10")
4302                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4303                (const_string "12")]
4304               (const_string "14")))
4305     (set_attr "type" "arith")])
4306
4307 ;; These patterns are found in expansions of DImode shifts by 16, and
4308 ;; allow the xtrct instruction to be generated from C source.
4309
4310 (define_insn "xtrct_left"
4311   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4312         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4313                            (const_int 16))
4314                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4315                              (const_int 16))))]
4316   "TARGET_SH1"
4317   "xtrct        %1,%0"
4318   [(set_attr "type" "arith")])
4319
4320 (define_insn "xtrct_right"
4321   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4322         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4323                              (const_int 16))
4324                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4325                            (const_int 16))))]
4326   "TARGET_SH1"
4327   "xtrct        %2,%0"
4328   [(set_attr "type" "arith")])
4329
4330 ;; -------------------------------------------------------------------------
4331 ;; Unary arithmetic
4332 ;; -------------------------------------------------------------------------
4333
4334 (define_insn "negc"
4335   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4336         (neg:SI (plus:SI (reg:SI T_REG)
4337                          (match_operand:SI 1 "arith_reg_operand" "r"))))
4338    (set (reg:SI T_REG)
4339         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4340                (const_int 0)))]
4341   "TARGET_SH1"
4342   "negc %1,%0"
4343   [(set_attr "type" "arith")])
4344
4345 (define_insn "*negdi_media"
4346   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4347         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4348   "TARGET_SHMEDIA"
4349   "sub  r63, %1, %0"
4350   [(set_attr "type" "arith_media")])
4351
4352 (define_expand "negdi2"
4353   [(set (match_operand:DI 0 "arith_reg_operand" "")
4354         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
4355   ""
4356   "
4357 {
4358   if (TARGET_SH1)
4359     {
4360       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4361       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4362
4363       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4364       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4365
4366       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4367       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4368
4369       emit_insn (gen_clrt ());
4370       emit_insn (gen_negc (low_dst, low_src));
4371       emit_insn (gen_negc (high_dst, high_src));
4372       DONE;
4373     }
4374 }")
4375
4376 (define_insn "negsi2"
4377   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4378         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4379   "TARGET_SH1"
4380   "neg  %1,%0"
4381   [(set_attr "type" "arith")])
4382
4383 (define_insn "one_cmplsi2"
4384   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4385         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4386   "TARGET_SH1"
4387   "not  %1,%0"
4388   [(set_attr "type" "arith")])
4389
4390 (define_expand "one_cmpldi2"
4391   [(set (match_operand:DI 0 "arith_reg_dest" "")
4392         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4393                 (const_int -1)))]
4394   "TARGET_SHMEDIA" "")
4395
4396 /* The SH4 202 can do zero-offset branches without pipeline stalls.
4397    This can be used as some kind of conditional execution, which is useful
4398    for abs.  */
4399 (define_split
4400   [(set (match_operand:SI 0 "arith_reg_dest" "")
4401         (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
4402                          (match_operand:SI 1 "arith_reg_operand" ""))
4403                  (reg:SI T_REG)))]
4404   "TARGET_HARD_SH4"
4405   [(const_int 0)]
4406   "emit_insn (gen_movsi_i (operands[0], operands[1]));
4407    emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
4408    DONE;")
4409
4410 (define_insn "cneg"
4411   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4412         (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
4413                       (match_operand:SI 1 "arith_reg_operand" "0")
4414                       (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4415   "TARGET_HARD_SH4"
4416   "bf 0f\;neg %2,%0\\n0:"
4417   [(set_attr "type" "arith") ;; poor approximation
4418    (set_attr "length" "4")])
4419
4420 \f
4421 ;; -------------------------------------------------------------------------
4422 ;; Zero extension instructions
4423 ;; -------------------------------------------------------------------------
4424
4425 (define_insn "zero_extendsidi2"
4426   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4427         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4428   "TARGET_SHMEDIA"
4429   "addz.l       %1, r63, %0"
4430   [(set_attr "type" "arith_media")
4431    (set_attr "highpart" "extend")])
4432
4433 (define_insn "zero_extendhidi2"
4434   [(set (match_operand:DI 0 "register_operand" "=r,r")
4435         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4436   "TARGET_SHMEDIA"
4437   "@
4438         #
4439         ld%M1.uw        %m1, %0"
4440   [(set_attr "type" "*,load_media")
4441    (set (attr "highpart")
4442         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4443                (const_string "user")]
4444               (const_string "ignore")))])
4445
4446 (define_split
4447   [(set (match_operand:DI 0 "register_operand" "")
4448         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4449   "TARGET_SHMEDIA && reload_completed"
4450   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4451    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4452   "
4453 {
4454   if (GET_CODE (operands[1]) == TRUNCATE)
4455     operands[1] = XEXP (operands[1], 0);
4456 }")
4457
4458 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4459 ;; reload the entire truncate expression.
4460 (define_insn_and_split "*loaddi_trunc"
4461   [(set (match_operand 0 "any_register_operand" "=r")
4462         (truncate (match_operand:DI 1 "memory_operand" "m")))]
4463   "TARGET_SHMEDIA && reload_completed"
4464   "#"
4465   "TARGET_SHMEDIA && reload_completed"
4466   [(set (match_dup 0) (match_dup 1))]
4467   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4468
4469 (define_insn "zero_extendqidi2"
4470   [(set (match_operand:DI 0 "register_operand" "=r,r")
4471         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4472   "TARGET_SHMEDIA"
4473   "@
4474         andi    %1, 255, %0
4475         ld%M1.ub        %m1, %0"
4476   [(set_attr "type" "arith_media,load_media")
4477    (set (attr "highpart")
4478         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4479                (const_string "user")]
4480               (const_string "ignore")))])
4481
4482 (define_expand "zero_extendhisi2"
4483   [(set (match_operand:SI 0 "arith_reg_operand" "")
4484         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4485   ""
4486   "
4487 {
4488   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4489     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4490 }")
4491
4492 (define_insn "*zero_extendhisi2_compact"
4493   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4494         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4495   "TARGET_SH1"
4496   "extu.w       %1,%0"
4497   [(set_attr "type" "arith")])
4498
4499 (define_insn "*zero_extendhisi2_media"
4500   [(set (match_operand:SI 0 "register_operand" "=r,r")
4501         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4502   "TARGET_SHMEDIA"
4503   "@
4504         #
4505         ld%M1.uw        %m1, %0"
4506   [(set_attr "type" "arith_media,load_media")
4507    (set (attr "highpart")
4508         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4509                (const_string "user")]
4510               (const_string "ignore")))])
4511
4512 (define_split
4513   [(set (match_operand:SI 0 "register_operand" "")
4514         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4515   "TARGET_SHMEDIA && reload_completed"
4516   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4517    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4518   "
4519 {
4520   rtx op1 = operands[1];
4521
4522   if (GET_CODE (op1) == TRUNCATE)
4523     op1 = XEXP (op1, 0);
4524   operands[2]
4525     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4526                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4527 }")
4528
4529 (define_expand "zero_extendqisi2"
4530   [(set (match_operand:SI 0 "arith_reg_operand" "")
4531         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4532   ""
4533   "
4534 {
4535   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4536     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4537 }")
4538
4539 (define_insn "*zero_extendqisi2_compact"
4540   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4541         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4542   "TARGET_SH1"
4543   "extu.b       %1,%0"
4544   [(set_attr "type" "arith")])
4545
4546 (define_insn "*zero_extendqisi2_media"
4547   [(set (match_operand:SI 0 "register_operand" "=r,r")
4548         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4549   "TARGET_SHMEDIA"
4550   "@
4551         andi    %1, 255, %0
4552         ld%M1.ub        %m1, %0"
4553   [(set_attr "type" "arith_media,load_media")
4554    (set (attr "highpart")
4555         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4556                (const_string "user")]
4557               (const_string "ignore")))])
4558
4559 (define_insn "zero_extendqihi2"
4560   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4561         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4562   "TARGET_SH1"
4563   "extu.b       %1,%0"
4564   [(set_attr "type" "arith")])
4565
4566 ;; -------------------------------------------------------------------------
4567 ;; Sign extension instructions
4568 ;; -------------------------------------------------------------------------
4569
4570 ;; ??? This should be a define expand.
4571 ;; ??? Or perhaps it should be dropped?
4572
4573 ;; convert_move generates good code for SH[1-4].
4574 (define_insn "extendsidi2"
4575   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4576         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4577   "TARGET_SHMEDIA"
4578   "@
4579         add.l   %1, r63, %0
4580         ld%M1.l %m1, %0
4581         fmov.sl %1, %0"
4582   [(set_attr "type" "arith_media,load_media,fpconv_media")
4583    (set (attr "highpart")
4584         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4585                (const_string "user")]
4586               (const_string "extend")))])
4587
4588 (define_insn "extendhidi2"
4589   [(set (match_operand:DI 0 "register_operand" "=r,r")
4590         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4591   "TARGET_SHMEDIA"
4592   "@
4593         #
4594         ld%M1.w %m1, %0"
4595   [(set_attr "type" "*,load_media")
4596    (set (attr "highpart")
4597         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4598                (const_string "user")]
4599               (const_string "ignore")))])
4600
4601 (define_split
4602   [(set (match_operand:DI 0 "register_operand" "")
4603         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4604   "TARGET_SHMEDIA && reload_completed"
4605   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4606    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4607   "
4608 {
4609   if (GET_CODE (operands[1]) == TRUNCATE)
4610     operands[1] = XEXP (operands[1], 0);
4611 }")
4612
4613 (define_insn "extendqidi2"
4614   [(set (match_operand:DI 0 "register_operand" "=r,r")
4615         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4616   "TARGET_SHMEDIA"
4617   "@
4618         #
4619         ld%M1.b %m1, %0"
4620   [(set_attr "type" "*,load_media")
4621    (set (attr "highpart")
4622         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4623                (const_string "user")]
4624               (const_string "ignore")))])
4625
4626 (define_split
4627   [(set (match_operand:DI 0 "register_operand" "")
4628         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4629   "TARGET_SHMEDIA && reload_completed"
4630   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4631    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4632   "
4633 {
4634   if (GET_CODE (operands[1]) == TRUNCATE)
4635     operands[1] = XEXP (operands[1], 0);
4636 }")
4637
4638 (define_expand "extendhisi2"
4639   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4640         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4641   ""
4642   "")
4643
4644 (define_insn "*extendhisi2_compact"
4645   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4646         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4647   "TARGET_SH1"
4648   "@
4649         exts.w  %1,%0
4650         mov.w   %1,%0"
4651   [(set_attr "type" "arith,load")])
4652
4653 (define_insn "*extendhisi2_media"
4654   [(set (match_operand:SI 0 "register_operand" "=r,r")
4655         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4656   "TARGET_SHMEDIA"
4657   "@
4658         #
4659         ld%M1.w %m1, %0"
4660   [(set_attr "type" "arith_media,load_media")
4661    (set (attr "highpart")
4662         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4663                (const_string "user")]
4664               (const_string "ignore")))])
4665
4666 (define_split
4667   [(set (match_operand:SI 0 "register_operand" "")
4668         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4669   "TARGET_SHMEDIA && reload_completed"
4670   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4671    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4672   "
4673 {
4674   rtx op1 = operands[1];
4675   if (GET_CODE (op1) == TRUNCATE)
4676     op1 = XEXP (op1, 0);
4677   operands[2]
4678     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4679                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4680 }")
4681
4682 (define_expand "extendqisi2"
4683   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4684         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4685   ""
4686   "")
4687
4688 (define_insn "*extendqisi2_compact"
4689   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4690         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4691   "TARGET_SH1"
4692   "@
4693         exts.b  %1,%0
4694         mov.b   %1,%0"
4695   [(set_attr "type" "arith,load")])
4696
4697 (define_insn "*extendqisi2_media"
4698   [(set (match_operand:SI 0 "register_operand" "=r,r")
4699         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4700   "TARGET_SHMEDIA"
4701   "@
4702         #
4703         ld%M1.b %m1, %0"
4704   [(set_attr "type" "arith_media,load_media")
4705    (set (attr "highpart")
4706         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4707                (const_string "user")]
4708               (const_string "ignore")))])
4709
4710 (define_split
4711   [(set (match_operand:SI 0 "register_operand" "")
4712         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4713   "TARGET_SHMEDIA && reload_completed"
4714   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4715    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4716    "
4717 {
4718   rtx op1 = operands[1];
4719   if (GET_CODE (op1) == TRUNCATE)
4720     op1 = XEXP (op1, 0);
4721   operands[2]
4722     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4723                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4724 }")
4725
4726 (define_insn "extendqihi2"
4727   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4728         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4729   "TARGET_SH1"
4730   "@
4731         exts.b  %1,%0
4732         mov.b   %1,%0"
4733   [(set_attr "type" "arith,load")])
4734
4735 /* It would seem useful to combine the truncXi patterns into the movXi
4736    patterns, but unary operators are ignored when matching constraints,
4737    so we need separate patterns.  */
4738 (define_insn "truncdisi2"
4739   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4740         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4741   "TARGET_SHMEDIA"
4742   "@
4743         add.l   %1, r63, %0
4744         st%M0.l %m0, %1
4745         fst%M0.s        %m0, %T1
4746         fmov.ls %1, %0
4747         fmov.sl %T1, %0
4748         fmov.s  %T1, %0"
4749   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4750    (set (attr "highpart")
4751         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4752                (const_string "user")]
4753               (const_string "extend")))])
4754
4755 (define_insn "truncdihi2"
4756   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4757         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4758   "TARGET_SHMEDIA"
4759   "@
4760         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4761         st%M0.w %m0, %1"
4762   [(set_attr "type"   "arith_media,store_media")
4763    (set_attr "length" "8,4")
4764    (set (attr "highpart")
4765         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4766                (const_string "user")]
4767               (const_string "extend")))])
4768
4769 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4770 ; Because we use zero extension, we can't provide signed QImode compares
4771 ; using a simple compare or conditional branch insn.
4772 (define_insn "truncdiqi2"
4773   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4774         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4775   "TARGET_SHMEDIA"
4776   "@
4777         andi    %1, 255, %0
4778         st%M0.b %m0, %1"
4779   [(set_attr "type"   "arith_media,store")
4780    (set (attr "highpart")
4781         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4782                (const_string "user")]
4783               (const_string "extend")))])
4784 ;; -------------------------------------------------------------------------
4785 ;; Move instructions
4786 ;; -------------------------------------------------------------------------
4787
4788 ;; define push and pop so it is easy for sh.c
4789 ;; We can't use push and pop on SHcompact because the stack must always
4790 ;; be 8-byte aligned.
4791
4792 (define_expand "push"
4793   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4794         (match_operand:SI 0 "register_operand" "r,l,x"))]
4795   "TARGET_SH1 && ! TARGET_SH5"
4796   "")
4797
4798 (define_expand "pop"
4799   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4800         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
4801   "TARGET_SH1 && ! TARGET_SH5"
4802   "")
4803
4804 (define_expand "push_e"
4805   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4806                    (match_operand:SF 0 "" ""))
4807               (use (reg:PSI FPSCR_REG))
4808               (clobber (scratch:SI))])]
4809   "TARGET_SH1 && ! TARGET_SH5"
4810   "")
4811
4812 (define_insn "push_fpul"
4813   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4814   "TARGET_SH2E && ! TARGET_SH5"
4815   "sts.l        fpul,@-r15"
4816   [(set_attr "type" "fstore")
4817    (set_attr "late_fp_use" "yes")
4818    (set_attr "hit_stack" "yes")])
4819
4820 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4821 ;; so use that.
4822 (define_expand "push_4"
4823   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4824                    (match_operand:DF 0 "" ""))
4825               (use (reg:PSI FPSCR_REG))
4826               (clobber (scratch:SI))])]
4827   "TARGET_SH1 && ! TARGET_SH5"
4828   "")
4829
4830 (define_expand "pop_e"
4831   [(parallel [(set (match_operand:SF 0 "" "")
4832               (mem:SF (post_inc:SI (reg:SI SP_REG))))
4833               (use (reg:PSI FPSCR_REG))
4834               (clobber (scratch:SI))])]
4835   "TARGET_SH1 && ! TARGET_SH5"
4836   "")
4837
4838 (define_insn "pop_fpul"
4839   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4840   "TARGET_SH2E && ! TARGET_SH5"
4841   "lds.l        @r15+,fpul"
4842   [(set_attr "type" "load")
4843    (set_attr "hit_stack" "yes")])
4844
4845 (define_expand "pop_4"
4846   [(parallel [(set (match_operand:DF 0 "" "")
4847                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
4848               (use (reg:PSI FPSCR_REG))
4849               (clobber (scratch:SI))])]
4850   "TARGET_SH1 && ! TARGET_SH5"
4851   "")
4852
4853 (define_expand "push_fpscr"
4854   [(const_int 0)]
4855   "TARGET_SH2E"
4856   "
4857 {
4858   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4859                                                  gen_rtx_PRE_DEC (Pmode,
4860                                                           stack_pointer_rtx)),
4861                                         get_fpscr_rtx ()));
4862   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4863   DONE;
4864 }")
4865
4866 (define_expand "pop_fpscr"
4867   [(const_int 0)]
4868   "TARGET_SH2E"
4869   "
4870 {
4871   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4872                                         gen_frame_mem (PSImode,
4873                                                  gen_rtx_POST_INC (Pmode,
4874                                                           stack_pointer_rtx))));
4875   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4876   DONE;
4877 }")
4878
4879 ;; These two patterns can happen as the result of optimization, when
4880 ;; comparisons get simplified to a move of zero or 1 into the T reg.
4881 ;; They don't disappear completely, because the T reg is a fixed hard reg.
4882
4883 (define_insn "clrt"
4884   [(set (reg:SI T_REG) (const_int 0))]
4885   "TARGET_SH1"
4886   "clrt")
4887
4888 (define_insn "sett"
4889   [(set (reg:SI T_REG) (const_int 1))]
4890   "TARGET_SH1"
4891   "sett")
4892
4893 ;; t/r must come after r/r, lest reload will try to reload stuff like
4894 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
4895 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
4896 (define_insn "movsi_i"
4897   [(set (match_operand:SI 0 "general_movdst_operand"
4898             "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
4899         (match_operand:SI 1 "general_movsrc_operand"
4900          "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
4901   "TARGET_SH1
4902    && ! TARGET_SH2E
4903    && ! TARGET_SH2A
4904    && (register_operand (operands[0], SImode)
4905        || register_operand (operands[1], SImode))"
4906   "@
4907         mov.l   %1,%0
4908         mov     %1,%0
4909         mov     %1,%0
4910         cmp/pl  %1
4911         mov.l   %1,%0
4912         sts     %1,%0
4913         sts     %1,%0
4914         movt    %0
4915         mov.l   %1,%0
4916         sts.l   %1,%0
4917         sts.l   %1,%0
4918         lds     %1,%0
4919         lds     %1,%0
4920         lds.l   %1,%0
4921         lds.l   %1,%0
4922         fake    %1,%0"
4923   [(set_attr "type" "pcload_si,move,movi8,mt_group,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
4924    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
4925
4926 ;; t/r must come after r/r, lest reload will try to reload stuff like
4927 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
4928 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
4929 ;; will require a reload.
4930 ;; ??? We can't include f/f because we need the proper FPSCR setting when
4931 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
4932 (define_insn "movsi_ie"
4933   [(set (match_operand:SI 0 "general_movdst_operand"
4934             "=r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
4935         (match_operand:SI 1 "general_movsrc_operand"
4936          "Q,r,I08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
4937   "(TARGET_SH2E || TARGET_SH2A)
4938    && (register_operand (operands[0], SImode)
4939        || register_operand (operands[1], SImode))"
4940   "@
4941         mov.l   %1,%0
4942         mov     %1,%0
4943         mov     %1,%0
4944         movi20  %1,%0
4945         cmp/pl  %1
4946         mov.l   %1,%0
4947         sts     %1,%0
4948         sts     %1,%0
4949         movt    %0
4950         mov.l   %1,%0
4951         sts.l   %1,%0
4952         sts.l   %1,%0
4953         lds     %1,%0
4954         lds     %1,%0
4955         lds.l   %1,%0
4956         lds.l   %1,%0
4957         lds.l   %1,%0
4958         sts.l   %1,%0
4959         fake    %1,%0
4960         lds     %1,%0
4961         sts     %1,%0
4962         fsts    fpul,%0
4963         flds    %1,fpul
4964         fmov    %1,%0
4965         ! move optimized away"
4966   [(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")
4967    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
4968    (set_attr_alternative "length"
4969      [(const_int 2)
4970       (const_int 2)
4971       (const_int 2)
4972       (const_int 4)
4973       (const_int 2)
4974       (if_then_else
4975         (ne (symbol_ref "TARGET_SH2A") (const_int 0))
4976         (const_int 4) (const_int 2))
4977       (const_int 2)
4978       (const_int 2)
4979       (const_int 2)
4980       (if_then_else
4981         (ne (symbol_ref "TARGET_SH2A") (const_int 0))
4982         (const_int 4) (const_int 2))
4983       (const_int 2)
4984       (const_int 2)
4985       (const_int 2)
4986       (const_int 2)
4987       (const_int 2)
4988       (const_int 2)
4989       (const_int 2)
4990       (const_int 2)
4991       (const_int 2)
4992       (const_int 2)
4993       (const_int 2)
4994       (const_int 2)
4995       (const_int 2)
4996       (const_int 2)
4997       (const_int 0)])])
4998
4999 (define_insn "movsi_i_lowpart"
5000   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
5001         (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
5002    "TARGET_SH1
5003     && (register_operand (operands[0], SImode)
5004         || register_operand (operands[1], SImode))"
5005   "@
5006         mov.l   %1,%0
5007         mov     %1,%0
5008         mov     %1,%0
5009         mov.l   %1,%0
5010         sts     %1,%0
5011         sts     %1,%0
5012         movt    %0
5013         mov.l   %1,%0
5014         fake    %1,%0"
5015   [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
5016
5017 (define_insn_and_split "load_ra"
5018   [(set (match_operand:SI 0 "general_movdst_operand" "")
5019         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
5020   "TARGET_SH1"
5021   "#"
5022   "&& ! currently_expanding_to_rtl"
5023   [(set (match_dup 0) (match_dup 1))]
5024   "
5025 {
5026   if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
5027     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
5028 }")
5029
5030 ;; The '?'s in the following constraints may not reflect the time taken
5031 ;; to perform the move. They are there to discourage the use of floating-
5032 ;; point registers for storing integer values.
5033 (define_insn "*movsi_media"
5034   [(set (match_operand:SI 0 "general_movdst_operand"
5035                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
5036         (match_operand:SI 1 "general_movsrc_operand"
5037          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5038   "TARGET_SHMEDIA_FPU
5039    && (register_operand (operands[0], SImode)
5040        || sh_register_operand (operands[1], SImode)
5041        || GET_CODE (operands[1]) == TRUNCATE)"
5042   "@
5043         add.l   %1, r63, %0
5044         movi    %1, %0
5045         #
5046         ld%M1.l %m1, %0
5047         st%M0.l %m0, %N1
5048         fld%M1.s        %m1, %0
5049         fst%M0.s        %m0, %1
5050         fmov.ls %N1, %0
5051         fmov.sl %1, %0
5052         fmov.s  %1, %0
5053         ptabs   %1, %0
5054         gettr   %1, %0
5055         pt      %1, %0"
5056   [(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")
5057    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5058    (set (attr "highpart")
5059         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5060                (const_string "user")]
5061               (const_string "ignore")))])
5062
5063 (define_insn "*movsi_media_nofpu"
5064   [(set (match_operand:SI 0 "general_movdst_operand"
5065                 "=r,r,r,r,m,*b,r,*b")
5066         (match_operand:SI 1 "general_movsrc_operand"
5067          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5068   "TARGET_SHMEDIA
5069    && (register_operand (operands[0], SImode)
5070        || sh_register_operand (operands[1], SImode)
5071        || GET_CODE (operands[1]) == TRUNCATE)"
5072   "@
5073         add.l   %1, r63, %0
5074         movi    %1, %0
5075         #
5076         ld%M1.l %m1, %0
5077         st%M0.l %m0, %N1
5078         ptabs   %1, %0
5079         gettr   %1, %0
5080         pt      %1, %0"
5081   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5082    (set_attr "length" "4,4,8,4,4,4,4,12")
5083    (set (attr "highpart")
5084         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5085                (const_string "user")]
5086               (const_string "ignore")))])
5087
5088 (define_expand "movsi_const"
5089   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5090         (const:SI (sign_extend:SI
5091                    (truncate:HI
5092                     (ashiftrt:SI
5093                      (match_operand:DI 1 "immediate_operand" "s")
5094                      (const_int 16))))))
5095    (set (match_dup 0)
5096         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5097                 (const:SI
5098                   (zero_extend:SI
5099                    (truncate:HI (match_dup 1))))))]
5100   "TARGET_SHMEDIA && reload_completed
5101    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5102   "
5103 {
5104   if (GET_CODE (operands[1]) == LABEL_REF
5105       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5106     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5107   else if (GOTOFF_P (operands[1]))
5108     {
5109       rtx unspec = XEXP (operands[1], 0);
5110
5111       if (! UNSPEC_GOTOFF_P (unspec))
5112         {
5113           unspec = XEXP (unspec, 0);
5114           if (! UNSPEC_GOTOFF_P (unspec))
5115             abort ();
5116         }
5117       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5118           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5119         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5120     }
5121 }")
5122
5123 (define_expand "movsi_const_16bit"
5124   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5125         (const:SI (sign_extend:SI
5126                    (truncate:HI
5127                     (match_operand:DI 1 "immediate_operand" "s")))))]
5128   "TARGET_SHMEDIA && flag_pic && reload_completed
5129    && GET_CODE (operands[1]) == SYMBOL_REF"
5130   "")
5131
5132 (define_split
5133   [(set (match_operand:SI 0 "arith_reg_dest" "")
5134         (match_operand:SI 1 "immediate_operand" ""))]
5135   "TARGET_SHMEDIA && reload_completed
5136    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5137   [(const_int 0)]
5138   "
5139 {
5140   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5141
5142   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5143
5144   DONE;
5145 }")
5146
5147 (define_split
5148   [(set (match_operand:SI 0 "register_operand" "")
5149         (match_operand:SI 1 "immediate_operand" ""))]
5150   "TARGET_SHMEDIA && reload_completed
5151    && ((GET_CODE (operands[1]) == CONST_INT
5152         && ! satisfies_constraint_I16 (operands[1]))
5153        || GET_CODE (operands[1]) == CONST_DOUBLE)"
5154   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5155
5156 (define_expand "movsi"
5157   [(set (match_operand:SI 0 "general_movdst_operand" "")
5158         (match_operand:SI 1 "general_movsrc_operand" ""))]
5159   ""
5160   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5161
5162 (define_expand "ic_invalidate_line"
5163   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5164                                 (match_dup 1)] UNSPEC_ICACHE)
5165               (clobber (scratch:SI))])]
5166   "TARGET_HARD_SH4 || TARGET_SH5"
5167   "
5168 {
5169   if (TARGET_SHMEDIA)
5170     {
5171       emit_insn (gen_ic_invalidate_line_media (operands[0]));
5172       DONE;
5173     }
5174   else if (TARGET_SHCOMPACT)
5175     {
5176       operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5177       operands[1] = force_reg (Pmode, operands[1]);
5178       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5179       DONE;
5180     }
5181   else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5182     {
5183       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5184       DONE;
5185     }
5186   operands[0] = force_reg (Pmode, operands[0]);
5187   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5188                                                                Pmode)));
5189 }")
5190
5191 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
5192 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5193 ;; the requirement *1*00 for associative address writes.  The alignment of
5194 ;; %0 implies that its least significant bit is cleared,
5195 ;; thus we clear the V bit of a matching entry if there is one.
5196 (define_insn "ic_invalidate_line_i"
5197   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5198                      (match_operand:SI 1 "register_operand" "r")]
5199                      UNSPEC_ICACHE)
5200    (clobber (match_scratch:SI 2 "=&r"))]
5201   "TARGET_HARD_SH4"
5202   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5203   [(set_attr "length" "8")
5204    (set_attr "type" "cwb")])
5205
5206 (define_insn "ic_invalidate_line_sh4a"
5207   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5208                     UNSPEC_ICACHE)]
5209   "TARGET_SH4A_ARCH || TARGET_SH4_300"
5210   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5211   [(set_attr "length" "16")
5212    (set_attr "type" "cwb")])
5213
5214 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5215 ;; an add in the code that calculates the address.
5216 (define_insn "ic_invalidate_line_media"
5217   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5218                     UNSPEC_ICACHE)]
5219   "TARGET_SHMEDIA"
5220   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
5221   [(set_attr "length" "16")
5222    (set_attr "type" "invalidate_line_media")])
5223
5224 (define_insn "ic_invalidate_line_compact"
5225   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5226                      (match_operand:SI 1 "register_operand" "r")]
5227                     UNSPEC_ICACHE)
5228    (clobber (reg:SI PR_REG))]
5229   "TARGET_SHCOMPACT"
5230   "jsr @%1%#"
5231   [(set_attr "type" "sfunc")
5232    (set_attr "needs_delay_slot" "yes")])
5233
5234 (define_expand "initialize_trampoline"
5235   [(match_operand:SI 0 "" "")
5236    (match_operand:SI 1 "" "")
5237    (match_operand:SI 2 "" "")]
5238   "TARGET_SHCOMPACT"
5239   "
5240 {
5241   rtx sfun, tramp;
5242
5243   tramp = force_reg (Pmode, operands[0]);
5244   sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5245                                             SFUNC_STATIC));
5246   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5247   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5248
5249   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5250   DONE;
5251 }")
5252
5253 (define_insn "initialize_trampoline_compact"
5254   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5255                      (match_operand:SI 1 "register_operand" "r")
5256                      (reg:SI R2_REG) (reg:SI R3_REG)]
5257                     UNSPEC_INIT_TRAMP)
5258
5259    (clobber (reg:SI PR_REG))]
5260   "TARGET_SHCOMPACT"
5261   "jsr @%1%#"
5262   [(set_attr "type" "sfunc")
5263    (set_attr "needs_delay_slot" "yes")])
5264
5265 (define_insn "movqi_i"
5266   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m,r,r,l")
5267         (match_operand:QI 1 "general_movsrc_operand"  "r,i,m,r,t,l,r"))]
5268   "TARGET_SH1
5269    && (arith_reg_operand (operands[0], QImode)
5270        || arith_reg_operand (operands[1], QImode))"
5271   "@
5272         mov     %1,%0
5273         mov     %1,%0
5274         mov.b   %1,%0
5275         mov.b   %1,%0
5276         movt    %0
5277         sts     %1,%0
5278         lds     %1,%0"
5279  [(set_attr "type" "move,movi8,load,store,arith,prget,prset")])
5280
5281 (define_insn "*movqi_media"
5282   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5283         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5284   "TARGET_SHMEDIA
5285    && (arith_reg_operand (operands[0], QImode)
5286        || extend_reg_or_0_operand (operands[1], QImode))"
5287   "@
5288         add.l   %1, r63, %0
5289         movi    %1, %0
5290         ld%M1.ub        %m1, %0
5291         st%M0.b %m0, %N1"
5292   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5293    (set (attr "highpart")
5294         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5295                (const_string "user")]
5296               (const_string "ignore")))])
5297
5298 (define_expand "movqi"
5299   [(set (match_operand:QI 0 "general_operand" "")
5300         (match_operand:QI 1 "general_operand"  ""))]
5301   ""
5302   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5303
5304 (define_expand "reload_inqi"
5305   [(set (match_operand:SI 2 "" "=&r")
5306         (match_operand:QI 1 "inqhi_operand" ""))
5307    (set (match_operand:QI 0 "arith_reg_operand" "=r")
5308         (truncate:QI (match_dup 3)))]
5309   "TARGET_SHMEDIA"
5310   "
5311 {
5312   rtx inner = XEXP (operands[1], 0);
5313   int regno = REGNO (inner);
5314
5315   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5316   operands[1] = gen_rtx_REG (SImode, regno);
5317   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5318 }")
5319
5320 /* When storing r0, we have to avoid reg+reg addressing.  */
5321 (define_insn "movhi_i"
5322   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
5323         (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5324   "TARGET_SH1
5325    && (arith_reg_operand (operands[0], HImode)
5326        || arith_reg_operand (operands[1], HImode))
5327    && (GET_CODE (operands[0]) != MEM
5328        || GET_CODE (XEXP (operands[0], 0)) != PLUS
5329        || GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != REG
5330        || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5331   "@
5332         mov.w   %1,%0
5333         mov     %1,%0
5334         mov.w   %1,%0
5335         movt    %0
5336         mov.w   %1,%0
5337         sts     %1,%0
5338         lds     %1,%0
5339         fake    %1,%0"
5340   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5341
5342 (define_insn "*movhi_media"
5343   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
5344         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5345   "TARGET_SHMEDIA
5346    && (arith_reg_operand (operands[0], HImode)
5347        || arith_reg_or_0_operand (operands[1], HImode))"
5348   "@
5349         add.l   %1, r63, %0
5350         movi    %1, %0
5351         #
5352         ld%M1.w %m1, %0
5353         st%M0.w %m0, %N1"
5354   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5355    (set (attr "highpart")
5356         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5357                (const_string "user")]
5358               (const_string "ignore")))])
5359
5360 (define_split
5361   [(set (match_operand:HI 0 "register_operand" "")
5362         (match_operand:HI 1 "immediate_operand" ""))]
5363   "TARGET_SHMEDIA && reload_completed
5364    && ! satisfies_constraint_I16 (operands[1])"
5365   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5366
5367 (define_expand "movhi"
5368   [(set (match_operand:HI 0 "general_movdst_operand" "")
5369         (match_operand:HI 1 "general_movsrc_operand"  ""))]
5370   ""
5371   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5372
5373 (define_expand "reload_inhi"
5374   [(set (match_operand:SI 2 "" "=&r")
5375         (match_operand:HI 1 "inqhi_operand" ""))
5376    (set (match_operand:HI 0 "arith_reg_operand" "=r")
5377         (truncate:HI (match_dup 3)))]
5378   "TARGET_SHMEDIA"
5379   "
5380 {
5381   rtx inner = XEXP (operands[1], 0);
5382   int regno = REGNO (inner);
5383
5384   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5385   operands[1] = gen_rtx_REG (SImode, regno);
5386   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5387 }")
5388
5389 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5390 ;; compiled with -m2 -ml -O3 -funroll-loops
5391 (define_insn "*movdi_i"
5392   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5393         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5394   "TARGET_SH1
5395    && (arith_reg_operand (operands[0], DImode)
5396        || arith_reg_operand (operands[1], DImode))"
5397   "* return output_movedouble (insn, operands, DImode);"
5398   [(set_attr "length" "4")
5399    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5400
5401 ;; If the output is a register and the input is memory or a register, we have
5402 ;; to be careful and see which word needs to be loaded first.
5403
5404 (define_split
5405   [(set (match_operand:DI 0 "general_movdst_operand" "")
5406         (match_operand:DI 1 "general_movsrc_operand" ""))]
5407   "TARGET_SH1 && reload_completed"
5408   [(set (match_dup 2) (match_dup 3))
5409    (set (match_dup 4) (match_dup 5))]
5410   "
5411 {
5412   int regno;
5413
5414   if ((GET_CODE (operands[0]) == MEM
5415        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5416       || (GET_CODE (operands[1]) == MEM
5417           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5418     FAIL;
5419
5420   switch (GET_CODE (operands[0]))
5421     {
5422     case REG:
5423       regno = REGNO (operands[0]);
5424       break;
5425     case SUBREG:
5426       regno = subreg_regno (operands[0]);
5427       break;
5428     case MEM:
5429       regno = -1;
5430       break;
5431     default:
5432       gcc_unreachable ();
5433     }
5434
5435   if (regno == -1
5436       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5437     {
5438       operands[2] = operand_subword (operands[0], 0, 0, DImode);
5439       operands[3] = operand_subword (operands[1], 0, 0, DImode);
5440       operands[4] = operand_subword (operands[0], 1, 0, DImode);
5441       operands[5] = operand_subword (operands[1], 1, 0, DImode);
5442     }
5443   else
5444     {
5445       operands[2] = operand_subword (operands[0], 1, 0, DImode);
5446       operands[3] = operand_subword (operands[1], 1, 0, DImode);
5447       operands[4] = operand_subword (operands[0], 0, 0, DImode);
5448       operands[5] = operand_subword (operands[1], 0, 0, DImode);
5449     }
5450
5451   if (operands[2] == 0 || operands[3] == 0
5452       || operands[4] == 0 || operands[5] == 0)
5453     FAIL;
5454 }")
5455
5456 ;; The '?'s in the following constraints may not reflect the time taken
5457 ;; to perform the move. They are there to discourage the use of floating-
5458 ;; point registers for storing integer values.
5459 (define_insn "*movdi_media"
5460   [(set (match_operand:DI 0 "general_movdst_operand"
5461                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5462         (match_operand:DI 1 "general_movsrc_operand"
5463          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5464   "TARGET_SHMEDIA_FPU
5465    && (register_operand (operands[0], DImode)
5466        || sh_register_operand (operands[1], DImode))"
5467   "@
5468         add     %1, r63, %0
5469         movi    %1, %0
5470         #
5471         ld%M1.q %m1, %0
5472         st%M0.q %m0, %N1
5473         fld%M1.d        %m1, %0
5474         fst%M0.d        %m0, %1
5475         fmov.qd %N1, %0
5476         fmov.dq %1, %0
5477         fmov.d  %1, %0
5478         ptabs   %1, %0
5479         gettr   %1, %0
5480         pt      %1, %0"
5481   [(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")
5482    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5483
5484 (define_insn "*movdi_media_nofpu"
5485   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5486         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5487   "TARGET_SHMEDIA
5488    && (register_operand (operands[0], DImode)
5489        || sh_register_operand (operands[1], DImode))"
5490   "@
5491         add     %1, r63, %0
5492         movi    %1, %0
5493         #
5494         ld%M1.q %m1, %0
5495         st%M0.q %m0, %N1
5496         ptabs   %1, %0
5497         gettr   %1, %0
5498         pt      %1, %0"
5499   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5500    (set_attr "length" "4,4,16,4,4,4,4,*")])
5501
5502 (define_insn "*movdi_media_I16"
5503   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5504         (match_operand:DI 1 "const_int_operand" "I16"))]
5505   "TARGET_SHMEDIA && reload_completed"
5506   "movi %1, %0"
5507   [(set_attr "type" "arith_media")
5508    (set_attr "length" "4")])
5509
5510 (define_split
5511   [(set (match_operand:DI 0 "arith_reg_dest" "")
5512         (match_operand:DI 1 "immediate_operand" ""))]
5513   "TARGET_SHMEDIA && reload_completed
5514    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5515   [(set (match_dup 0) (match_dup 1))]
5516   "
5517 {
5518   rtx insn;
5519
5520   if (TARGET_SHMEDIA64)
5521     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5522   else
5523     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5524
5525   set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5526
5527   DONE;
5528 }")
5529
5530 (define_expand "movdi_const"
5531   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5532         (const:DI (sign_extend:DI
5533                    (truncate:HI
5534                     (ashiftrt:DI
5535                      (match_operand:DI 1 "immediate_operand" "s")
5536                      (const_int 48))))))
5537    (set (match_dup 0)
5538         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5539                 (const:DI
5540                  (zero_extend:DI
5541                   (truncate:HI
5542                    (ashiftrt:SI
5543                     (match_dup 1)
5544                     (const_int 32)))))))
5545    (set (match_dup 0)
5546         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5547                 (const:DI
5548                  (zero_extend:DI
5549                   (truncate:HI
5550                    (ashiftrt:SI
5551                     (match_dup 1)
5552                     (const_int 16)))))))
5553    (set (match_dup 0)
5554         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5555                 (const:DI
5556                  (zero_extend:DI
5557                   (truncate:HI
5558                    (match_dup 1))))))]
5559   "TARGET_SHMEDIA64 && reload_completed
5560    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5561   "
5562 {
5563   sh_mark_label (operands[1], 4);
5564 }")
5565
5566 (define_expand "movdi_const_32bit"
5567   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5568         (const:DI (sign_extend:DI
5569                    (truncate:HI
5570                     (ashiftrt:DI
5571                      (match_operand:DI 1 "immediate_operand" "s")
5572                      (const_int 16))))))
5573    (set (match_dup 0)
5574         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5575                 (const:DI
5576                  (zero_extend:DI
5577                   (truncate:HI
5578                    (match_dup 1))))))]
5579   "TARGET_SHMEDIA32 && reload_completed
5580    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5581   "
5582 {
5583   sh_mark_label (operands[1], 2);
5584 }")
5585
5586 (define_expand "movdi_const_16bit"
5587   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5588         (const:DI (sign_extend:DI
5589                    (truncate:HI
5590                     (match_operand:DI 1 "immediate_operand" "s")))))]
5591   "TARGET_SHMEDIA && flag_pic && reload_completed
5592    && GET_CODE (operands[1]) == SYMBOL_REF"
5593   "")
5594
5595 (define_split
5596   [(set (match_operand:DI 0 "ext_dest_operand" "")
5597         (match_operand:DI 1 "immediate_operand" ""))]
5598   "TARGET_SHMEDIA && reload_completed
5599    && GET_CODE (operands[1]) == CONST_INT
5600    && ! satisfies_constraint_I16 (operands[1])"
5601   [(set (match_dup 0) (match_dup 2))
5602    (match_dup 1)]
5603   "
5604 {
5605   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5606   unsigned HOST_WIDE_INT low = val;
5607   unsigned HOST_WIDE_INT high = val;
5608   unsigned HOST_WIDE_INT sign;
5609   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5610
5611   /* Zero-extend the 16 least-significant bits.  */
5612   low &= 0xffff;
5613
5614   /* Arithmetic shift right the word by 16 bits.  */
5615   high >>= 16;
5616   if (GET_CODE (operands[0]) == SUBREG
5617       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5618     {
5619       high &= 0xffff;
5620       high ^= 0x8000;
5621       high -= 0x8000;
5622     }
5623   else
5624     {
5625       sign = 1;
5626       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5627       high ^= sign;
5628       high -= sign;
5629     }
5630   do
5631     {
5632       /* If we can't generate the constant with a two-insn movi / shori
5633          sequence, try some other strategies.  */
5634       if (! CONST_OK_FOR_I16 (high))
5635         {
5636           /* Try constant load / left shift.  We know VAL != 0.  */
5637           val2 = val ^ (val-1);
5638           if (val2 > 0x1ffff)
5639             {
5640               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5641
5642               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5643                   || (! CONST_OK_FOR_I16 (high >> 16)
5644                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5645                 {
5646                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5647                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
5648                                                    GEN_INT (trailing_zeroes));
5649                   break;
5650                 }
5651             }
5652           /* Try constant load / right shift.  */
5653           val2 = (val >> 15) + 1;
5654           if (val2 == (val2 & -val2))
5655             {
5656               int shift = 49 - exact_log2 (val2);
5657
5658               val2 = trunc_int_for_mode (val << shift, DImode);
5659               if (CONST_OK_FOR_I16 (val2))
5660                 {
5661                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5662                                                    GEN_INT (shift));
5663                   break;
5664                 }
5665             }
5666           /* Try mperm.w .  */
5667           val2 = val & 0xffff;
5668           if ((val >> 16 & 0xffff) == val2
5669               && (val >> 32 & 0xffff) == val2
5670               && (val >> 48 & 0xffff) == val2)
5671             {
5672               val2 = (HOST_WIDE_INT) val >> 48;
5673               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5674               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5675               break;
5676             }
5677           /* Try movi / mshflo.l  */
5678           val2 = (HOST_WIDE_INT) val >> 32;
5679           if (val2 == ((unsigned HOST_WIDE_INT)
5680                         trunc_int_for_mode (val, SImode)))
5681             {
5682               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5683                                              operands[0]);
5684               break;
5685             }
5686           /* Try movi / mshflo.l w/ r63.  */
5687           val2 = val + ((HOST_WIDE_INT) -1 << 32);
5688           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5689             {
5690               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5691                                              const0_rtx);
5692               break;
5693             }
5694         }
5695       val2 = high;
5696       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5697     }
5698   while (0);
5699   operands[2] = GEN_INT (val2);
5700 }")
5701
5702 (define_split
5703   [(set (match_operand:DI 0 "ext_dest_operand" "")
5704         (match_operand:DI 1 "immediate_operand" ""))]
5705   "TARGET_SHMEDIA && reload_completed
5706    && GET_CODE (operands[1]) == CONST_DOUBLE"
5707   [(set (match_dup 0) (match_dup 2))
5708   (set (match_dup 0)
5709        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5710   "
5711 {
5712   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5713   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5714   unsigned HOST_WIDE_INT val = low;
5715   unsigned HOST_WIDE_INT sign;
5716
5717   /* Zero-extend the 16 least-significant bits.  */
5718   val &= 0xffff;
5719   operands[1] = GEN_INT (val);
5720
5721   /* Arithmetic shift right the double-word by 16 bits.  */
5722   low >>= 16;
5723   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5724   high >>= 16;
5725   sign = 1;
5726   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5727   high ^= sign;
5728   high -= sign;
5729
5730   /* This will only be true if high is a sign-extension of low, i.e.,
5731      it must be either 0 or (unsigned)-1, and be zero iff the
5732      most-significant bit of low is set.  */
5733   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5734     operands[2] = GEN_INT (low);
5735   else
5736     operands[2] = immed_double_const (low, high, DImode);
5737 }")
5738
5739 (define_insn "shori_media"
5740   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5741         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5742                            (const_int 16))
5743                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5744   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5745   "@
5746         shori   %u2, %0
5747         #"
5748   [(set_attr "type" "arith_media,*")])
5749
5750 (define_insn "*shori_media_si"
5751   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5752         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5753                            (const_int 16))
5754                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
5755   "TARGET_SHMEDIA"
5756   "shori        %u2, %0")
5757
5758 (define_expand "movdi"
5759   [(set (match_operand:DI 0 "general_movdst_operand" "")
5760         (match_operand:DI 1 "general_movsrc_operand" ""))]
5761   ""
5762   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5763
5764 (define_insn "movdf_media"
5765   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5766         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5767   "TARGET_SHMEDIA_FPU
5768    && (register_operand (operands[0], DFmode)
5769        || sh_register_operand (operands[1], DFmode))"
5770   "@
5771         fmov.d  %1, %0
5772         fmov.qd %N1, %0
5773         fmov.dq %1, %0
5774         add     %1, r63, %0
5775         #
5776         fld%M1.d        %m1, %0
5777         fst%M0.d        %m0, %1
5778         ld%M1.q %m1, %0
5779         st%M0.q %m0, %N1"
5780   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5781
5782 (define_insn "movdf_media_nofpu"
5783   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5784         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5785   "TARGET_SHMEDIA
5786    && (register_operand (operands[0], DFmode)
5787        || sh_register_operand (operands[1], DFmode))"
5788   "@
5789         add     %1, r63, %0
5790         #
5791         ld%M1.q %m1, %0
5792         st%M0.q %m0, %N1"
5793   [(set_attr "type" "arith_media,*,load_media,store_media")])
5794
5795 (define_split
5796   [(set (match_operand:DF 0 "arith_reg_dest" "")
5797         (match_operand:DF 1 "immediate_operand" ""))]
5798   "TARGET_SHMEDIA && reload_completed"
5799   [(set (match_dup 3) (match_dup 2))]
5800   "
5801 {
5802   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5803   long values[2];
5804   REAL_VALUE_TYPE value;
5805
5806   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5807   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5808
5809   if (HOST_BITS_PER_WIDE_INT >= 64)
5810     operands[2] = immed_double_const ((unsigned long) values[endian]
5811                                       | ((HOST_WIDE_INT) values[1 - endian]
5812                                          << 32), 0, DImode);
5813   else
5814     {
5815       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5816       operands[2] = immed_double_const (values[endian], values[1 - endian],
5817                                         DImode);
5818     }
5819
5820   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5821 }")
5822
5823 ;; ??? This should be a define expand.
5824
5825 (define_insn "movdf_k"
5826   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5827         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5828   "TARGET_SH1
5829    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5830        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5831        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
5832        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
5833    && (arith_reg_operand (operands[0], DFmode)
5834        || arith_reg_operand (operands[1], DFmode))"
5835   "* return output_movedouble (insn, operands, DFmode);"
5836   [(set_attr "length" "4")
5837    (set_attr "type" "move,pcload,load,store")])
5838
5839 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5840 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
5841 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
5842 ;; the d/m/c/X alternative, which is split later into single-precision
5843 ;; instructions.  And when not optimizing, no splits are done before fixing
5844 ;; up pcloads, so we need usable length information for that.
5845 (define_insn "movdf_i4"
5846   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5847         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
5848    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
5849    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
5850   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5851    && (arith_reg_operand (operands[0], DFmode)
5852        || arith_reg_operand (operands[1], DFmode))"
5853   "@
5854         fmov    %1,%0
5855         #
5856         #
5857         fmov.d  %1,%0
5858         fmov.d  %1,%0
5859         #
5860         #
5861         #
5862         #
5863         #"
5864   [(set_attr_alternative "length"
5865      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
5866       (const_int 4)
5867       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5868       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5869       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5870       (const_int 4)
5871       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
5872       ;; We can't use 4-byte push/pop on SHcompact, so we have to
5873       ;; increment or decrement r15 explicitly.
5874       (if_then_else
5875        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5876        (const_int 10) (const_int 8))
5877       (if_then_else
5878        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5879        (const_int 10) (const_int 8))])
5880    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
5881    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
5882    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
5883                                            (const_string "double")
5884                                            (const_string "none")))])
5885
5886 ;; Moving DFmode between fp/general registers through memory
5887 ;; (the top of the stack) is faster than moving through fpul even for
5888 ;; little endian.  Because the type of an instruction is important for its
5889 ;; scheduling,  it is beneficial to split these operations, rather than
5890 ;; emitting them in one single chunk, even if this will expose a stack
5891 ;; use that will prevent scheduling of other stack accesses beyond this
5892 ;; instruction.
5893 (define_split
5894   [(set (match_operand:DF 0 "register_operand" "")
5895         (match_operand:DF 1 "register_operand" ""))
5896    (use (match_operand:PSI 2 "fpscr_operand" ""))
5897    (clobber (match_scratch:SI 3 "=X"))]
5898   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
5899    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
5900   [(const_int 0)]
5901   "
5902 {
5903   rtx insn, tos;
5904
5905   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
5906     {
5907       emit_move_insn (stack_pointer_rtx,
5908                       plus_constant (stack_pointer_rtx, -8));
5909       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5910     }
5911   else
5912     tos = gen_tmp_stack_mem (DFmode,
5913                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
5914   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
5915   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
5916     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5917   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5918     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5919   else
5920     tos = gen_tmp_stack_mem (DFmode,
5921                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
5922   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
5923   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5924     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
5925   else
5926     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5927   DONE;
5928 }")
5929
5930 ;; local-alloc sometimes allocates scratch registers even when not required,
5931 ;; so we must be prepared to handle these.
5932
5933 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
5934 (define_split
5935   [(set (match_operand:DF 0 "general_movdst_operand" "")
5936         (match_operand:DF 1 "general_movsrc_operand"  ""))
5937    (use (match_operand:PSI 2 "fpscr_operand" ""))
5938    (clobber (match_scratch:SI 3 ""))]
5939   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5940    && reload_completed
5941    && true_regnum (operands[0]) < 16
5942    && true_regnum (operands[1]) < 16"
5943   [(set (match_dup 0) (match_dup 1))]
5944   "
5945 {
5946   /* If this was a reg <-> mem operation with base + index reg addressing,
5947      we have to handle this in a special way.  */
5948   rtx mem = operands[0];
5949   int store_p = 1;
5950   if (! memory_operand (mem, DFmode))
5951     {
5952       mem = operands[1];
5953       store_p = 0;
5954     }
5955   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
5956     mem = SUBREG_REG (mem);
5957   if (GET_CODE (mem) == MEM)
5958     {
5959       rtx addr = XEXP (mem, 0);
5960       if (GET_CODE (addr) == PLUS
5961           && GET_CODE (XEXP (addr, 0)) == REG
5962           && GET_CODE (XEXP (addr, 1)) == REG)
5963         {
5964           int offset;
5965           rtx reg0 = gen_rtx_REG (Pmode, 0);
5966           rtx regop = operands[store_p], word0 ,word1;
5967
5968           if (GET_CODE (regop) == SUBREG)
5969             alter_subreg (&regop);
5970           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
5971             offset = 2;
5972           else
5973             offset = 4;
5974           mem = copy_rtx (mem);
5975           PUT_MODE (mem, SImode);
5976           word0 = gen_rtx_SUBREG (SImode, regop, 0);
5977           alter_subreg (&word0);
5978           word1 = gen_rtx_SUBREG (SImode, regop, 4);
5979           alter_subreg (&word1);
5980           if (store_p || ! refers_to_regno_p (REGNO (word0),
5981                                               REGNO (word0) + 1, addr, 0))
5982             {
5983               emit_insn (store_p
5984                          ? gen_movsi_ie (mem, word0)
5985                          : gen_movsi_ie (word0, mem));
5986               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5987               mem = copy_rtx (mem);
5988               emit_insn (store_p
5989                          ? gen_movsi_ie (mem, word1)
5990                          : gen_movsi_ie (word1, mem));
5991               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5992             }
5993           else
5994             {
5995               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5996               emit_insn (gen_movsi_ie (word1, mem));
5997               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5998               mem = copy_rtx (mem);
5999               emit_insn (gen_movsi_ie (word0, mem));
6000             }
6001           DONE;
6002         }
6003     }
6004 }")
6005
6006 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
6007 (define_split
6008   [(set (match_operand:DF 0 "register_operand" "")
6009         (match_operand:DF 1 "memory_operand"  ""))
6010    (use (match_operand:PSI 2 "fpscr_operand" ""))
6011    (clobber (reg:SI R0_REG))]
6012   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
6013   [(parallel [(set (match_dup 0) (match_dup 1))
6014               (use (match_dup 2))
6015               (clobber (scratch:SI))])]
6016   "")
6017
6018 (define_expand "reload_indf__frn"
6019   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
6020                    (match_operand:DF 1 "immediate_operand" "FQ"))
6021               (use (reg:PSI FPSCR_REG))
6022               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6023   "TARGET_SH1"
6024   "")
6025
6026 (define_expand "reload_outdf__RnFRm"
6027   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
6028                    (match_operand:DF 1 "register_operand" "af,r"))
6029               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
6030   "TARGET_SH1"
6031   "")
6032
6033 ;; Simplify no-op moves.
6034 (define_split
6035   [(set (match_operand:SF 0 "register_operand" "")
6036         (match_operand:SF 1 "register_operand" ""))
6037    (use (match_operand:PSI 2 "fpscr_operand" ""))
6038    (clobber (match_scratch:SI 3 ""))]
6039   "TARGET_SH2E && reload_completed
6040    && true_regnum (operands[0]) == true_regnum (operands[1])"
6041   [(set (match_dup 0) (match_dup 0))]
6042   "")
6043
6044 ;; fmovd substitute post-reload splits
6045 (define_split
6046   [(set (match_operand:DF 0 "register_operand" "")
6047         (match_operand:DF 1 "register_operand" ""))
6048    (use (match_operand:PSI 2 "fpscr_operand" ""))
6049    (clobber (match_scratch:SI 3 ""))]
6050   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
6051    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6052    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6053   [(const_int 0)]
6054   "
6055 {
6056   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6057   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6058                            gen_rtx_REG (SFmode, src), operands[2]));
6059   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6060                            gen_rtx_REG (SFmode, src + 1), operands[2]));
6061   DONE;
6062 }")
6063
6064 (define_split
6065   [(set (match_operand:DF 0 "register_operand" "")
6066         (mem:DF (match_operand:SI 1 "register_operand" "")))
6067    (use (match_operand:PSI 2 "fpscr_operand" ""))
6068    (clobber (match_scratch:SI 3 ""))]
6069   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6070    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6071    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6072   [(const_int 0)]
6073   "
6074 {
6075   int regno = true_regnum (operands[0]);
6076   rtx insn;
6077   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6078   rtx mem2
6079     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6080   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6081                                            regno + !! TARGET_LITTLE_ENDIAN),
6082                                   mem2, operands[2]));
6083   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
6084   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6085                                                regno + ! TARGET_LITTLE_ENDIAN),
6086                                   change_address (mem, SFmode, NULL_RTX),
6087                                   operands[2]));
6088   DONE;
6089 }")
6090
6091 (define_split
6092   [(set (match_operand:DF 0 "register_operand" "")
6093         (match_operand:DF 1 "memory_operand" ""))
6094    (use (match_operand:PSI 2 "fpscr_operand" ""))
6095    (clobber (match_scratch:SI 3 ""))]
6096   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6097    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6098   [(const_int 0)]
6099   "
6100 {
6101   int regno = true_regnum (operands[0]);
6102   rtx addr, insn, adjust = NULL_RTX;
6103   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6104   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
6105   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
6106
6107   operands[1] = copy_rtx (mem2);
6108   addr = XEXP (mem2, 0);
6109   if (GET_CODE (addr) != POST_INC)
6110     {
6111       /* If we have to modify the stack pointer, the value that we have
6112          read with post-increment might be modified by an interrupt,
6113          so write it back.  */
6114       if (REGNO (addr) == STACK_POINTER_REGNUM)
6115         adjust = gen_push_e (reg0);
6116       else
6117         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
6118       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6119     }
6120   addr = XEXP (addr, 0);
6121   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6122   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6123   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6124   if (adjust)
6125     emit_insn (adjust);
6126   else
6127     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6128   DONE;
6129 }")
6130
6131 (define_split
6132   [(set (match_operand:DF 0 "memory_operand" "")
6133         (match_operand:DF 1 "register_operand" ""))
6134    (use (match_operand:PSI 2 "fpscr_operand" ""))
6135    (clobber (match_scratch:SI 3 ""))]
6136   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6137    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6138   [(const_int 0)]
6139   "
6140 {
6141   int regno = true_regnum (operands[1]);
6142   rtx insn, addr, adjust = NULL_RTX;
6143
6144   operands[0] = copy_rtx (operands[0]);
6145   PUT_MODE (operands[0], SFmode);
6146   insn = emit_insn (gen_movsf_ie (operands[0],
6147                                   gen_rtx_REG (SFmode,
6148                                            regno + ! TARGET_LITTLE_ENDIAN),
6149                                   operands[2]));
6150   operands[0] = copy_rtx (operands[0]);
6151   addr = XEXP (operands[0], 0);
6152   if (GET_CODE (addr) != PRE_DEC)
6153     {
6154       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
6155       emit_insn_before (adjust, insn);
6156       XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6157     }
6158   addr = XEXP (addr, 0);
6159   if (! adjust)
6160     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6161   insn = emit_insn (gen_movsf_ie (operands[0],
6162                                   gen_rtx_REG (SFmode,
6163                                            regno + !! TARGET_LITTLE_ENDIAN),
6164                                   operands[2]));
6165   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6166   DONE;
6167 }")
6168
6169 ;; If the output is a register and the input is memory or a register, we have
6170 ;; to be careful and see which word needs to be loaded first.
6171
6172 (define_split
6173   [(set (match_operand:DF 0 "general_movdst_operand" "")
6174         (match_operand:DF 1 "general_movsrc_operand" ""))]
6175   "TARGET_SH1 && reload_completed"
6176   [(set (match_dup 2) (match_dup 3))
6177    (set (match_dup 4) (match_dup 5))]
6178   "
6179 {
6180   int regno;
6181
6182   if ((GET_CODE (operands[0]) == MEM
6183        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6184       || (GET_CODE (operands[1]) == MEM
6185           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6186     FAIL;
6187
6188   switch (GET_CODE (operands[0]))
6189     {
6190     case REG:
6191       regno = REGNO (operands[0]);
6192       break;
6193     case SUBREG:
6194       regno = subreg_regno (operands[0]);
6195       break;
6196     case MEM:
6197       regno = -1;
6198       break;
6199     default:
6200       gcc_unreachable ();
6201     }
6202
6203   if (regno == -1
6204       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6205     {
6206       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6207       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6208       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6209       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6210     }
6211   else
6212     {
6213       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6214       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6215       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6216       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6217     }
6218
6219   if (operands[2] == 0 || operands[3] == 0
6220       || operands[4] == 0 || operands[5] == 0)
6221     FAIL;
6222 }")
6223
6224 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6225 ;; used only once, let combine add in the index again.
6226
6227 (define_split
6228   [(set (match_operand:SI 0 "register_operand" "")
6229         (match_operand:SI 1 "" ""))
6230    (clobber (match_operand 2 "register_operand" ""))]
6231   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6232    && ALLOW_INDEXED_ADDRESS"
6233   [(use (reg:SI R0_REG))]
6234   "
6235 {
6236   rtx addr, reg, const_int;
6237
6238   if (GET_CODE (operands[1]) != MEM)
6239     FAIL;
6240   addr = XEXP (operands[1], 0);
6241   if (GET_CODE (addr) != PLUS)
6242     FAIL;
6243   reg = XEXP (addr, 0);
6244   const_int = XEXP (addr, 1);
6245   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6246          && GET_CODE (const_int) == CONST_INT))
6247     FAIL;
6248   emit_move_insn (operands[2], const_int);
6249   emit_move_insn (operands[0],
6250                   change_address (operands[1], VOIDmode,
6251                                   gen_rtx_PLUS (SImode, reg, operands[2])));
6252   DONE;
6253 }")
6254
6255 (define_split
6256   [(set (match_operand:SI 1 "" "")
6257         (match_operand:SI 0 "register_operand" ""))
6258    (clobber (match_operand 2 "register_operand" ""))]
6259   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6260    && ALLOW_INDEXED_ADDRESS"
6261   [(use (reg:SI R0_REG))]
6262   "
6263 {
6264   rtx addr, reg, const_int;
6265
6266   if (GET_CODE (operands[1]) != MEM)
6267     FAIL;
6268   addr = XEXP (operands[1], 0);
6269   if (GET_CODE (addr) != PLUS)
6270     FAIL;
6271   reg = XEXP (addr, 0);
6272   const_int = XEXP (addr, 1);
6273   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6274          && GET_CODE (const_int) == CONST_INT))
6275     FAIL;
6276   emit_move_insn (operands[2], const_int);
6277   emit_move_insn (change_address (operands[1], VOIDmode,
6278                                   gen_rtx_PLUS (SImode, reg, operands[2])),
6279                   operands[0]);
6280   DONE;
6281 }")
6282
6283 (define_expand "movdf"
6284   [(set (match_operand:DF 0 "general_movdst_operand" "")
6285         (match_operand:DF 1 "general_movsrc_operand" ""))]
6286   ""
6287   "
6288 {
6289   if (prepare_move_operands (operands, DFmode)) DONE;
6290   if (TARGET_SHMEDIA)
6291     {
6292       if (TARGET_SHMEDIA_FPU)
6293         emit_insn (gen_movdf_media (operands[0], operands[1]));
6294       else
6295         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6296       DONE;
6297     }
6298   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6299     {
6300       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6301       DONE;
6302     }
6303 }")
6304
6305 ;;This is incompatible with the way gcc uses subregs.
6306 ;;(define_insn "movv2sf_i"
6307 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6308 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6309 ;;  "TARGET_SHMEDIA_FPU
6310 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
6311 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
6312 ;;  "@
6313 ;;      #
6314 ;;      fld%M1.p        %m1, %0
6315 ;;      fst%M0.p        %m0, %1"
6316 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
6317
6318 (define_insn_and_split "movv2sf_i"
6319   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6320         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6321   "TARGET_SHMEDIA_FPU"
6322   "#"
6323   "TARGET_SHMEDIA_FPU && reload_completed"
6324   [(set (match_dup 0) (match_dup 1))]
6325   "
6326 {
6327   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6328   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6329 }")
6330
6331 (define_expand "movv2sf"
6332   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6333         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6334   "TARGET_SHMEDIA_FPU"
6335   "
6336 {
6337   if (prepare_move_operands (operands, V2SFmode))
6338     DONE;
6339 }")
6340
6341 (define_expand "addv2sf3"
6342   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6343    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6344    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6345   "TARGET_SHMEDIA_FPU"
6346   "
6347 {
6348   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6349   DONE;
6350 }")
6351
6352 (define_expand "subv2sf3"
6353   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6354    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6355    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6356   "TARGET_SHMEDIA_FPU"
6357   "
6358 {
6359   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6360   DONE;
6361 }")
6362
6363 (define_expand "mulv2sf3"
6364   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6365    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6366    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6367   "TARGET_SHMEDIA_FPU"
6368   "
6369 {
6370   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6371   DONE;
6372 }")
6373
6374 (define_expand "divv2sf3"
6375   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6376    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6377    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6378   "TARGET_SHMEDIA_FPU"
6379   "
6380 {
6381   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6382   DONE;
6383 }")
6384
6385 (define_insn_and_split "*movv4sf_i"
6386   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6387         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6388   "TARGET_SHMEDIA_FPU"
6389   "#"
6390   "&& reload_completed"
6391   [(const_int 0)]
6392   "
6393 {
6394   int i;
6395
6396   for (i = 0; i < 4/2; i++)
6397     {
6398       rtx x, y;
6399
6400       if (GET_CODE (operands[0]) == MEM)
6401         x = adjust_address (operands[0], V2SFmode,
6402                             i * GET_MODE_SIZE (V2SFmode));
6403       else
6404         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6405
6406       if (GET_CODE (operands[1]) == MEM)
6407         y = adjust_address (operands[1], V2SFmode,
6408                             i * GET_MODE_SIZE (V2SFmode));
6409       else
6410         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6411
6412       emit_insn (gen_movv2sf_i (x, y));
6413     }
6414
6415   DONE;
6416 }"
6417   [(set_attr "length" "8")])
6418
6419 (define_expand "movv4sf"
6420   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6421         (match_operand:V4SF 1 "general_operand" ""))]
6422   "TARGET_SHMEDIA_FPU"
6423   "
6424 {
6425   if (prepare_move_operands (operands, V4SFmode))
6426     DONE;
6427 }")
6428
6429 (define_insn_and_split "*movv16sf_i"
6430   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6431         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6432   "TARGET_SHMEDIA_FPU"
6433   "#"
6434   "&& reload_completed"
6435   [(const_int 0)]
6436   "
6437 {
6438   int i;
6439
6440   for (i = 0; i < 16/2; i++)
6441     {
6442       rtx x,y;
6443
6444       if (GET_CODE (operands[0]) == MEM)
6445         x = adjust_address (operands[0], V2SFmode,
6446                             i * GET_MODE_SIZE (V2SFmode));
6447       else
6448         {
6449           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6450           alter_subreg (&x);
6451         }
6452
6453       if (GET_CODE (operands[1]) == MEM)
6454         y = adjust_address (operands[1], V2SFmode,
6455                             i * GET_MODE_SIZE (V2SFmode));
6456       else
6457         {
6458           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6459           alter_subreg (&y);
6460         }
6461
6462       emit_insn (gen_movv2sf_i (x, y));
6463     }
6464
6465   DONE;
6466 }"
6467   [(set_attr "length" "32")])
6468
6469 (define_expand "movv16sf"
6470   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6471         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6472   "TARGET_SHMEDIA_FPU"
6473   "
6474 {
6475   if (prepare_move_operands (operands, V16SFmode))
6476     DONE;
6477 }")
6478
6479 (define_insn "movsf_media"
6480   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6481         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6482   "TARGET_SHMEDIA_FPU
6483    && (register_operand (operands[0], SFmode)
6484        || sh_register_operand (operands[1], SFmode))"
6485   "@
6486         fmov.s  %1, %0
6487         fmov.ls %N1, %0
6488         fmov.sl %1, %0
6489         add.l   %1, r63, %0
6490         #
6491         fld%M1.s        %m1, %0
6492         fst%M0.s        %m0, %1
6493         ld%M1.l %m1, %0
6494         st%M0.l %m0, %N1"
6495   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6496    (set (attr "highpart")
6497         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6498                (const_string "user")]
6499               (const_string "ignore")))])
6500
6501 (define_insn "movsf_media_nofpu"
6502   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6503         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6504   "TARGET_SHMEDIA
6505    && (register_operand (operands[0], SFmode)
6506        || sh_register_operand (operands[1], SFmode))"
6507   "@
6508         add.l   %1, r63, %0
6509         #
6510         ld%M1.l %m1, %0
6511         st%M0.l %m0, %N1"
6512   [(set_attr "type" "arith_media,*,load_media,store_media")
6513    (set (attr "highpart")
6514         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6515                (const_string "user")]
6516               (const_string "ignore")))])
6517
6518 (define_split
6519   [(set (match_operand:SF 0 "arith_reg_dest" "")
6520         (match_operand:SF 1 "immediate_operand" ""))]
6521   "TARGET_SHMEDIA && reload_completed
6522    && ! FP_REGISTER_P (true_regnum (operands[0]))"
6523   [(set (match_dup 3) (match_dup 2))]
6524   "
6525 {
6526   long values;
6527   REAL_VALUE_TYPE value;
6528
6529   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6530   REAL_VALUE_TO_TARGET_SINGLE (value, values);
6531   operands[2] = GEN_INT (values);
6532
6533   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6534 }")
6535
6536 (define_insn "movsf_i"
6537   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6538         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
6539   "TARGET_SH1
6540    && (! TARGET_SH2E
6541        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6542        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
6543        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
6544    && (arith_reg_operand (operands[0], SFmode)
6545        || arith_reg_operand (operands[1], SFmode))"
6546   "@
6547         mov     %1,%0
6548         mov     #0,%0
6549         mov.l   %1,%0
6550         mov.l   %1,%0
6551         mov.l   %1,%0
6552         lds     %1,%0
6553         sts     %1,%0"
6554   [(set_attr "type" "move,move,pcload,load,store,move,move")])
6555
6556 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6557 ;; update_flow_info would not know where to put REG_EQUAL notes
6558 ;; when the destination changes mode.
6559 (define_insn "movsf_ie"
6560   [(set (match_operand:SF 0 "general_movdst_operand"
6561          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6562         (match_operand:SF 1 "general_movsrc_operand"
6563           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6564    (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"))
6565    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6566
6567   "TARGET_SH2E
6568    && (arith_reg_operand (operands[0], SFmode)
6569        || arith_reg_operand (operands[1], SFmode)
6570        || arith_reg_operand (operands[3], SImode)
6571        || (fpul_operand (operands[0], SFmode)
6572            && memory_operand (operands[1], SFmode)
6573            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6574        || (fpul_operand (operands[1], SFmode)
6575            && memory_operand (operands[0], SFmode)
6576            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6577   "@
6578         fmov    %1,%0
6579         mov     %1,%0
6580         fldi0   %0
6581         fldi1   %0
6582         #
6583         fmov.s  %1,%0
6584         fmov.s  %1,%0
6585         mov.l   %1,%0
6586         mov.l   %1,%0
6587         mov.l   %1,%0
6588         fsts    fpul,%0
6589         flds    %1,fpul
6590         lds.l   %1,%0
6591         #
6592         sts     %1,%0
6593         lds     %1,%0
6594         sts.l   %1,%0
6595         lds.l   %1,%0
6596         ! move optimized away"
6597   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6598    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6599    (set_attr "length" "*,*,*,*,4,2,2,*,*,*,2,2,2,4,2,2,2,2,0")
6600    (set_attr_alternative "length"
6601      [(const_int 2)
6602       (const_int 2)
6603       (const_int 2)
6604       (const_int 2)
6605       (const_int 4)
6606       (if_then_else
6607         (ne (symbol_ref "TARGET_SH2A") (const_int 0))
6608         (const_int 4) (const_int 2))
6609       (if_then_else
6610         (ne (symbol_ref "TARGET_SH2A") (const_int 0))
6611         (const_int 4) (const_int 2))
6612       (const_int 2)
6613       (const_int 2)
6614       (const_int 2)
6615       (const_int 2)
6616       (const_int 2)
6617       (const_int 2)
6618       (const_int 4)
6619       (const_int 2)
6620       (const_int 2)
6621       (const_int 2)
6622       (const_int 2)
6623       (const_int 0)])
6624    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6625                                            (const_string "single")
6626                                            (const_string "none")))])
6627
6628 (define_split
6629   [(set (match_operand:SF 0 "register_operand" "")
6630         (match_operand:SF 1 "register_operand" ""))
6631    (use (match_operand:PSI 2 "fpscr_operand" ""))
6632    (clobber (reg:SI FPUL_REG))]
6633   "TARGET_SH1"
6634   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6635               (use (match_dup 2))
6636               (clobber (scratch:SI))])
6637    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6638               (use (match_dup 2))
6639               (clobber (scratch:SI))])]
6640   "")
6641
6642 (define_expand "movsf"
6643   [(set (match_operand:SF 0 "general_movdst_operand" "")
6644         (match_operand:SF 1 "general_movsrc_operand" ""))]
6645   ""
6646   "
6647 {
6648   if (prepare_move_operands (operands, SFmode))
6649     DONE;
6650   if (TARGET_SHMEDIA)
6651     {
6652       if (TARGET_SHMEDIA_FPU)
6653         emit_insn (gen_movsf_media (operands[0], operands[1]));
6654       else
6655         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6656       DONE;
6657     }
6658   if (TARGET_SH2E)
6659     {
6660       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6661       DONE;
6662     }
6663 }")
6664
6665 (define_insn "mov_nop"
6666   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6667   "TARGET_SH2E"
6668   ""
6669   [(set_attr "length" "0")
6670    (set_attr "type" "nil")])
6671
6672 (define_expand "reload_insf__frn"
6673   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6674                    (match_operand:SF 1 "immediate_operand" "FQ"))
6675               (use (reg:PSI FPSCR_REG))
6676               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6677   "TARGET_SH1"
6678   "")
6679
6680 (define_expand "reload_insi__i_fpul"
6681   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6682                    (match_operand:SI 1 "immediate_operand" "i"))
6683               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6684   "TARGET_SH1"
6685   "")
6686
6687 (define_expand "ptabs"
6688   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6689   "TARGET_SHMEDIA"
6690   "
6691 {
6692   if (!TARGET_PT_FIXED)
6693     {
6694       rtx eq = operands[1];
6695
6696       /* ??? For canonical RTL we really should remove any CONST from EQ
6697          before wrapping it in the AND, and finally wrap the EQ into a
6698          const if is constant.  However, for reload we must expose the
6699          input register or symbolic constant, and we can't have
6700          different insn structures outside of the operands for different
6701          alternatives of the same pattern.  */
6702       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6703                        GEN_INT (3));
6704       operands[1]
6705         = (gen_rtx_IF_THEN_ELSE
6706             (PDImode,
6707              eq,
6708              gen_rtx_MEM (PDImode, operands[1]),
6709              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6710                             PDImode, operands[1])));
6711     }
6712 }")
6713
6714 ;; expanded by ptabs expander.
6715 (define_insn "*extendsipdi_media"
6716   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6717         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6718                                                           "r,Csy")
6719                                       (const_int 3))
6720                               (const_int 3))
6721                           (mem:PDI (match_dup 1))
6722                           (sign_extend:PDI (match_dup 1))))]
6723   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6724   "@
6725         ptabs   %1, %0
6726         pt      %1, %0"
6727   [(set_attr "type"   "ptabs_media,pt_media")
6728    (set_attr "length" "4,*")])
6729
6730 (define_insn "*truncdipdi_media"
6731   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6732         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6733                                                           "r,Csy")
6734                                       (const_int 3))
6735                               (const_int 3))
6736                           (mem:PDI (match_dup 1))
6737                           (truncate:PDI (match_dup 1))))]
6738   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6739   "@
6740         ptabs   %1, %0
6741         pt      %1, %0"
6742   [(set_attr "type"   "ptabs_media,pt_media")
6743    (set_attr "length" "4,*")])
6744
6745 (define_insn "*movsi_y"
6746   [(set (match_operand:SI 0 "register_operand" "=y,y")
6747         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
6748    (clobber (match_scratch:SI 2 "=&z,r"))]
6749   "TARGET_SH2E
6750    && (reload_in_progress || reload_completed)"
6751   "#"
6752   [(set_attr "length" "4")
6753    (set_attr "type" "pcload,move")])
6754
6755 (define_split
6756   [(set (match_operand:SI 0 "register_operand" "")
6757         (match_operand:SI 1 "immediate_operand" ""))
6758    (clobber (match_operand:SI 2 "register_operand" ""))]
6759   "TARGET_SH1"
6760   [(set (match_dup 2) (match_dup 1))
6761    (set (match_dup 0) (match_dup 2))]
6762   "")
6763
6764 (define_split
6765   [(set (match_operand:SI 0 "register_operand" "")
6766         (match_operand:SI 1 "memory_operand" ""))
6767    (clobber (reg:SI R0_REG))]
6768   "TARGET_SH1"
6769   [(set (match_dup 0) (match_dup 1))]
6770   "")
6771 \f
6772 ;; ------------------------------------------------------------------------
6773 ;; Define the real conditional branch instructions.
6774 ;; ------------------------------------------------------------------------
6775
6776 (define_insn "branch_true"
6777   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6778                            (label_ref (match_operand 0 "" ""))
6779                            (pc)))]
6780   "TARGET_SH1"
6781   "* return output_branch (1, insn, operands);"
6782   [(set_attr "type" "cbranch")])
6783
6784 (define_insn "branch_false"
6785   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6786                            (label_ref (match_operand 0 "" ""))
6787                            (pc)))]
6788   "TARGET_SH1"
6789   "* return output_branch (0, insn, operands);"
6790   [(set_attr "type" "cbranch")])
6791
6792 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
6793 ;; which destination is too far away.
6794 ;; The const_int_operand is distinct for each branch target; it avoids
6795 ;; unwanted matches with redundant_insn.
6796 (define_insn "block_branch_redirect"
6797   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
6798   "TARGET_SH1"
6799   ""
6800   [(set_attr "length" "0")])
6801
6802 ;; This one has the additional purpose to record a possible scratch register
6803 ;; for the following branch.
6804 ;; ??? Unfortunately, just setting the scratch register is not good enough,
6805 ;; because the insn then might be deemed dead and deleted.  And we can't
6806 ;; make the use in the jump insn explicit because that would disable
6807 ;; delay slot scheduling from the target.
6808 (define_insn "indirect_jump_scratch"
6809   [(set (match_operand:SI 0 "register_operand" "=r")
6810         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
6811    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
6812   "TARGET_SH1"
6813   ""
6814   [(set_attr "length" "0")])
6815
6816 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
6817 ;; being pulled into the delay slot of a condbranch that has been made to
6818 ;; jump around the unconditional jump because it was out of range.
6819 (define_insn "stuff_delay_slot"
6820   [(set (pc)
6821         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
6822    (set (reg:SI T_REG) (match_operand:SI 1 "const_int_operand" ""))]
6823   "TARGET_SH1"
6824   ""
6825   [(set_attr "length" "0")
6826    (set_attr "cond_delay_slot" "yes")])
6827 \f
6828 ;; Conditional branch insns
6829
6830 (define_expand "beq_media"
6831   [(set (pc)
6832         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
6833                           (match_operand:DI 2 "arith_operand" "r,I06"))
6834                       (match_operand 0 "" "")
6835                       (pc)))]
6836   "TARGET_SHMEDIA"
6837   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6838
6839 (define_insn "*beq_media_i"
6840   [(set (pc)
6841         (if_then_else (match_operator 3 "equality_comparison_operator"
6842                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
6843                          (match_operand:DI 2 "arith_operand" "r,I06")])
6844                       (match_operand 0 "target_operand" "b,b")
6845                       (pc)))]
6846   "TARGET_SHMEDIA"
6847   "@
6848         b%o3%'  %1, %2, %0%>
6849         b%o3i%' %1, %2, %0%>"
6850   [(set_attr "type" "cbranch_media")])
6851
6852 (define_insn "*beq_media_i32"
6853   [(set (pc)
6854         (if_then_else (match_operator 3 "equality_comparison_operator"
6855                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
6856                          (match_operand:SI 2 "arith_operand" "r,I06")])
6857                       (match_operand 0 "target_operand" "b,b")
6858                       (pc)))]
6859   "TARGET_SHMEDIA"
6860   "@
6861         b%o3%'  %1, %2, %0%>
6862         b%o3i%' %1, %2, %0%>"
6863   [(set_attr "type" "cbranch_media")])
6864
6865 (define_expand "bne_media"
6866   [(set (pc)
6867         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
6868                           (match_operand:DI 2 "arith_operand" "r,I06"))
6869                       (match_operand 0 "" "")
6870                       (pc)))]
6871   "TARGET_SHMEDIA"
6872   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6873
6874 (define_expand "bgt_media"
6875   [(set (pc)
6876         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "")
6877                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6878                       (match_operand 0 "" "")
6879                       (pc)))]
6880   "TARGET_SHMEDIA"
6881   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6882
6883 (define_expand "bge_media"
6884   [(set (pc)
6885         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "")
6886                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6887                       (match_operand 0 "" "")
6888                       (pc)))]
6889   "TARGET_SHMEDIA"
6890   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6891
6892 (define_expand "bgtu_media"
6893   [(set (pc)
6894         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6895                            (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6896                       (match_operand 0 "" "")
6897                       (pc)))]
6898   "TARGET_SHMEDIA"
6899   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6900
6901 (define_expand "bgeu_media"
6902   [(set (pc)
6903         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6904                            (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6905                       (match_operand 0 "" "")
6906                       (pc)))]
6907   "TARGET_SHMEDIA"
6908   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6909
6910 (define_insn "*bgt_media_i"
6911   [(set (pc)
6912         (if_then_else (match_operator 3 "greater_comparison_operator"
6913                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6914                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6915                       (match_operand 0 "target_operand" "b")
6916                       (pc)))]
6917   "TARGET_SHMEDIA"
6918   "b%o3%'       %N1, %N2, %0%>"
6919   [(set_attr "type" "cbranch_media")])
6920
6921 (define_insn "*bgt_media_i32"
6922   [(set (pc)
6923         (if_then_else (match_operator 3 "greater_comparison_operator"
6924                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6925                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6926                       (match_operand 0 "target_operand" "b")
6927                       (pc)))]
6928   "TARGET_SHMEDIA"
6929   "b%o3%'       %N1, %N2, %0%>"
6930   [(set_attr "type" "cbranch_media")])
6931
6932 ;; These are only needed to make invert_jump() happy - otherwise, jump
6933 ;; optimization will be silently disabled.
6934 (define_insn "*blt_media_i"
6935   [(set (pc)
6936         (if_then_else (match_operator 3 "less_comparison_operator"
6937                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6938                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6939                       (match_operand 0 "target_operand" "b")
6940                       (pc)))]
6941   "TARGET_SHMEDIA"
6942   "b%o3%'       %N2, %N1, %0%>"
6943   [(set_attr "type" "cbranch_media")])
6944
6945 (define_insn "*blt_media_i32"
6946   [(set (pc)
6947         (if_then_else (match_operator 3 "less_comparison_operator"
6948                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6949                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6950                       (match_operand 0 "target_operand" "b")
6951                       (pc)))]
6952   "TARGET_SHMEDIA"
6953   "b%o3%'       %N2, %N1, %0%>"
6954   [(set_attr "type" "cbranch_media")])
6955
6956 (define_expand "beq"
6957   [(set (pc)
6958         (if_then_else (ne (reg:SI T_REG) (const_int 0))
6959                       (label_ref (match_operand 0 "" ""))
6960                       (pc)))]
6961   ""
6962   "
6963 {
6964   if (TARGET_SHMEDIA)
6965     {
6966       enum machine_mode mode = GET_MODE (sh_compare_op0);
6967
6968       if (mode != DImode && mode != SImode)
6969         {
6970           rtx tmp = gen_reg_rtx (DImode);
6971
6972           emit_insn (gen_seq (tmp));
6973           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6974           DONE;
6975         }
6976
6977       sh_compare_op0 = force_reg (mode, sh_compare_op0);
6978       if (CONSTANT_P (sh_compare_op1)
6979           && (! satisfies_constraint_I06 (sh_compare_op1)))
6980         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6981       emit_jump_insn (gen_beq_media (operands[0],
6982                                      sh_compare_op0, sh_compare_op1));
6983       DONE;
6984     }
6985
6986   from_compare (operands, EQ);
6987 }")
6988
6989 (define_expand "bne"
6990   [(set (pc)
6991         (if_then_else (eq (reg:SI T_REG) (const_int 0))
6992                       (label_ref (match_operand 0 "" ""))
6993                       (pc)))]
6994   ""
6995   "
6996 {
6997   if (TARGET_SHMEDIA)
6998     {
6999       enum machine_mode mode = GET_MODE (sh_compare_op0);
7000
7001       if (mode != DImode && mode != SImode)
7002         {
7003           rtx tmp = gen_reg_rtx (DImode);
7004
7005           emit_insn (gen_seq (tmp));
7006           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
7007           DONE;
7008         }
7009
7010       sh_compare_op0 = force_reg (mode, sh_compare_op0);
7011       if (CONSTANT_P (sh_compare_op1)
7012           && (! satisfies_constraint_I06 (sh_compare_op1)))
7013         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7014       emit_jump_insn (gen_bne_media (operands[0],
7015                                      sh_compare_op0, sh_compare_op1));
7016       DONE;
7017     }
7018
7019   from_compare (operands, EQ);
7020 }")
7021
7022 (define_expand "bgt"
7023   [(set (pc)
7024         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7025                       (label_ref (match_operand 0 "" ""))
7026                       (pc)))]
7027   ""
7028   "
7029 {
7030   if (TARGET_SHMEDIA)
7031     {
7032       enum machine_mode mode = GET_MODE (sh_compare_op0);
7033
7034       if (mode != DImode && mode != SImode)
7035         {
7036           rtx tmp = gen_reg_rtx (DImode);
7037
7038           emit_insn (gen_sgt (tmp));
7039           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7040           DONE;
7041         }
7042
7043       if (sh_compare_op0 != const0_rtx)
7044         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7045       if (sh_compare_op1 != const0_rtx)
7046         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7047       emit_jump_insn (gen_bgt_media (operands[0],
7048                                      sh_compare_op0, sh_compare_op1));
7049       DONE;
7050     }
7051
7052   from_compare (operands, GT);
7053 }")
7054
7055 (define_expand "blt"
7056   [(set (pc)
7057         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7058                       (label_ref (match_operand 0 "" ""))
7059                       (pc)))]
7060   ""
7061   "
7062 {
7063   if (TARGET_SHMEDIA)
7064     {
7065       enum machine_mode mode = GET_MODE (sh_compare_op0);
7066
7067       if (mode != DImode && mode != SImode)
7068         {
7069           rtx tmp = gen_reg_rtx (DImode);
7070
7071           emit_insn (gen_slt (tmp));
7072           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7073           DONE;
7074         }
7075
7076       if (sh_compare_op0 != const0_rtx)
7077         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7078       if (sh_compare_op1 != const0_rtx)
7079         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7080       emit_jump_insn (gen_bgt_media (operands[0],
7081                                      sh_compare_op1, sh_compare_op0));
7082       DONE;
7083     }
7084
7085   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7086     {
7087       rtx tmp = sh_compare_op0;
7088       sh_compare_op0 = sh_compare_op1;
7089       sh_compare_op1 = tmp;
7090       emit_insn (gen_bgt (operands[0]));
7091       DONE;
7092     }
7093   from_compare (operands, GE);
7094 }")
7095
7096 (define_expand "ble"
7097   [(set (pc)
7098         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7099                       (label_ref (match_operand 0 "" ""))
7100                       (pc)))]
7101   ""
7102   "
7103 {
7104   if (TARGET_SHMEDIA)
7105     {
7106       enum machine_mode mode = GET_MODE (sh_compare_op0);
7107
7108       if (mode != DImode && mode != SImode)
7109         {
7110           rtx tmp = gen_reg_rtx (DImode);
7111
7112           emit_insn (gen_sle (tmp));
7113           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7114           DONE;
7115         }
7116
7117       if (sh_compare_op0 != const0_rtx)
7118         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7119       if (sh_compare_op1 != const0_rtx)
7120         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7121       emit_jump_insn (gen_bge_media (operands[0],
7122                                      sh_compare_op1, sh_compare_op0));
7123       DONE;
7124     }
7125
7126   if (TARGET_SH2E
7127       && TARGET_IEEE
7128       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7129     {
7130       rtx tmp = sh_compare_op0;
7131       sh_compare_op0 = sh_compare_op1;
7132       sh_compare_op1 = tmp;
7133       emit_insn (gen_bge (operands[0]));
7134       DONE;
7135     }
7136   from_compare (operands, GT);
7137 }")
7138
7139 (define_expand "bge"
7140   [(set (pc)
7141         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7142                       (label_ref (match_operand 0 "" ""))
7143                       (pc)))]
7144   ""
7145   "
7146 {
7147   if (TARGET_SHMEDIA)
7148     {
7149       enum machine_mode mode = GET_MODE (sh_compare_op0);
7150
7151       if (mode != DImode && mode != SImode)
7152         {
7153           rtx tmp = gen_reg_rtx (DImode);
7154
7155           emit_insn (gen_sge (tmp));
7156           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7157           DONE;
7158         }
7159
7160       if (sh_compare_op0 != const0_rtx)
7161         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7162       if (sh_compare_op1 != const0_rtx)
7163         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7164       emit_jump_insn (gen_bge_media (operands[0],
7165                                      sh_compare_op0, sh_compare_op1));
7166       DONE;
7167     }
7168
7169   if (TARGET_SH2E
7170       && ! TARGET_IEEE
7171       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7172     {
7173       rtx tmp = sh_compare_op0;
7174       sh_compare_op0 = sh_compare_op1;
7175       sh_compare_op1 = tmp;
7176       emit_insn (gen_ble (operands[0]));
7177       DONE;
7178     }
7179   from_compare (operands, GE);
7180 }")
7181
7182 (define_expand "bgtu"
7183   [(set (pc)
7184         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7185                       (label_ref (match_operand 0 "" ""))
7186                       (pc)))]
7187   ""
7188   "
7189 {
7190   if (TARGET_SHMEDIA)
7191     {
7192       enum machine_mode mode = GET_MODE (sh_compare_op0);
7193
7194       if (sh_compare_op0 != const0_rtx)
7195         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7196       if (sh_compare_op1 != const0_rtx)
7197         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7198       emit_jump_insn (gen_bgtu_media (operands[0],
7199                                       sh_compare_op0, sh_compare_op1));
7200       DONE;
7201     }
7202
7203   from_compare (operands, GTU);
7204 }")
7205
7206 (define_expand "bltu"
7207   [(set (pc)
7208         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7209                       (label_ref (match_operand 0 "" ""))
7210                       (pc)))]
7211   ""
7212   "
7213 {
7214   if (TARGET_SHMEDIA)
7215     {
7216       enum machine_mode mode = GET_MODE (sh_compare_op0);
7217
7218       if (sh_compare_op0 != const0_rtx)
7219         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7220       if (sh_compare_op1 != const0_rtx)
7221         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7222       emit_jump_insn (gen_bgtu_media (operands[0],
7223                                       sh_compare_op1, sh_compare_op0));
7224       DONE;
7225     }
7226
7227   from_compare (operands, GEU);
7228 }")
7229
7230 (define_expand "bgeu"
7231   [(set (pc)
7232         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7233                       (label_ref (match_operand 0 "" ""))
7234                       (pc)))]
7235   ""
7236   "
7237 {
7238   if (TARGET_SHMEDIA)
7239     {
7240       enum machine_mode mode = GET_MODE (sh_compare_op0);
7241
7242       if (sh_compare_op0 != const0_rtx)
7243         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7244       if (sh_compare_op1 != const0_rtx)
7245         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7246       emit_jump_insn (gen_bgeu_media (operands[0],
7247                                       sh_compare_op0, sh_compare_op1));
7248       DONE;
7249     }
7250
7251   from_compare (operands, GEU);
7252 }")
7253
7254 (define_expand "bleu"
7255   [(set (pc)
7256         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7257                       (label_ref (match_operand 0 "" ""))
7258                       (pc)))]
7259   ""
7260   "
7261 {
7262   if (TARGET_SHMEDIA)
7263     {
7264       enum machine_mode mode = GET_MODE (sh_compare_op0);
7265
7266       if (sh_compare_op0 != const0_rtx)
7267         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7268       if (sh_compare_op1 != const0_rtx)
7269         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7270       emit_jump_insn (gen_bgeu_media (operands[0],
7271                                       sh_compare_op1, sh_compare_op0));
7272       DONE;
7273     }
7274
7275   from_compare (operands, GTU);
7276 }")
7277
7278 (define_expand "bunordered"
7279   [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3)))
7280    (set (pc)
7281         (if_then_else (ne (match_dup 1) (const_int 0))
7282                       (match_operand 0 "" "")
7283                       (pc)))]
7284   "TARGET_SHMEDIA"
7285   "
7286 {
7287   operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);
7288   operands[1] = gen_reg_rtx (SImode);
7289   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7290   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7291 }")
7292
7293 ;; combiner splitter for test-and-branch on single bit in register.  This
7294 ;; is endian dependent because the non-paradoxical subreg looks different
7295 ;; on big endian.
7296 (define_split
7297   [(set (pc)
7298         (if_then_else
7299           (match_operator 3 "equality_comparison_operator"
7300             [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7301                                                       "extend_reg_operand" "")
7302                                                     0)
7303                                          (const_int 1)
7304                                          (match_operand 2
7305                                           "const_int_operand" "")) 0)
7306              (const_int 0)])
7307           (match_operand 0 "target_operand" "")
7308           (pc)))
7309    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7310   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7311   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7312    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7313
7314   "
7315 {
7316   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7317   operands[6] = (GET_CODE (operands[3]) == EQ
7318                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7319                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7320 }")
7321
7322 ; operand 0 is the loop count pseudo register
7323 ; operand 1 is the number of loop iterations or 0 if it is unknown
7324 ; operand 2 is the maximum number of loop iterations
7325 ; operand 3 is the number of levels of enclosed loops
7326 ; operand 4 is the label to jump to at the top of the loop
7327
7328 (define_expand "doloop_end"
7329   [(parallel [(set (pc) (if_then_else
7330                           (ne:SI (match_operand:SI 0 "" "")
7331                               (const_int 1))
7332                           (label_ref (match_operand 4 "" ""))
7333                           (pc)))
7334               (set (match_dup 0)
7335                    (plus:SI (match_dup 0) (const_int -1)))
7336               (clobber (reg:SI T_REG))])]
7337   "TARGET_SH2"
7338   "
7339 {
7340   if (GET_MODE (operands[0]) != SImode)
7341     FAIL;
7342 }
7343 ")
7344
7345 (define_insn_and_split "doloop_end_split"
7346   [(set (pc)
7347         (if_then_else (ne:SI (match_operand:SI 0 "arith_reg_dest" "+r")
7348                           (const_int 1))
7349                       (label_ref (match_operand 1 "" ""))
7350                       (pc)))
7351    (set (match_dup 0)
7352         (plus (match_dup 0) (const_int -1)))
7353    (clobber (reg:SI T_REG))]
7354   "TARGET_SH2"
7355   "#"
7356   ""
7357   [(parallel [(set (reg:SI T_REG)
7358                    (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r")
7359                           (const_int 1)))
7360               (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))])
7361    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7362                            (label_ref (match_operand 1 "" ""))
7363                            (pc)))]
7364 ""
7365    [(set_attr "type" "cbranch")])
7366
7367 \f
7368 ;; ------------------------------------------------------------------------
7369 ;; Jump and linkage insns
7370 ;; ------------------------------------------------------------------------
7371
7372 (define_insn "jump_compact"
7373   [(set (pc)
7374         (label_ref (match_operand 0 "" "")))]
7375   "TARGET_SH1"
7376   "*
7377 {
7378   /* The length is 16 if the delay slot is unfilled.  */
7379   if (get_attr_length(insn) > 4)
7380     return output_far_jump(insn, operands[0]);
7381   else
7382     return   \"bra      %l0%#\";
7383 }"
7384   [(set_attr "type" "jump")
7385    (set_attr "needs_delay_slot" "yes")])
7386
7387 ;; ??? It would be much saner to explicitly use the scratch register
7388 ;; in the jump insn, and have indirect_jump_scratch only set it,
7389 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7390 ;; from the target then, as it uses simplejump_p.
7391 ;;(define_insn "jump_compact_far"
7392 ;;  [(set (pc)
7393 ;;      (label_ref (match_operand 0 "" "")))
7394 ;;   (use (match_operand 1 "register_operand" "r")]
7395 ;;  "TARGET_SH1"
7396 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
7397 ;;  [(set_attr "type" "jump")
7398 ;;   (set_attr "needs_delay_slot" "yes")])
7399
7400 (define_insn "jump_media"
7401   [(set (pc)
7402         (match_operand 0 "target_operand" "b"))]
7403   "TARGET_SHMEDIA"
7404   "blink        %0, r63%>"
7405   [(set_attr "type" "jump_media")])
7406
7407 (define_expand "jump"
7408   [(set (pc)
7409         (label_ref (match_operand 0 "" "")))]
7410   ""
7411   "
7412 {
7413   if (TARGET_SH1)
7414     emit_jump_insn (gen_jump_compact (operands[0]));
7415   else if (TARGET_SHMEDIA)
7416     {
7417       if (reload_in_progress || reload_completed)
7418         FAIL;
7419       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7420                                                          operands[0])));
7421     }
7422   DONE;
7423 }")
7424
7425 (define_insn "force_mode_for_call"
7426   [(use (reg:PSI FPSCR_REG))]
7427   "TARGET_SHCOMPACT"
7428   ""
7429   [(set_attr "length" "0")
7430    (set (attr "fp_mode")
7431         (if_then_else (eq_attr "fpu_single" "yes")
7432                       (const_string "single") (const_string "double")))])
7433
7434 (define_insn "calli"
7435   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7436          (match_operand 1 "" ""))
7437    (use (reg:PSI FPSCR_REG))
7438    (clobber (reg:SI PR_REG))]
7439   "TARGET_SH1"
7440   "jsr  @%0%#"
7441   [(set_attr "type" "call")
7442    (set (attr "fp_mode")
7443         (if_then_else (eq_attr "fpu_single" "yes")
7444                       (const_string "single") (const_string "double")))
7445    (set_attr "needs_delay_slot" "yes")
7446    (set_attr "fp_set" "unknown")])
7447
7448 ;; This is a pc-rel call, using bsrf, for use with PIC.
7449
7450 (define_insn "calli_pcrel"
7451   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7452          (match_operand 1 "" ""))
7453    (use (reg:PSI FPSCR_REG))
7454    (use (reg:SI PIC_REG))
7455    (use (match_operand 2 "" ""))
7456    (clobber (reg:SI PR_REG))]
7457   "TARGET_SH2"
7458   "bsrf %0\\n%O2:%#"
7459   [(set_attr "type" "call")
7460    (set (attr "fp_mode")
7461         (if_then_else (eq_attr "fpu_single" "yes")
7462                       (const_string "single") (const_string "double")))
7463    (set_attr "needs_delay_slot" "yes")
7464    (set_attr "fp_set" "unknown")])
7465
7466 (define_insn_and_split "call_pcrel"
7467   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7468          (match_operand 1 "" ""))
7469    (use (reg:PSI FPSCR_REG))
7470    (use (reg:SI PIC_REG))
7471    (clobber (reg:SI PR_REG))
7472    (clobber (match_scratch:SI 2 "=r"))]
7473   "TARGET_SH2"
7474   "#"
7475   "reload_completed"
7476   [(const_int 0)]
7477   "
7478 {
7479   rtx lab = PATTERN (gen_call_site ());
7480
7481   if (SYMBOL_REF_LOCAL_P (operands[0]))
7482     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7483   else
7484     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7485   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7486   DONE;
7487 }"
7488   [(set_attr "type" "call")
7489    (set (attr "fp_mode")
7490         (if_then_else (eq_attr "fpu_single" "yes")
7491                       (const_string "single") (const_string "double")))
7492    (set_attr "needs_delay_slot" "yes")
7493    (set_attr "fp_set" "unknown")])
7494
7495 (define_insn "call_compact"
7496   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7497          (match_operand 1 "" ""))
7498    (match_operand 2 "immediate_operand" "n")
7499    (use (reg:SI R0_REG))
7500    (use (reg:SI R1_REG))
7501    (use (reg:PSI FPSCR_REG))
7502    (clobber (reg:SI PR_REG))]
7503   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7504   "jsr  @%0%#"
7505   [(set_attr "type" "call")
7506    (set (attr "fp_mode")
7507         (if_then_else (eq_attr "fpu_single" "yes")
7508                       (const_string "single") (const_string "double")))
7509    (set_attr "needs_delay_slot" "yes")])
7510
7511 (define_insn "call_compact_rettramp"
7512   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7513          (match_operand 1 "" ""))
7514    (match_operand 2 "immediate_operand" "n")
7515    (use (reg:SI R0_REG))
7516    (use (reg:SI R1_REG))
7517    (use (reg:PSI FPSCR_REG))
7518    (clobber (reg:SI R10_REG))
7519    (clobber (reg:SI PR_REG))]
7520   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7521   "jsr  @%0%#"
7522   [(set_attr "type" "call")
7523    (set (attr "fp_mode")
7524         (if_then_else (eq_attr "fpu_single" "yes")
7525                       (const_string "single") (const_string "double")))
7526    (set_attr "needs_delay_slot" "yes")])
7527
7528 (define_insn "call_media"
7529   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7530          (match_operand 1 "" ""))
7531    (clobber (reg:DI PR_MEDIA_REG))]
7532   "TARGET_SHMEDIA"
7533   "blink        %0, r18"
7534   [(set_attr "type" "jump_media")])
7535
7536 (define_insn "call_valuei"
7537   [(set (match_operand 0 "" "=rf")
7538         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7539               (match_operand 2 "" "")))
7540    (use (reg:PSI FPSCR_REG))
7541    (clobber (reg:SI PR_REG))]
7542   "TARGET_SH1"
7543   "jsr  @%1%#"
7544   [(set_attr "type" "call")
7545    (set (attr "fp_mode")
7546         (if_then_else (eq_attr "fpu_single" "yes")
7547                       (const_string "single") (const_string "double")))
7548    (set_attr "needs_delay_slot" "yes")
7549    (set_attr "fp_set" "unknown")])
7550
7551 (define_insn "call_valuei_pcrel"
7552   [(set (match_operand 0 "" "=rf")
7553         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7554               (match_operand 2 "" "")))
7555    (use (reg:PSI FPSCR_REG))
7556    (use (reg:SI PIC_REG))
7557    (use (match_operand 3 "" ""))
7558    (clobber (reg:SI PR_REG))]
7559   "TARGET_SH2"
7560   "bsrf %1\\n%O3:%#"
7561   [(set_attr "type" "call")
7562    (set (attr "fp_mode")
7563         (if_then_else (eq_attr "fpu_single" "yes")
7564                       (const_string "single") (const_string "double")))
7565    (set_attr "needs_delay_slot" "yes")
7566    (set_attr "fp_set" "unknown")])
7567
7568 (define_insn_and_split "call_value_pcrel"
7569   [(set (match_operand 0 "" "=rf")
7570         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7571               (match_operand 2 "" "")))
7572    (use (reg:PSI FPSCR_REG))
7573    (use (reg:SI PIC_REG))
7574    (clobber (reg:SI PR_REG))
7575    (clobber (match_scratch:SI 3 "=r"))]
7576   "TARGET_SH2"
7577   "#"
7578   "reload_completed"
7579   [(const_int 0)]
7580   "
7581 {
7582   rtx lab = PATTERN (gen_call_site ());
7583
7584   if (SYMBOL_REF_LOCAL_P (operands[1]))
7585     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7586   else
7587     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7588   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7589                                          operands[2], copy_rtx (lab)));
7590   DONE;
7591 }"
7592   [(set_attr "type" "call")
7593    (set (attr "fp_mode")
7594         (if_then_else (eq_attr "fpu_single" "yes")
7595                       (const_string "single") (const_string "double")))
7596    (set_attr "needs_delay_slot" "yes")
7597    (set_attr "fp_set" "unknown")])
7598
7599 (define_insn "call_value_compact"
7600   [(set (match_operand 0 "" "=rf")
7601         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7602               (match_operand 2 "" "")))
7603    (match_operand 3 "immediate_operand" "n")
7604    (use (reg:SI R0_REG))
7605    (use (reg:SI R1_REG))
7606    (use (reg:PSI FPSCR_REG))
7607    (clobber (reg:SI PR_REG))]
7608   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7609   "jsr  @%1%#"
7610   [(set_attr "type" "call")
7611    (set (attr "fp_mode")
7612         (if_then_else (eq_attr "fpu_single" "yes")
7613                       (const_string "single") (const_string "double")))
7614    (set_attr "needs_delay_slot" "yes")])
7615
7616 (define_insn "call_value_compact_rettramp"
7617   [(set (match_operand 0 "" "=rf")
7618         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7619               (match_operand 2 "" "")))
7620    (match_operand 3 "immediate_operand" "n")
7621    (use (reg:SI R0_REG))
7622    (use (reg:SI R1_REG))
7623    (use (reg:PSI FPSCR_REG))
7624    (clobber (reg:SI R10_REG))
7625    (clobber (reg:SI PR_REG))]
7626   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7627   "jsr  @%1%#"
7628   [(set_attr "type" "call")
7629    (set (attr "fp_mode")
7630         (if_then_else (eq_attr "fpu_single" "yes")
7631                       (const_string "single") (const_string "double")))
7632    (set_attr "needs_delay_slot" "yes")])
7633
7634 (define_insn "call_value_media"
7635   [(set (match_operand 0 "" "=rf")
7636         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7637               (match_operand 2 "" "")))
7638    (clobber (reg:DI PR_MEDIA_REG))]
7639   "TARGET_SHMEDIA"
7640   "blink        %1, r18"
7641   [(set_attr "type" "jump_media")])
7642
7643 (define_expand "call"
7644   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7645                             (match_operand 1 "" ""))
7646               (match_operand 2 "" "")
7647               (use (reg:PSI FPSCR_REG))
7648               (clobber (reg:SI PR_REG))])]
7649   ""
7650   "
7651 {
7652   if (TARGET_SHMEDIA)
7653     {
7654       operands[0] = shmedia_prepare_call_address (operands[0], 0);
7655       emit_call_insn (gen_call_media (operands[0], operands[1]));
7656       DONE;
7657     }
7658   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7659     {
7660       rtx cookie_rtx = operands[2];
7661       long cookie = INTVAL (cookie_rtx);
7662       rtx func = XEXP (operands[0], 0);
7663       rtx r0, r1;
7664
7665       if (flag_pic)
7666         {
7667           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7668             {
7669               rtx reg = gen_reg_rtx (Pmode);
7670
7671               emit_insn (gen_symGOTPLT2reg (reg, func));
7672               func = reg;
7673             }
7674           else
7675             func = legitimize_pic_address (func, Pmode, 0);
7676         }
7677
7678       r0 = gen_rtx_REG (SImode, R0_REG);
7679       r1 = gen_rtx_REG (SImode, R1_REG);
7680
7681       /* Since such a call function may use all call-clobbered
7682          registers, we force a mode switch earlier, so that we don't
7683          run out of registers when adjusting fpscr for the call.  */
7684       emit_insn (gen_force_mode_for_call ());
7685
7686       operands[0]
7687         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7688                            SFUNC_GOT);
7689       operands[0] = force_reg (SImode, operands[0]);
7690
7691       emit_move_insn (r0, func);
7692       emit_move_insn (r1, cookie_rtx);
7693
7694       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7695         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7696                                                    operands[2]));
7697       else
7698         emit_call_insn (gen_call_compact (operands[0], operands[1],
7699                                           operands[2]));
7700
7701       DONE;
7702     }
7703   else if (TARGET_SHCOMPACT && flag_pic
7704            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7705            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7706     {
7707       rtx reg = gen_reg_rtx (Pmode);
7708
7709       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7710       XEXP (operands[0], 0) = reg;
7711     }
7712   if (flag_pic && TARGET_SH2
7713       && GET_CODE (operands[0]) == MEM
7714       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7715     {
7716       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7717       DONE;
7718     }
7719   else
7720   {
7721     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7722     operands[1] = operands[2];
7723   }
7724
7725   emit_call_insn (gen_calli (operands[0], operands[1]));
7726   DONE;
7727 }")
7728
7729 (define_insn "call_pop_compact"
7730   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7731          (match_operand 1 "" ""))
7732    (match_operand 2 "immediate_operand" "n")
7733    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7734                                  (match_operand 3 "immediate_operand" "n")))
7735    (use (reg:SI R0_REG))
7736    (use (reg:SI R1_REG))
7737    (use (reg:PSI FPSCR_REG))
7738    (clobber (reg:SI PR_REG))]
7739   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7740   "jsr  @%0%#"
7741   [(set_attr "type" "call")
7742    (set (attr "fp_mode")
7743         (if_then_else (eq_attr "fpu_single" "yes")
7744                       (const_string "single") (const_string "double")))
7745    (set_attr "needs_delay_slot" "yes")])
7746
7747 (define_insn "call_pop_compact_rettramp"
7748   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7749          (match_operand 1 "" ""))
7750    (match_operand 2 "immediate_operand" "n")
7751    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7752                                  (match_operand 3 "immediate_operand" "n")))
7753    (use (reg:SI R0_REG))
7754    (use (reg:SI R1_REG))
7755    (use (reg:PSI FPSCR_REG))
7756    (clobber (reg:SI R10_REG))
7757    (clobber (reg:SI PR_REG))]
7758   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7759   "jsr  @%0%#"
7760   [(set_attr "type" "call")
7761    (set (attr "fp_mode")
7762         (if_then_else (eq_attr "fpu_single" "yes")
7763                       (const_string "single") (const_string "double")))
7764    (set_attr "needs_delay_slot" "yes")])
7765
7766 (define_expand "call_pop"
7767   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7768                     (match_operand 1 "" ""))
7769              (match_operand 2 "" "")
7770              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7771                                            (match_operand 3 "" "")))])]
7772   "TARGET_SHCOMPACT"
7773   "
7774 {
7775   rtx cookie_rtx;
7776   long cookie;
7777   rtx func;
7778   rtx r0, r1;
7779
7780   gcc_assert (operands[2] && INTVAL (operands[2]));
7781   cookie_rtx = operands[2];
7782   cookie = INTVAL (cookie_rtx);
7783   func = XEXP (operands[0], 0);
7784
7785   if (flag_pic)
7786     {
7787       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7788         {
7789           rtx reg = gen_reg_rtx (Pmode);
7790           emit_insn (gen_symGOTPLT2reg (reg, func));
7791           func = reg;
7792         }
7793       else
7794         func = legitimize_pic_address (func, Pmode, 0);
7795     }
7796
7797   r0 = gen_rtx_REG (SImode, R0_REG);
7798   r1 = gen_rtx_REG (SImode, R1_REG);
7799
7800   /* Since such a call function may use all call-clobbered
7801      registers, we force a mode switch earlier, so that we don't
7802      run out of registers when adjusting fpscr for the call.  */
7803   emit_insn (gen_force_mode_for_call ());
7804
7805   operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7806                                  SFUNC_GOT);
7807   operands[0] = force_reg (SImode, operands[0]);
7808
7809   emit_move_insn (r0, func);
7810   emit_move_insn (r1, cookie_rtx);
7811
7812   if (cookie & CALL_COOKIE_RET_TRAMP (1))
7813     emit_call_insn (gen_call_pop_compact_rettramp
7814                      (operands[0], operands[1], operands[2], operands[3]));
7815   else
7816     emit_call_insn (gen_call_pop_compact
7817                      (operands[0], operands[1], operands[2], operands[3]));
7818
7819   DONE;
7820 }")
7821
7822 (define_expand "call_value"
7823   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7824                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7825                                  (match_operand 2 "" "")))
7826               (match_operand 3 "" "")
7827               (use (reg:PSI FPSCR_REG))
7828               (clobber (reg:SI PR_REG))])]
7829   ""
7830   "
7831 {
7832   if (TARGET_SHMEDIA)
7833     {
7834       operands[1] = shmedia_prepare_call_address (operands[1], 0);
7835       emit_call_insn (gen_call_value_media (operands[0], operands[1],
7836                                             operands[2]));
7837       DONE;
7838     }
7839   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7840     {
7841       rtx cookie_rtx = operands[3];
7842       long cookie = INTVAL (cookie_rtx);
7843       rtx func = XEXP (operands[1], 0);
7844       rtx r0, r1;
7845
7846       if (flag_pic)
7847         {
7848           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7849             {
7850               rtx reg = gen_reg_rtx (Pmode);
7851
7852               emit_insn (gen_symGOTPLT2reg (reg, func));
7853               func = reg;
7854             }
7855           else
7856             func = legitimize_pic_address (func, Pmode, 0);
7857         }
7858
7859       r0 = gen_rtx_REG (SImode, R0_REG);
7860       r1 = gen_rtx_REG (SImode, R1_REG);
7861
7862       /* Since such a call function may use all call-clobbered
7863          registers, we force a mode switch earlier, so that we don't
7864          run out of registers when adjusting fpscr for the call.  */
7865       emit_insn (gen_force_mode_for_call ());
7866
7867       operands[1]
7868         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7869                            SFUNC_GOT);
7870       operands[1] = force_reg (SImode, operands[1]);
7871
7872       emit_move_insn (r0, func);
7873       emit_move_insn (r1, cookie_rtx);
7874
7875       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7876         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7877                                                          operands[1],
7878                                                          operands[2],
7879                                                          operands[3]));
7880       else
7881         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7882                                                 operands[2], operands[3]));
7883
7884       DONE;
7885     }
7886   else if (TARGET_SHCOMPACT && flag_pic
7887            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7888            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7889     {
7890       rtx reg = gen_reg_rtx (Pmode);
7891
7892       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7893       XEXP (operands[1], 0) = reg;
7894     }
7895   if (flag_pic && TARGET_SH2
7896       && GET_CODE (operands[1]) == MEM
7897       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7898     {
7899       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7900                                             operands[2]));
7901       DONE;
7902     }
7903   else
7904     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7905
7906   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7907   DONE;
7908 }")
7909
7910 (define_insn "sibcalli"
7911   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7912          (match_operand 1 "" ""))
7913    (use (reg:PSI FPSCR_REG))
7914    (return)]
7915   "TARGET_SH1"
7916   "jmp  @%0%#"
7917   [(set_attr "needs_delay_slot" "yes")
7918    (set (attr "fp_mode")
7919         (if_then_else (eq_attr "fpu_single" "yes")
7920                       (const_string "single") (const_string "double")))
7921    (set_attr "type" "jump_ind")])
7922
7923 (define_insn "sibcalli_pcrel"
7924   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7925          (match_operand 1 "" ""))
7926    (use (match_operand 2 "" ""))
7927    (use (reg:PSI FPSCR_REG))
7928    (return)]
7929   "TARGET_SH2"
7930   "braf %0\\n%O2:%#"
7931   [(set_attr "needs_delay_slot" "yes")
7932    (set (attr "fp_mode")
7933         (if_then_else (eq_attr "fpu_single" "yes")
7934                       (const_string "single") (const_string "double")))
7935    (set_attr "type" "jump_ind")])
7936
7937 ;; This uses an unspec to describe that the symbol_ref is very close.
7938 (define_insn "sibcalli_thunk"
7939   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7940                              UNSPEC_THUNK))
7941          (match_operand 1 "" ""))
7942    (use (reg:PSI FPSCR_REG))
7943    (return)]
7944   "TARGET_SH1"
7945   "bra  %O0"
7946   [(set_attr "needs_delay_slot" "yes")
7947    (set (attr "fp_mode")
7948         (if_then_else (eq_attr "fpu_single" "yes")
7949                       (const_string "single") (const_string "double")))
7950    (set_attr "type" "jump")
7951    (set_attr "length" "2")])
7952
7953 (define_insn_and_split "sibcall_pcrel"
7954   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7955          (match_operand 1 "" ""))
7956    (use (reg:PSI FPSCR_REG))
7957    (clobber (match_scratch:SI 2 "=k"))
7958    (return)]
7959   "TARGET_SH2"
7960   "#"
7961   "reload_completed"
7962   [(const_int 0)]
7963   "
7964 {
7965   rtx lab = PATTERN (gen_call_site ());
7966   rtx call_insn;
7967
7968   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7969   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7970                                                   copy_rtx (lab)));
7971   SIBLING_CALL_P (call_insn) = 1;
7972   DONE;
7973 }"
7974   [(set_attr "needs_delay_slot" "yes")
7975    (set (attr "fp_mode")
7976         (if_then_else (eq_attr "fpu_single" "yes")
7977                       (const_string "single") (const_string "double")))
7978    (set_attr "type" "jump_ind")])
7979
7980 (define_insn "sibcall_compact"
7981   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7982          (match_operand 1 "" ""))
7983    (return)
7984    (use (match_operand:SI 2 "register_operand" "z,x"))
7985    (use (reg:SI R1_REG))
7986    (use (reg:PSI FPSCR_REG))
7987    ;; We want to make sure the `x' above will only match MACH_REG
7988    ;; because sibcall_epilogue may clobber MACL_REG.
7989    (clobber (reg:SI MACL_REG))]
7990   "TARGET_SHCOMPACT"
7991   "@
7992         jmp     @%0%#
7993         jmp     @%0\\n  sts     %2, r0"
7994   [(set_attr "needs_delay_slot" "yes,no")
7995    (set_attr "length" "2,4")
7996    (set (attr "fp_mode") (const_string "single"))
7997    (set_attr "type" "jump_ind")])
7998
7999 (define_insn "sibcall_media"
8000   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
8001          (match_operand 1 "" ""))
8002    (use (reg:SI PR_MEDIA_REG))
8003    (return)]
8004   "TARGET_SHMEDIA"
8005   "blink        %0, r63"
8006   [(set_attr "type" "jump_media")])
8007
8008 (define_expand "sibcall"
8009   [(parallel
8010     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
8011            (match_operand 1 "" ""))
8012      (match_operand 2 "" "")
8013      (use (reg:PSI FPSCR_REG))
8014      (return)])]
8015   ""
8016   "
8017 {
8018   if (TARGET_SHMEDIA)
8019     {
8020       operands[0] = shmedia_prepare_call_address (operands[0], 1);
8021       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
8022       DONE;
8023     }
8024   else if (TARGET_SHCOMPACT && operands[2]
8025            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8026     {
8027       rtx cookie_rtx = operands[2];
8028       long cookie = INTVAL (cookie_rtx);
8029       rtx func = XEXP (operands[0], 0);
8030       rtx mach, r1;
8031
8032       if (flag_pic)
8033         {
8034           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8035             {
8036               rtx reg = gen_reg_rtx (Pmode);
8037
8038               emit_insn (gen_symGOT2reg (reg, func));
8039               func = reg;
8040             }
8041           else
8042             func = legitimize_pic_address (func, Pmode, 0);
8043         }
8044
8045       /* FIXME: if we could tell whether all argument registers are
8046          already taken, we could decide whether to force the use of
8047          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
8048          simple way to tell.  We could use the CALL_COOKIE, but we
8049          can't currently tell a register used for regular argument
8050          passing from one that is unused.  If we leave it up to reload
8051          to decide which register to use, it seems to always choose
8052          R0_REG, which leaves no available registers in SIBCALL_REGS
8053          to hold the address of the trampoline.  */
8054       mach = gen_rtx_REG (SImode, MACH_REG);
8055       r1 = gen_rtx_REG (SImode, R1_REG);
8056
8057       /* Since such a call function may use all call-clobbered
8058          registers, we force a mode switch earlier, so that we don't
8059          run out of registers when adjusting fpscr for the call.  */
8060       emit_insn (gen_force_mode_for_call ());
8061
8062       operands[0]
8063         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8064                            SFUNC_GOT);
8065       operands[0] = force_reg (SImode, operands[0]);
8066
8067       /* We don't need a return trampoline, since the callee will
8068          return directly to the upper caller.  */
8069       if (cookie & CALL_COOKIE_RET_TRAMP (1))
8070         {
8071           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8072           cookie_rtx = GEN_INT (cookie);
8073         }
8074
8075       emit_move_insn (mach, func);
8076       emit_move_insn (r1, cookie_rtx);
8077
8078       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
8079       DONE;
8080     }
8081   else if (TARGET_SHCOMPACT && flag_pic
8082            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8083            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8084     {
8085       rtx reg = gen_reg_rtx (Pmode);
8086
8087       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
8088       XEXP (operands[0], 0) = reg;
8089     }
8090   if (flag_pic && TARGET_SH2
8091       && GET_CODE (operands[0]) == MEM
8092       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8093       /* The PLT needs the PIC register, but the epilogue would have
8094          to restore it, so we can only use PC-relative PIC calls for
8095          static functions.  */
8096       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8097     {
8098       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
8099       DONE;
8100     }
8101   else
8102     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
8103
8104   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
8105   DONE;
8106 }")
8107
8108 (define_insn "sibcall_valuei"
8109   [(set (match_operand 0 "" "=rf")
8110         (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
8111               (match_operand 2 "" "")))
8112    (use (reg:PSI FPSCR_REG))
8113    (return)]
8114   "TARGET_SH1"
8115   "jmp  @%1%#"
8116   [(set_attr "needs_delay_slot" "yes")
8117    (set (attr "fp_mode")
8118         (if_then_else (eq_attr "fpu_single" "yes")
8119                       (const_string "single") (const_string "double")))
8120    (set_attr "type" "jump_ind")])
8121
8122 (define_insn "sibcall_valuei_pcrel"
8123   [(set (match_operand 0 "" "=rf")
8124         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
8125               (match_operand 2 "" "")))
8126    (use (match_operand 3 "" ""))
8127    (use (reg:PSI FPSCR_REG))
8128    (return)]
8129   "TARGET_SH2"
8130   "braf %1\\n%O3:%#"
8131   [(set_attr "needs_delay_slot" "yes")
8132    (set (attr "fp_mode")
8133         (if_then_else (eq_attr "fpu_single" "yes")
8134                       (const_string "single") (const_string "double")))
8135    (set_attr "type" "jump_ind")])
8136
8137 (define_insn_and_split "sibcall_value_pcrel"
8138   [(set (match_operand 0 "" "=rf")
8139         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8140               (match_operand 2 "" "")))
8141    (use (reg:PSI FPSCR_REG))
8142    (clobber (match_scratch:SI 3 "=k"))
8143    (return)]
8144   "TARGET_SH2"
8145   "#"
8146   "reload_completed"
8147   [(const_int 0)]
8148   "
8149 {
8150   rtx lab = PATTERN (gen_call_site ());
8151   rtx call_insn;
8152
8153   emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8154   call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
8155                                                         operands[3],
8156                                                         operands[2],
8157                                                         copy_rtx (lab)));
8158   SIBLING_CALL_P (call_insn) = 1;
8159   DONE;
8160 }"
8161   [(set_attr "needs_delay_slot" "yes")
8162    (set (attr "fp_mode")
8163         (if_then_else (eq_attr "fpu_single" "yes")
8164                       (const_string "single") (const_string "double")))
8165    (set_attr "type" "jump_ind")])
8166
8167 (define_insn "sibcall_value_compact"
8168   [(set (match_operand 0 "" "=rf,rf")
8169         (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
8170               (match_operand 2 "" "")))
8171    (return)
8172    (use (match_operand:SI 3 "register_operand" "z,x"))
8173    (use (reg:SI R1_REG))
8174    (use (reg:PSI FPSCR_REG))
8175    ;; We want to make sure the `x' above will only match MACH_REG
8176    ;; because sibcall_epilogue may clobber MACL_REG.
8177    (clobber (reg:SI MACL_REG))]
8178   "TARGET_SHCOMPACT"
8179   "@
8180         jmp     @%1%#
8181         jmp     @%1\\n  sts     %3, r0"
8182   [(set_attr "needs_delay_slot" "yes,no")
8183    (set_attr "length" "2,4")
8184    (set (attr "fp_mode") (const_string "single"))
8185    (set_attr "type" "jump_ind")])
8186
8187 (define_insn "sibcall_value_media"
8188   [(set (match_operand 0 "" "=rf")
8189         (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
8190               (match_operand 2 "" "")))
8191    (use (reg:SI PR_MEDIA_REG))
8192    (return)]
8193   "TARGET_SHMEDIA"
8194   "blink        %1, r63"
8195   [(set_attr "type" "jump_media")])
8196
8197 (define_expand "sibcall_value"
8198   [(parallel
8199     [(set (match_operand 0 "arith_reg_operand" "")
8200           (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8201                 (match_operand 2 "" "")))
8202      (match_operand 3 "" "")
8203      (use (reg:PSI FPSCR_REG))
8204      (return)])]
8205   ""
8206   "
8207 {
8208   if (TARGET_SHMEDIA)
8209     {
8210       operands[1] = shmedia_prepare_call_address (operands[1], 1);
8211       emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
8212                                                operands[2]));
8213       DONE;
8214     }
8215   else if (TARGET_SHCOMPACT && operands[3]
8216            && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
8217     {
8218       rtx cookie_rtx = operands[3];
8219       long cookie = INTVAL (cookie_rtx);
8220       rtx func = XEXP (operands[1], 0);
8221       rtx mach, r1;
8222
8223       if (flag_pic)
8224         {
8225           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8226             {
8227               rtx reg = gen_reg_rtx (Pmode);
8228
8229               emit_insn (gen_symGOT2reg (reg, func));
8230               func = reg;
8231             }
8232           else
8233             func = legitimize_pic_address (func, Pmode, 0);
8234         }
8235
8236       /* FIXME: if we could tell whether all argument registers are
8237          already taken, we could decide whether to force the use of
8238          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
8239          simple way to tell.  We could use the CALL_COOKIE, but we
8240          can't currently tell a register used for regular argument
8241          passing from one that is unused.  If we leave it up to reload
8242          to decide which register to use, it seems to always choose
8243          R0_REG, which leaves no available registers in SIBCALL_REGS
8244          to hold the address of the trampoline.  */
8245       mach = gen_rtx_REG (SImode, MACH_REG);
8246       r1 = gen_rtx_REG (SImode, R1_REG);
8247
8248       /* Since such a call function may use all call-clobbered
8249          registers, we force a mode switch earlier, so that we don't
8250          run out of registers when adjusting fpscr for the call.  */
8251       emit_insn (gen_force_mode_for_call ());
8252
8253       operands[1]
8254         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8255                            SFUNC_GOT);
8256       operands[1] = force_reg (SImode, operands[1]);
8257
8258       /* We don't need a return trampoline, since the callee will
8259          return directly to the upper caller.  */
8260       if (cookie & CALL_COOKIE_RET_TRAMP (1))
8261         {
8262           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8263           cookie_rtx = GEN_INT (cookie);
8264         }
8265
8266       emit_move_insn (mach, func);
8267       emit_move_insn (r1, cookie_rtx);
8268
8269       emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
8270                                                  operands[2], mach));
8271       DONE;
8272     }
8273   else if (TARGET_SHCOMPACT && flag_pic
8274            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8275            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8276     {
8277       rtx reg = gen_reg_rtx (Pmode);
8278
8279       emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
8280       XEXP (operands[1], 0) = reg;
8281     }
8282   if (flag_pic && TARGET_SH2
8283       && GET_CODE (operands[1]) == MEM
8284       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8285       /* The PLT needs the PIC register, but the epilogue would have
8286          to restore it, so we can only use PC-relative PIC calls for
8287          static functions.  */
8288       && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8289     {
8290       emit_call_insn (gen_sibcall_value_pcrel (operands[0],
8291                                                XEXP (operands[1], 0),
8292                                                operands[2]));
8293       DONE;
8294     }
8295   else
8296     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8297
8298   emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
8299   DONE;
8300 }")
8301
8302 (define_insn "call_value_pop_compact"
8303   [(set (match_operand 0 "" "=rf")
8304         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8305               (match_operand 2 "" "")))
8306    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8307                                  (match_operand 4 "immediate_operand" "n")))
8308    (match_operand 3 "immediate_operand" "n")
8309    (use (reg:SI R0_REG))
8310    (use (reg:SI R1_REG))
8311    (use (reg:PSI FPSCR_REG))
8312    (clobber (reg:SI PR_REG))]
8313   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8314   "jsr  @%1%#"
8315   [(set_attr "type" "call")
8316    (set (attr "fp_mode")
8317         (if_then_else (eq_attr "fpu_single" "yes")
8318                       (const_string "single") (const_string "double")))
8319    (set_attr "needs_delay_slot" "yes")])
8320
8321 (define_insn "call_value_pop_compact_rettramp"
8322   [(set (match_operand 0 "" "=rf")
8323         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8324               (match_operand 2 "" "")))
8325    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8326                                  (match_operand 4 "immediate_operand" "n")))
8327    (match_operand 3 "immediate_operand" "n")
8328    (use (reg:SI R0_REG))
8329    (use (reg:SI R1_REG))
8330    (use (reg:PSI FPSCR_REG))
8331    (clobber (reg:SI R10_REG))
8332    (clobber (reg:SI PR_REG))]
8333   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8334   "jsr  @%1%#"
8335   [(set_attr "type" "call")
8336    (set (attr "fp_mode")
8337         (if_then_else (eq_attr "fpu_single" "yes")
8338                       (const_string "single") (const_string "double")))
8339    (set_attr "needs_delay_slot" "yes")])
8340
8341 (define_expand "call_value_pop"
8342   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8343                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8344                                  (match_operand 2 "" "")))
8345               (match_operand 3 "" "")
8346               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8347                                             (match_operand 4 "" "")))])]
8348   "TARGET_SHCOMPACT"
8349   "
8350 {
8351   rtx cookie_rtx;
8352   long cookie;
8353   rtx func;
8354   rtx r0, r1;
8355
8356   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8357   cookie_rtx = operands[3];
8358   cookie = INTVAL (cookie_rtx);
8359   func = XEXP (operands[1], 0);
8360
8361   if (flag_pic)
8362     {
8363       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8364         {
8365           rtx reg = gen_reg_rtx (Pmode);
8366
8367           emit_insn (gen_symGOTPLT2reg (reg, func));
8368           func = reg;
8369         }
8370       else
8371         func = legitimize_pic_address (func, Pmode, 0);
8372     }
8373
8374   r0 = gen_rtx_REG (SImode, R0_REG);
8375   r1 = gen_rtx_REG (SImode, R1_REG);
8376
8377   /* Since such a call function may use all call-clobbered
8378      registers, we force a mode switch earlier, so that we don't
8379      run out of registers when adjusting fpscr for the call.  */
8380   emit_insn (gen_force_mode_for_call ());
8381
8382   operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8383                                  SFUNC_GOT);
8384   operands[1] = force_reg (SImode, operands[1]);
8385
8386   emit_move_insn (r0, func);
8387   emit_move_insn (r1, cookie_rtx);
8388
8389   if (cookie & CALL_COOKIE_RET_TRAMP (1))
8390     emit_call_insn (gen_call_value_pop_compact_rettramp
8391                         (operands[0], operands[1], operands[2],
8392                          operands[3], operands[4]));
8393   else
8394     emit_call_insn (gen_call_value_pop_compact
8395                         (operands[0], operands[1], operands[2],
8396                          operands[3], operands[4]));
8397
8398   DONE;
8399 }")
8400
8401 (define_expand "sibcall_epilogue"
8402   [(return)]
8403   ""
8404   "
8405 {
8406   sh_expand_epilogue (1);
8407   if (TARGET_SHCOMPACT)
8408     {
8409       rtx insn, set;
8410
8411       /* If epilogue clobbers r0, preserve it in macl.  */
8412       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8413         if ((set = single_set (insn))
8414             && GET_CODE (SET_DEST (set)) == REG
8415             && REGNO (SET_DEST (set)) == R0_REG)
8416           {
8417             rtx r0 = gen_rtx_REG (SImode, R0_REG);
8418             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8419
8420             /* We can't tell at this point whether the sibcall is a
8421                sibcall_compact and, if it is, whether it uses r0 or
8422                mach as operand 2, so let the instructions that
8423                preserve r0 be optimized away if r0 turns out to be
8424                dead.  */
8425             emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8426             emit_move_insn (r0, tmp);
8427             break;
8428           }
8429     }
8430   DONE;
8431 }")
8432
8433 (define_insn "indirect_jump_compact"
8434   [(set (pc)
8435         (match_operand:SI 0 "arith_reg_operand" "r"))]
8436   "TARGET_SH1"
8437   "jmp  @%0%#"
8438   [(set_attr "needs_delay_slot" "yes")
8439    (set_attr "type" "jump_ind")])
8440
8441 (define_expand "indirect_jump"
8442   [(set (pc)
8443         (match_operand 0 "register_operand" ""))]
8444   ""
8445   "
8446 {
8447   if (GET_MODE (operands[0]) != Pmode)
8448     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8449 }")
8450
8451 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8452 ;; which can be present in structured code from indirect jumps which can not
8453 ;; be present in structured code.  This allows -fprofile-arcs to work.
8454
8455 ;; For SH1 processors.
8456 (define_insn "casesi_jump_1"
8457   [(set (pc)
8458         (match_operand:SI 0 "register_operand" "r"))
8459    (use (label_ref (match_operand 1 "" "")))]
8460   "TARGET_SH1"
8461   "jmp  @%0%#"
8462   [(set_attr "needs_delay_slot" "yes")
8463    (set_attr "type" "jump_ind")])
8464
8465 ;; For all later processors.
8466 (define_insn "casesi_jump_2"
8467   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8468                       (label_ref (match_operand 1 "" ""))))
8469    (use (label_ref (match_operand 2 "" "")))]
8470   "TARGET_SH2
8471    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8472   "braf %0%#"
8473   [(set_attr "needs_delay_slot" "yes")
8474    (set_attr "type" "jump_ind")])
8475
8476 (define_insn "casesi_jump_media"
8477   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8478    (use (label_ref (match_operand 1 "" "")))]
8479   "TARGET_SHMEDIA"
8480   "blink        %0, r63"
8481   [(set_attr "type" "jump_media")])
8482
8483 ;; Call subroutine returning any type.
8484 ;; ??? This probably doesn't work.
8485
8486 (define_expand "untyped_call"
8487   [(parallel [(call (match_operand 0 "" "")
8488                     (const_int 0))
8489               (match_operand 1 "" "")
8490               (match_operand 2 "" "")])]
8491   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8492   "
8493 {
8494   int i;
8495
8496   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8497
8498   for (i = 0; i < XVECLEN (operands[2], 0); i++)
8499     {
8500       rtx set = XVECEXP (operands[2], 0, i);
8501       emit_move_insn (SET_DEST (set), SET_SRC (set));
8502     }
8503
8504   /* The optimizer does not know that the call sets the function value
8505      registers we stored in the result block.  We avoid problems by
8506      claiming that all hard registers are used and clobbered at this
8507      point.  */
8508   emit_insn (gen_blockage ());
8509
8510   DONE;
8511 }")
8512 \f
8513 ;; ------------------------------------------------------------------------
8514 ;; Misc insns
8515 ;; ------------------------------------------------------------------------
8516
8517 (define_insn "dect"
8518   [(set (reg:SI T_REG)
8519         (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1)))
8520    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
8521   "TARGET_SH2"
8522   "dt   %0"
8523   [(set_attr "type" "arith")])
8524
8525 (define_insn "nop"
8526   [(const_int 0)]
8527   ""
8528   "nop")
8529
8530 ;; Load address of a label. This is only generated by the casesi expand,
8531 ;; and by machine_dependent_reorg (fixing up fp moves).
8532 ;; This must use unspec, because this only works for labels that are
8533 ;; within range,
8534
8535 (define_insn "mova"
8536   [(set (reg:SI R0_REG)
8537         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8538   "TARGET_SH1"
8539   "mova %O0,r0"
8540   [(set_attr "in_delay_slot" "no")
8541    (set_attr "type" "arith")])
8542
8543 ;; machine_dependent_reorg will make this a `mova'.
8544 (define_insn "mova_const"
8545   [(set (reg:SI R0_REG)
8546         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8547   "TARGET_SH1"
8548   "#"
8549   [(set_attr "in_delay_slot" "no")
8550    (set_attr "type" "arith")])
8551
8552 (define_expand "GOTaddr2picreg"
8553   [(set (reg:SI R0_REG)
8554         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8555                    UNSPEC_MOVA))
8556    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8557    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8558   "" "
8559 {
8560   if (TARGET_VXWORKS_RTP)
8561     {
8562       rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
8563       rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
8564       emit_insn (gen_vxworks_picreg (gott_base, gott_index));
8565       DONE;
8566     }
8567
8568   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8569   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8570
8571   if (TARGET_SHMEDIA)
8572     {
8573       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8574       rtx pic = operands[0];
8575       rtx lab = PATTERN (gen_call_site ());
8576       rtx insn, equiv;
8577
8578       equiv = operands[1];
8579       operands[1] = gen_rtx_MINUS (Pmode,
8580                                    operands[1],
8581                                    gen_rtx_CONST
8582                                    (Pmode,
8583                                     gen_rtx_MINUS (Pmode,
8584                                                    gen_rtx_CONST (Pmode,
8585                                                                   lab),
8586                                                    pc_rtx)));
8587       operands[1] = gen_sym2PIC (operands[1]);
8588       PUT_MODE (operands[1], Pmode);
8589
8590       if (Pmode == SImode)
8591         {
8592           emit_insn (gen_movsi_const (pic, operands[1]));
8593           emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8594         }
8595       else
8596         {
8597           emit_insn (gen_movdi_const (pic, operands[1]));
8598           emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8599         }
8600
8601       insn = emit_move_insn (operands[0], tr);
8602
8603       set_unique_reg_note (insn, REG_EQUAL, equiv);
8604
8605       DONE;
8606     }
8607 }
8608 ")
8609
8610 ;; A helper for GOTaddr2picreg to finish up the initialization of the
8611 ;; PIC register.
8612
8613 (define_expand "vxworks_picreg"
8614   [(set (reg:SI PIC_REG)
8615         (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
8616    (set (reg:SI R0_REG)
8617         (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
8618    (set (reg:SI PIC_REG)
8619         (mem:SI (reg:SI PIC_REG)))
8620    (set (reg:SI PIC_REG)
8621         (mem:SI (plus:SI (reg:SI PIC_REG)
8622                          (reg:SI R0_REG))))]
8623   "TARGET_VXWORKS_RTP")
8624
8625 (define_insn "*ptb"
8626   [(set (match_operand 0 "target_reg_operand" "=b")
8627         (const (unspec [(match_operand 1 "" "Csy")]
8628                              UNSPEC_DATALABEL)))]
8629   "TARGET_SHMEDIA && flag_pic
8630    && satisfies_constraint_Csy (operands[1])"
8631   "ptb/u        datalabel %1, %0"
8632   [(set_attr "type" "ptabs_media")
8633    (set_attr "length" "*")])
8634
8635 (define_insn "ptrel_si"
8636   [(set (match_operand:SI 0 "target_reg_operand" "=b")
8637         (plus:SI (match_operand:SI 1 "register_operand" "r")
8638               (pc)))
8639    (match_operand:SI 2 "" "")]
8640   "TARGET_SHMEDIA"
8641   "%O2: ptrel/u %1, %0"
8642   [(set_attr "type" "ptabs_media")])
8643
8644 (define_insn "ptrel_di"
8645   [(set (match_operand:DI 0 "target_reg_operand" "=b")
8646         (plus:DI (match_operand:DI 1 "register_operand" "r")
8647               (pc)))
8648    (match_operand:DI 2 "" "")]
8649   "TARGET_SHMEDIA"
8650   "%O2: ptrel/u %1, %0"
8651   [(set_attr "type" "ptabs_media")])
8652
8653 (define_expand "builtin_setjmp_receiver"
8654   [(match_operand 0 "" "")]
8655   "flag_pic"
8656   "
8657 {
8658   emit_insn (gen_GOTaddr2picreg ());
8659   DONE;
8660 }")
8661
8662 (define_expand "call_site"
8663   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8664   "TARGET_SH1"
8665   "
8666 {
8667   static HOST_WIDE_INT i = 0;
8668   operands[0] = GEN_INT (i);
8669   i++;
8670 }")
8671
8672 (define_expand "sym_label2reg"
8673   [(set (match_operand:SI 0 "" "")
8674         (const:SI (minus:SI
8675                    (const:SI
8676                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
8677                    (const:SI
8678                     (plus:SI
8679                      (match_operand:SI 2 "" "")
8680                      (const_int 2))))))]
8681   "TARGET_SH1" "")
8682
8683 (define_expand "symGOT_load"
8684   [(set (match_dup 2) (match_operand 1 "" ""))
8685    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8686    (set (match_operand 0 "" "") (mem (match_dup 3)))]
8687   ""
8688   "
8689 {
8690   rtx insn, mem;
8691
8692   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8693   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8694
8695   if (TARGET_SHMEDIA)
8696     {
8697       rtx reg = operands[2];
8698
8699       if (Pmode == DImode)
8700         {      
8701           if (flag_pic > 1)
8702             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8703           else
8704             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8705         }
8706       else
8707         {
8708           if (flag_pic > 1)
8709             emit_insn (gen_movsi_const (reg, operands[1]));
8710           else
8711             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8712         }
8713     }
8714   else
8715     emit_move_insn (operands[2], operands[1]);
8716
8717   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
8718                                              operands[2],
8719                                              gen_rtx_REG (Pmode, PIC_REG)));
8720
8721   /* When stack protector inserts codes after the result is set to
8722      R0, @(rX, r12) will cause a spill failure for R0.  Don't schedule
8723      insns to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8724      when rX is a GOT address for the guard symbol.  Ugly but doesn't
8725      matter because this is a rare situation.  */
8726   if (!TARGET_SHMEDIA
8727       && flag_stack_protect
8728       && GET_CODE (operands[1]) == CONST
8729       && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8730       && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8731       && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8732                  \"__stack_chk_guard\") == 0)
8733     emit_insn (gen_blockage ());
8734
8735   /* N.B. This is not constant for a GOTPLT relocation.  */
8736   mem = gen_rtx_MEM (Pmode, operands[3]);
8737   MEM_NOTRAP_P (mem) = 1;
8738   /* ??? Should we have a special alias set for the GOT?  */
8739   insn = emit_move_insn (operands[0], mem);
8740
8741   set_unique_reg_note (insn, REG_EQUAL,
8742                        XVECEXP (XEXP (operands[1], 0), 0, 0));
8743
8744   DONE;
8745 }")
8746
8747 (define_expand "sym2GOT"
8748   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8749   ""
8750   "")
8751
8752 (define_expand "symGOT2reg"
8753   [(match_operand 0 "" "") (match_operand 1 "" "")]
8754   ""
8755   "
8756 {
8757   rtx gotsym, insn;
8758
8759   gotsym = gen_sym2GOT (operands[1]);
8760   PUT_MODE (gotsym, Pmode);
8761   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8762
8763   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8764
8765   DONE;
8766 }")
8767
8768 (define_expand "symGOTPLT2reg"
8769   [(match_operand 0 "" "") (match_operand 1 "" "")]
8770   ""
8771   "
8772 {
8773   rtx pltsym = gen_rtx_CONST (Pmode,
8774                               gen_rtx_UNSPEC (Pmode,
8775                                               gen_rtvec (1, operands[1]),
8776                                               UNSPEC_GOTPLT));
8777   emit_insn (gen_symGOT_load (operands[0], pltsym));
8778   DONE;
8779 }")
8780
8781 (define_expand "sym2GOTOFF"
8782   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8783   ""
8784   "")
8785
8786 (define_expand "symGOTOFF2reg"
8787   [(match_operand 0 "" "") (match_operand 1 "" "")]
8788   ""
8789   "
8790 {
8791   rtx gotoffsym, insn;
8792   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8793
8794   gotoffsym = gen_sym2GOTOFF (operands[1]);
8795   PUT_MODE (gotoffsym, Pmode);
8796   emit_move_insn (t, gotoffsym);
8797   insn = emit_move_insn (operands[0],
8798                          gen_rtx_PLUS (Pmode, t,
8799                                        gen_rtx_REG (Pmode, PIC_REG)));
8800
8801   set_unique_reg_note (insn, REG_EQUAL, operands[1]);
8802
8803   DONE;
8804 }")
8805
8806 (define_expand "symPLT_label2reg"
8807   [(set (match_operand:SI 0 "" "")
8808         (const:SI (minus:SI
8809                    (const:SI
8810                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8811                    (const:SI
8812                     (minus:SI
8813                      (const:SI (plus:SI
8814                                 (match_operand:SI 2 "" "")
8815                                 (const_int 2)))
8816                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
8817    ;; Even though the PIC register is not really used by the call
8818    ;; sequence in which this is expanded, the PLT code assumes the PIC
8819    ;; register is set, so we must not skip its initialization.  Since
8820    ;; we only use this expand as part of calling sequences, and never
8821    ;; to take the address of a function, this is the best point to
8822    ;; insert the (use).  Using the PLT to take the address of a
8823    ;; function would be wrong, not only because the PLT entry could
8824    ;; then be called from a function that doesn't initialize the PIC
8825    ;; register to the proper GOT, but also because pointers to the
8826    ;; same function might not compare equal, should they be set by
8827    ;; different shared libraries.
8828    (use (reg:SI PIC_REG))]
8829   "TARGET_SH1"
8830   "")
8831
8832 (define_expand "sym2PIC"
8833   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8834   ""
8835   "")
8836
8837 ;; TLS code generation.
8838 ;; ??? this should be a define_insn_and_split
8839 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8840 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8841 ;; for details.
8842
8843 (define_insn "tls_global_dynamic"
8844   [(set (match_operand:SI 0 "register_operand" "=&z")
8845         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8846                                   UNSPEC_TLSGD))
8847               (const_int 0)))
8848    (use (reg:PSI FPSCR_REG))
8849    (use (reg:SI PIC_REG))
8850    (clobber (reg:SI PR_REG))
8851    (clobber (scratch:SI))]
8852   "TARGET_SH1"
8853   "*
8854 {
8855   return \"\\
8856 mov.l\\t1f,r4\\n\\
8857 \\tmova\\t2f,r0\\n\\
8858 \\tmov.l\\t2f,r1\\n\\
8859 \\tadd\\tr0,r1\\n\\
8860 \\tjsr\\t@r1\\n\\
8861 \\tadd\\tr12,r4\\n\\
8862 \\tbra\\t3f\\n\\
8863 \\tnop\\n\\
8864 \\t.align\\t2\\n\\
8865 1:\\t.long\\t%a1@TLSGD\\n\\
8866 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8867 3:\";
8868 }"
8869   [(set_attr "type" "tls_load")
8870    (set_attr "length" "26")])
8871
8872 (define_insn "tls_local_dynamic"
8873   [(set (match_operand:SI 0 "register_operand" "=&z")
8874         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8875                                   UNSPEC_TLSLDM))
8876               (const_int 0)))
8877    (use (reg:PSI FPSCR_REG))
8878    (use (reg:SI PIC_REG))
8879    (clobber (reg:SI PR_REG))
8880    (clobber (scratch:SI))]
8881   "TARGET_SH1"
8882   "*
8883 {
8884   return \"\\
8885 mov.l\\t1f,r4\\n\\
8886 \\tmova\\t2f,r0\\n\\
8887 \\tmov.l\\t2f,r1\\n\\
8888 \\tadd\\tr0,r1\\n\\
8889 \\tjsr\\t@r1\\n\\
8890 \\tadd\\tr12,r4\\n\\
8891 \\tbra\\t3f\\n\\
8892 \\tnop\\n\\
8893 \\t.align\\t2\\n\\
8894 1:\\t.long\\t%a1@TLSLDM\\n\\
8895 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8896 3:\";
8897 }"
8898   [(set_attr "type" "tls_load")
8899    (set_attr "length" "26")])
8900
8901 (define_expand "sym2DTPOFF"
8902   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8903   ""
8904   "")
8905
8906 (define_expand "symDTPOFF2reg"
8907   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8908   ""
8909   "
8910 {
8911   rtx dtpoffsym, insn;
8912   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8913
8914   dtpoffsym = gen_sym2DTPOFF (operands[1]);
8915   PUT_MODE (dtpoffsym, Pmode);
8916   emit_move_insn (t, dtpoffsym);
8917   insn = emit_move_insn (operands[0],
8918                          gen_rtx_PLUS (Pmode, t, operands[2]));
8919   DONE;
8920 }")
8921
8922 (define_expand "sym2GOTTPOFF"
8923   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8924   ""
8925   "")
8926
8927 (define_insn "tls_initial_exec"
8928   [(set (match_operand:SI 0 "register_operand" "=&r")
8929         (unspec:SI [(match_operand:SI 1 "" "")]
8930                     UNSPEC_TLSIE))
8931    (use (reg:SI GBR_REG))
8932    (use (reg:SI PIC_REG))
8933    (clobber (reg:SI R0_REG))]
8934   ""
8935   "*
8936 {
8937   return \"\\
8938 mov.l\\t1f,r0\\n\\
8939 \\tstc\\tgbr,%0\\n\\
8940 \\tmov.l\\t@(r0,r12),r0\\n\\
8941 \\tbra\\t2f\\n\\
8942 \\tadd\\tr0,%0\\n\\
8943 \\t.align\\t2\\n\\
8944 1:\\t.long\\t%a1\\n\\
8945 2:\";
8946 }"
8947   [(set_attr "type" "tls_load")
8948    (set_attr "length" "16")])
8949
8950 (define_expand "sym2TPOFF"
8951   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8952   ""
8953   "")
8954
8955 (define_expand "symTPOFF2reg"
8956   [(match_operand 0 "" "") (match_operand 1 "" "")]
8957   ""
8958   "
8959 {
8960   rtx tpoffsym, insn;
8961
8962   tpoffsym = gen_sym2TPOFF (operands[1]);
8963   PUT_MODE (tpoffsym, Pmode);
8964   insn = emit_move_insn (operands[0], tpoffsym);
8965   DONE;
8966 }")
8967
8968 (define_insn "load_gbr"
8969   [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
8970    (use (reg:SI GBR_REG))]
8971   ""
8972   "stc  gbr,%0"
8973   [(set_attr "type" "tls_load")])
8974
8975 ;; case instruction for switch statements.
8976
8977 ;; Operand 0 is index
8978 ;; operand 1 is the minimum bound
8979 ;; operand 2 is the maximum bound - minimum bound + 1
8980 ;; operand 3 is CODE_LABEL for the table;
8981 ;; operand 4 is the CODE_LABEL to go to if index out of range.
8982
8983 (define_expand "casesi"
8984   [(match_operand:SI 0 "arith_reg_operand" "")
8985    (match_operand:SI 1 "arith_reg_operand" "")
8986    (match_operand:SI 2 "arith_reg_operand" "")
8987    (match_operand 3 "" "") (match_operand 4 "" "")]
8988   ""
8989   "
8990 {
8991   rtx reg = gen_reg_rtx (SImode);
8992   rtx reg2 = gen_reg_rtx (SImode);
8993   if (TARGET_SHMEDIA)
8994     {
8995       rtx reg = gen_reg_rtx (DImode);
8996       rtx reg2 = gen_reg_rtx (DImode);
8997       rtx reg3 = gen_reg_rtx (Pmode);
8998       rtx reg4 = gen_reg_rtx (Pmode);
8999       rtx reg5 = gen_reg_rtx (Pmode);
9000       rtx load;
9001
9002       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
9003       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
9004       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
9005
9006       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
9007       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
9008       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
9009       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
9010       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
9011                                                (Pmode, operands[3])));
9012       /* Messy: can we subreg to clean this up? */
9013       if (Pmode == DImode)
9014         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
9015       else
9016         load = gen_casesi_load_media (reg4,
9017                                       gen_rtx_SUBREG (DImode, reg3, 0),
9018                                       reg2, operands[3]);
9019       PUT_MODE (SET_SRC (load), Pmode);
9020       emit_insn (load);
9021       /* ??? The following add could be eliminated if we used ptrel.  */
9022       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
9023       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
9024       emit_barrier ();
9025       DONE;
9026     }
9027   operands[1] = copy_to_mode_reg (SImode, operands[1]);
9028   operands[2] = copy_to_mode_reg (SImode, operands[2]);
9029   /* If optimizing, casesi_worker depends on the mode of the instruction
9030      before label it 'uses' - operands[3].  */
9031   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
9032                            reg));
9033   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
9034   if (TARGET_SH2)
9035     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
9036   else
9037     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
9038   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
9039      operands[3], but to lab.  We will fix this up in
9040      machine_dependent_reorg.  */
9041   emit_barrier ();
9042   DONE;
9043 }")
9044
9045 (define_expand "casesi_0"
9046   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
9047    (set (match_dup 4) (minus:SI (match_dup 4)
9048                                 (match_operand:SI 1 "arith_operand" "")))
9049    (set (reg:SI T_REG)
9050         (gtu:SI (match_dup 4)
9051                 (match_operand:SI 2 "arith_reg_operand" "")))
9052    (set (pc)
9053         (if_then_else (ne (reg:SI T_REG)
9054                           (const_int 0))
9055                       (label_ref (match_operand 3 "" ""))
9056                       (pc)))]
9057   "TARGET_SH1"
9058   "")
9059
9060 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
9061 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
9062 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
9063
9064 (define_insn "casesi_worker_0"
9065   [(set (match_operand:SI 0 "register_operand" "=r,r")
9066         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
9067                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9068    (clobber (match_scratch:SI 3 "=X,1"))
9069    (clobber (match_scratch:SI 4 "=&z,z"))]
9070   "TARGET_SH1"
9071   "#")
9072
9073 (define_split
9074   [(set (match_operand:SI 0 "register_operand" "")
9075         (unspec:SI [(match_operand:SI 1 "register_operand" "")
9076                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9077    (clobber (match_scratch:SI 3 ""))
9078    (clobber (match_scratch:SI 4 ""))]
9079   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
9080   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9081    (parallel [(set (match_dup 0)
9082               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9083                           (label_ref (match_dup 2))] UNSPEC_CASESI))
9084               (clobber (match_dup 3))])
9085    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9086   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
9087
9088 (define_split
9089   [(set (match_operand:SI 0 "register_operand" "")
9090         (unspec:SI [(match_operand:SI 1 "register_operand" "")
9091                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9092    (clobber (match_scratch:SI 3 ""))
9093    (clobber (match_scratch:SI 4 ""))]
9094   "TARGET_SH2 && reload_completed"
9095   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
9096    (parallel [(set (match_dup 0)
9097               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
9098                           (label_ref (match_dup 2))] UNSPEC_CASESI))
9099               (clobber (match_dup 3))])]
9100   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
9101
9102 (define_insn "casesi_worker_1"
9103   [(set (match_operand:SI 0 "register_operand" "=r,r")
9104         (unspec:SI [(reg:SI R0_REG)
9105                     (match_operand:SI 1 "register_operand" "0,r")
9106                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
9107    (clobber (match_scratch:SI 3 "=X,1"))]
9108   "TARGET_SH1"
9109   "*
9110 {
9111   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9112
9113   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9114
9115   switch (GET_MODE (diff_vec))
9116     {
9117     case SImode:
9118       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
9119     case HImode:
9120       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
9121     case QImode:
9122       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9123         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
9124       return \"mov.b    @(r0,%1),%0\";
9125     default:
9126       gcc_unreachable ();
9127     }
9128 }"
9129   [(set_attr "length" "4")])
9130
9131 (define_insn "casesi_worker_2"
9132   [(set (match_operand:SI 0 "register_operand" "=r,r")
9133         (unspec:SI [(reg:SI R0_REG)
9134                     (match_operand:SI 1 "register_operand" "0,r")
9135                     (label_ref (match_operand 2 "" ""))
9136                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
9137    (clobber (match_operand:SI 4 "" "=X,1"))]
9138   "TARGET_SH2 && reload_completed && flag_pic"
9139   "*
9140 {
9141   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9142   const char *load;
9143
9144   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9145
9146   switch (GET_MODE (diff_vec))
9147     {
9148     case SImode:
9149       output_asm_insn (\"shll2    %1\", operands);
9150       load = \"mov.l    @(r0,%1),%0\"; break;
9151     case HImode:
9152       output_asm_insn (\"add    %1,%1\", operands);
9153       load = \"mov.w    @(r0,%1),%0\"; break;
9154     case QImode:
9155       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9156         load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
9157       else
9158         load = \"mov.b  @(r0,%1),%0\";
9159       break;
9160     default:
9161       gcc_unreachable ();
9162     }
9163   output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
9164   return load;
9165 }"
9166   [(set_attr "length" "8")])
9167
9168 (define_insn "casesi_shift_media"
9169   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9170         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
9171                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
9172                     UNSPEC_CASESI)))]
9173   "TARGET_SHMEDIA"
9174   "*
9175 {
9176   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
9177
9178   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9179
9180   switch (GET_MODE (diff_vec))
9181     {
9182     case SImode:
9183       return \"shlli    %1, 2, %0\";
9184     case HImode:
9185       return \"shlli    %1, 1, %0\";
9186     case QImode:
9187       if (rtx_equal_p (operands[0], operands[1]))
9188         return \"\";
9189       return \"add      %1, r63, %0\";
9190     default:
9191       gcc_unreachable ();
9192     }
9193 }"
9194   [(set_attr "type" "arith_media")])
9195
9196 (define_insn "casesi_load_media"
9197   [(set (match_operand 0 "any_arith_reg_dest" "=r")
9198         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
9199                          (match_operand:DI 2 "arith_reg_operand" "r")
9200                          (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
9201   "TARGET_SHMEDIA"
9202   "*
9203 {
9204   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
9205
9206   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
9207
9208   switch (GET_MODE (diff_vec))
9209     {
9210     case SImode:
9211       return \"ldx.l    %1, %2, %0\";
9212     case HImode:
9213 #if 0
9214       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9215         return \"ldx.uw %1, %2, %0\";
9216 #endif
9217       return \"ldx.w    %1, %2, %0\";
9218     case QImode:
9219       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9220         return \"ldx.ub %1, %2, %0\";
9221       return \"ldx.b    %1, %2, %0\";
9222     default:
9223       gcc_unreachable ();
9224     }
9225 }"
9226   [(set_attr "type" "load_media")])
9227
9228 (define_expand "return"
9229   [(return)]
9230   "reload_completed && ! sh_need_epilogue ()"
9231   "
9232 {
9233   if (TARGET_SHMEDIA)
9234     {
9235       emit_jump_insn (gen_return_media ());
9236       DONE;
9237     }
9238
9239   if (TARGET_SHCOMPACT
9240       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
9241     {
9242       emit_jump_insn (gen_shcompact_return_tramp ());
9243       DONE;
9244     }
9245 }")
9246
9247 (define_insn "*return_i"
9248   [(return)]
9249   "TARGET_SH1 && ! (TARGET_SHCOMPACT
9250                     && (current_function_args_info.call_cookie
9251                         & CALL_COOKIE_RET_TRAMP (1)))
9252    && reload_completed
9253    && lookup_attribute (\"trap_exit\",
9254                         DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
9255   "%@   %#"
9256   [(set_attr "type" "return")
9257    (set_attr "needs_delay_slot" "yes")])
9258
9259 ;; trapa has no delay slot.
9260 (define_insn "*return_trapa"
9261   [(return)]
9262   "TARGET_SH1 && !TARGET_SHCOMPACT
9263    && reload_completed"
9264   "%@"
9265   [(set_attr "type" "return")])
9266
9267 (define_expand "shcompact_return_tramp"
9268   [(return)]
9269   "TARGET_SHCOMPACT
9270    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9271   "
9272 {
9273   rtx reg = gen_rtx_REG (Pmode, R0_REG);
9274
9275   function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
9276   emit_jump_insn (gen_shcompact_return_tramp_i ());
9277   DONE;
9278 }")
9279
9280 (define_insn "shcompact_return_tramp_i"
9281   [(parallel [(return) (use (reg:SI R0_REG))])]
9282   "TARGET_SHCOMPACT
9283    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9284   "jmp  @r0%#"
9285   [(set_attr "type" "jump_ind")
9286    (set_attr "needs_delay_slot" "yes")])
9287
9288 (define_insn "return_media_i"
9289   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
9290   "TARGET_SHMEDIA && reload_completed"
9291   "blink        %0, r63"
9292   [(set_attr "type" "jump_media")])
9293
9294 (define_insn "return_media_rte"
9295   [(return)]
9296   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
9297   "rte"
9298   [(set_attr "type" "jump_media")])
9299
9300 (define_expand "return_media"
9301   [(return)]
9302   "TARGET_SHMEDIA && reload_completed"
9303   "
9304 {
9305   int tr_regno = sh_media_register_for_return ();
9306   rtx tr;
9307
9308   if (current_function_interrupt)
9309     {
9310       emit_jump_insn (gen_return_media_rte ());
9311       DONE;
9312     }
9313   if (tr_regno < 0)
9314     {
9315       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9316
9317       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9318       tr_regno = TR0_REG;
9319       tr = gen_rtx_REG (Pmode, tr_regno);
9320       emit_move_insn (tr, r18);
9321     }
9322   else
9323     tr = gen_rtx_REG (Pmode, tr_regno);
9324
9325   emit_jump_insn (gen_return_media_i (tr));
9326   DONE;
9327 }")
9328
9329 (define_insn "shcompact_preserve_incoming_args"
9330   [(set (match_operand:SI 0 "register_operand" "+r")
9331         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9332   "TARGET_SHCOMPACT"
9333   ""
9334   [(set_attr "length" "0")])
9335
9336 (define_insn "shcompact_incoming_args"
9337   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9338    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9339    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9340    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9341    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9342    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9343    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9344    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9345    (set (mem:BLK (reg:SI MACL_REG))
9346         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9347    (use (reg:SI R0_REG))
9348    (clobber (reg:SI R0_REG))
9349    (clobber (reg:SI MACL_REG))
9350    (clobber (reg:SI MACH_REG))
9351    (clobber (reg:SI PR_REG))]
9352   "TARGET_SHCOMPACT"
9353   "jsr  @r0%#"
9354   [(set_attr "needs_delay_slot" "yes")])
9355
9356 (define_insn "shmedia_save_restore_regs_compact"
9357   [(set (reg:SI SP_REG)
9358         (plus:SI (reg:SI SP_REG)
9359                  (match_operand:SI 0 "immediate_operand" "i")))
9360    (use (reg:SI R0_REG))
9361    (clobber (reg:SI PR_REG))]
9362   "TARGET_SHCOMPACT
9363    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9364        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9365   "jsr @r0%#"
9366   [(set_attr "needs_delay_slot" "yes")])
9367
9368 (define_expand "prologue"
9369   [(const_int 0)]
9370   ""
9371   "sh_expand_prologue (); DONE;")
9372
9373 (define_expand "epilogue"
9374   [(return)]
9375   ""
9376   "
9377 {
9378   sh_expand_epilogue (0);
9379   emit_jump_insn (gen_return ());
9380   DONE;
9381 }")
9382
9383 (define_expand "eh_return"
9384   [(use (match_operand 0 "register_operand" ""))]
9385   ""
9386 {
9387   rtx ra = operands[0];
9388
9389   if (TARGET_SHMEDIA64)
9390     emit_insn (gen_eh_set_ra_di (ra));
9391   else
9392     emit_insn (gen_eh_set_ra_si (ra));
9393
9394   DONE;
9395 })
9396
9397 ;; Clobber the return address on the stack.  We can't expand this
9398 ;; until we know where it will be put in the stack frame.
9399
9400 (define_insn "eh_set_ra_si"
9401   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
9402       UNSPECV_EH_RETURN)
9403    (clobber (match_scratch:SI 1 "=&r"))]
9404   "! TARGET_SHMEDIA64"
9405   "#")
9406
9407 (define_insn "eh_set_ra_di"
9408   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
9409       UNSPECV_EH_RETURN)
9410    (clobber (match_scratch:DI 1 "=&r"))]
9411   "TARGET_SHMEDIA64"
9412   "#")
9413
9414 (define_split
9415   [(unspec_volatile [(match_operand 0 "register_operand" "")]
9416       UNSPECV_EH_RETURN)
9417    (clobber (match_scratch 1 ""))]
9418   "reload_completed"
9419   [(const_int 0)]
9420   "
9421 {
9422   sh_set_return_address (operands[0], operands[1]);
9423   DONE;
9424 }")
9425
9426 (define_insn "blockage"
9427   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9428   ""
9429   ""
9430   [(set_attr "length" "0")])
9431 \f
9432 ;; ------------------------------------------------------------------------
9433 ;; Scc instructions
9434 ;; ------------------------------------------------------------------------
9435
9436 (define_insn "movt"
9437   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9438         (eq:SI (reg:SI T_REG) (const_int 1)))]
9439   "TARGET_SH1"
9440   "movt %0"
9441   [(set_attr "type" "arith")])
9442
9443 (define_expand "seq"
9444   [(set (match_operand:SI 0 "arith_reg_dest" "")
9445         (match_dup 1))]
9446   ""
9447   "
9448 {
9449   if (TARGET_SHMEDIA)
9450     {
9451       rtx reg;
9452
9453       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9454       if (sh_compare_op1 != const0_rtx)
9455         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9456                                     ? GET_MODE (sh_compare_op0)
9457                                     : GET_MODE (sh_compare_op1),
9458                                     sh_compare_op1);
9459       if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4)
9460         {
9461           if (GET_MODE (operands[0]) != SImode)
9462             operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
9463
9464           switch (GET_MODE (sh_compare_op0))
9465             {
9466             case SImode:
9467               emit_insn (gen_cmpeqsi_media (operands[0],
9468                                               sh_compare_op0, sh_compare_op1));
9469               break;
9470
9471             case DImode:
9472               emit_insn (gen_cmpeqdi_media (operands[0],
9473                                               sh_compare_op0, sh_compare_op1));
9474               break;
9475
9476             case SFmode:
9477               if (! TARGET_SHMEDIA_FPU)
9478                 FAIL;
9479               emit_insn (gen_cmpeqsf_media (operands[0],
9480                                               sh_compare_op0, sh_compare_op1));
9481               break;
9482
9483             case DFmode:
9484               if (! TARGET_SHMEDIA_FPU)
9485                 FAIL;
9486               emit_insn (gen_cmpeqdf_media (operands[0],
9487                                               sh_compare_op0, sh_compare_op1));
9488               break;
9489
9490             default:
9491               FAIL;
9492             }
9493           DONE;
9494         }
9495
9496       reg = operands[0];
9497       if (GET_MODE (operands[0]) != SImode)
9498         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9499                              : gen_reg_rtx (SImode);
9500
9501       switch (GET_MODE (sh_compare_op0))
9502         {
9503         case SImode:
9504           emit_insn (gen_cmpeqsi_media (reg,
9505                                         sh_compare_op0, sh_compare_op1));
9506           break;
9507
9508         case DImode:
9509           emit_insn (gen_cmpeqdi_media (reg,
9510                                         sh_compare_op0, sh_compare_op1));
9511           break;
9512
9513         case SFmode:
9514           if (! TARGET_SHMEDIA_FPU)
9515             FAIL;
9516           emit_insn (gen_cmpeqsf_media (reg,
9517                                         sh_compare_op0, sh_compare_op1));
9518           break;
9519
9520         case DFmode:
9521           if (! TARGET_SHMEDIA_FPU)
9522             FAIL;
9523           emit_insn (gen_cmpeqdf_media (reg,
9524                                         sh_compare_op0, sh_compare_op1));
9525           break;
9526
9527         default:
9528           FAIL;
9529         }
9530
9531       if (GET_MODE (operands[0]) == DImode)
9532         emit_insn (gen_extendsidi2 (operands[0], reg));
9533
9534       DONE;
9535     }
9536   if (sh_expand_t_scc (EQ, operands[0]))
9537     DONE;
9538   if (! currently_expanding_to_rtl)
9539     FAIL;
9540   operands[1] = prepare_scc_operands (EQ);
9541 }")
9542
9543 (define_expand "slt"
9544   [(set (match_operand:SI 0 "arith_reg_operand" "")
9545         (match_dup 1))]
9546   ""
9547   "
9548 {
9549   if (TARGET_SHMEDIA)
9550     {
9551       rtx reg;
9552
9553       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9554       if (sh_compare_op1 != const0_rtx)
9555         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9556                                     ? GET_MODE (sh_compare_op0)
9557                                     : GET_MODE (sh_compare_op1),
9558                                     sh_compare_op1);
9559
9560       reg = operands[0];
9561       if (GET_MODE (operands[0]) != SImode)
9562         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9563                              : gen_reg_rtx (SImode);
9564
9565       switch (GET_MODE (sh_compare_op0))
9566         {
9567         case SImode:
9568           emit_insn (gen_cmpgtsi_media (reg,
9569                                         sh_compare_op1, sh_compare_op0));
9570           break;
9571
9572         case DImode:
9573           emit_insn (gen_cmpgtdi_media (reg,
9574                                         sh_compare_op1, sh_compare_op0));
9575           break;
9576
9577         case SFmode:
9578           if (! TARGET_SHMEDIA_FPU)
9579             FAIL;
9580           emit_insn (gen_cmpgtsf_media (reg,
9581                                         sh_compare_op1, sh_compare_op0));
9582           break;
9583
9584         case DFmode:
9585           if (! TARGET_SHMEDIA_FPU)
9586             FAIL;
9587           emit_insn (gen_cmpgtdf_media (reg,
9588                                         sh_compare_op1, sh_compare_op0));
9589           break;
9590
9591         default:
9592           FAIL;
9593         }
9594
9595       if (GET_MODE (operands[0]) == DImode)
9596         emit_insn (gen_extendsidi2 (operands[0], reg));
9597
9598       DONE;
9599     }
9600   if (! currently_expanding_to_rtl)
9601     FAIL;
9602   operands[1] = prepare_scc_operands (LT);
9603 }")
9604
9605 (define_expand "sle"
9606   [(match_operand:SI 0 "arith_reg_operand" "")]
9607   ""
9608   "
9609 {
9610   rtx tmp = sh_compare_op0;
9611
9612   if (TARGET_SHMEDIA)
9613     {
9614       rtx reg;
9615
9616       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9617       if (sh_compare_op1 != const0_rtx)
9618         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9619                                     ? GET_MODE (sh_compare_op0)
9620                                     : GET_MODE (sh_compare_op1),
9621                                     sh_compare_op1);
9622
9623       reg = operands[0];
9624       if (GET_MODE (operands[0]) != SImode)
9625         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9626                              : gen_reg_rtx (SImode);
9627
9628       switch (GET_MODE (sh_compare_op0))
9629         {
9630         case SImode:
9631           {
9632             tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9633
9634             emit_insn (gen_cmpgtsi_media (tmp,
9635                                           sh_compare_op0, sh_compare_op1));
9636             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9637             break;
9638           }
9639
9640         case DImode:
9641           {
9642             tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9643
9644             emit_insn (gen_cmpgtdi_media (tmp,
9645                                           sh_compare_op0, sh_compare_op1));
9646             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9647             break;
9648           }
9649
9650         case SFmode:
9651           if (! TARGET_SHMEDIA_FPU)
9652             FAIL;
9653           emit_insn (gen_cmpgesf_media (reg,
9654                                         sh_compare_op1, sh_compare_op0));
9655           break;
9656
9657         case DFmode:
9658           if (! TARGET_SHMEDIA_FPU)
9659             FAIL;
9660           emit_insn (gen_cmpgedf_media (reg,
9661                                         sh_compare_op1, sh_compare_op0));
9662           break;
9663
9664         default:
9665           FAIL;
9666         }
9667
9668       if (GET_MODE (operands[0]) == DImode)
9669         emit_insn (gen_extendsidi2 (operands[0], reg));
9670
9671       DONE;
9672     }
9673
9674   sh_compare_op0 = sh_compare_op1;
9675   sh_compare_op1 = tmp;
9676   emit_insn (gen_sge (operands[0]));
9677   DONE;
9678 }")
9679
9680 (define_expand "sgt"
9681   [(set (match_operand:SI 0 "arith_reg_operand" "")
9682         (match_dup 1))]
9683   ""
9684   "
9685 {
9686   if (TARGET_SHMEDIA)
9687     {
9688       rtx reg;
9689
9690       reg = operands[0];
9691       if (GET_MODE (operands[0]) != SImode)
9692         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9693                              : gen_reg_rtx (SImode);
9694       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9695       if (sh_compare_op1 != const0_rtx)
9696         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9697                                     ? GET_MODE (sh_compare_op0)
9698                                     : GET_MODE (sh_compare_op1),
9699                                     sh_compare_op1);
9700
9701       switch (GET_MODE (sh_compare_op0))
9702         {
9703         case SImode:
9704           emit_insn (gen_cmpgtsi_media (reg,
9705                                         sh_compare_op0, sh_compare_op1));
9706           break;
9707
9708         case DImode:
9709           emit_insn (gen_cmpgtdi_media (reg,
9710                                         sh_compare_op0, sh_compare_op1));
9711           break;
9712
9713         case SFmode:
9714           if (! TARGET_SHMEDIA_FPU)
9715             FAIL;
9716           emit_insn (gen_cmpgtsf_media (reg,
9717                                         sh_compare_op0, sh_compare_op1));
9718           break;
9719
9720         case DFmode:
9721           if (! TARGET_SHMEDIA_FPU)
9722             FAIL;
9723           emit_insn (gen_cmpgtdf_media (reg,
9724                                         sh_compare_op0, sh_compare_op1));
9725           break;
9726
9727         default:
9728           FAIL;
9729         }
9730
9731       if (GET_MODE (operands[0]) == DImode)
9732         emit_insn (gen_extendsidi2 (operands[0], reg));
9733
9734       DONE;
9735     }
9736   if (! currently_expanding_to_rtl)
9737     FAIL;
9738   operands[1] = prepare_scc_operands (GT);
9739 }")
9740
9741 (define_expand "sge"
9742   [(set (match_operand:SI 0 "arith_reg_operand" "")
9743         (match_dup 1))]
9744   ""
9745   "
9746 {
9747   if (TARGET_SHMEDIA)
9748     {
9749       rtx reg;
9750       enum machine_mode mode = GET_MODE (sh_compare_op0);
9751
9752       if ((mode) == VOIDmode)
9753         mode = GET_MODE (sh_compare_op1);
9754       reg = operands[0];
9755       if (GET_MODE (operands[0]) != SImode)
9756         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9757                              : gen_reg_rtx (SImode);
9758       sh_compare_op0 = force_reg (mode, sh_compare_op0);
9759       if (sh_compare_op1 != const0_rtx)
9760         sh_compare_op1 = force_reg (mode, sh_compare_op1);
9761
9762       switch (mode)
9763         {
9764         case SImode:
9765           {
9766             rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9767
9768             emit_insn (gen_cmpgtsi_media (tmp,
9769                                           sh_compare_op1, sh_compare_op0));
9770             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9771             break;
9772           }
9773
9774         case DImode:
9775           {
9776             rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9777
9778             emit_insn (gen_cmpgtdi_media (tmp,
9779                                           sh_compare_op1, sh_compare_op0));
9780             emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9781             break;
9782           }
9783
9784         case SFmode:
9785           if (! TARGET_SHMEDIA_FPU)
9786             FAIL;
9787           emit_insn (gen_cmpgesf_media (reg,
9788                                         sh_compare_op0, sh_compare_op1));
9789           break;
9790
9791         case DFmode:
9792           if (! TARGET_SHMEDIA_FPU)
9793             FAIL;
9794           emit_insn (gen_cmpgedf_media (reg,
9795                                         sh_compare_op0, sh_compare_op1));
9796           break;
9797
9798         default:
9799           FAIL;
9800         }
9801
9802       if (GET_MODE (operands[0]) == DImode)
9803         emit_insn (gen_extendsidi2 (operands[0], reg));
9804
9805       DONE;
9806     }
9807
9808   if (! currently_expanding_to_rtl)
9809     FAIL;
9810   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
9811     {
9812       if (TARGET_IEEE)
9813         {
9814           rtx lab = gen_label_rtx ();
9815           prepare_scc_operands (EQ);
9816           emit_jump_insn (gen_branch_true (lab));
9817           prepare_scc_operands (GT);
9818           emit_label (lab);
9819           emit_insn (gen_movt (operands[0]));
9820         }
9821       else
9822         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
9823       DONE;
9824     }
9825   operands[1] = prepare_scc_operands (GE);
9826 }")
9827
9828 (define_expand "sgtu"
9829   [(set (match_operand:SI 0 "arith_reg_operand" "")
9830         (match_dup 1))]
9831   ""
9832   "
9833 {
9834   if (TARGET_SHMEDIA)
9835     {
9836       rtx reg;
9837
9838       reg = operands[0];
9839       if (GET_MODE (operands[0]) == DImode)
9840         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9841                              : gen_reg_rtx (SImode);
9842       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9843       if (sh_compare_op1 != const0_rtx)
9844         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9845                                     ? GET_MODE (sh_compare_op0)
9846                                     : GET_MODE (sh_compare_op1),
9847                                     sh_compare_op1);
9848
9849       emit_insn (gen_cmpgtudi_media (reg,
9850                                      sh_compare_op0, sh_compare_op1));
9851       if (GET_MODE (operands[0]) == DImode)
9852         emit_insn (gen_extendsidi2 (operands[0], reg));
9853
9854       DONE;
9855     }
9856   if (! currently_expanding_to_rtl)
9857     FAIL;
9858   operands[1] = prepare_scc_operands (GTU);
9859 }")
9860
9861 (define_expand "sltu"
9862   [(set (match_operand:SI 0 "arith_reg_operand" "")
9863         (match_dup 1))]
9864   ""
9865   "
9866 {
9867   if (TARGET_SHMEDIA)
9868     {
9869       rtx reg;
9870
9871       reg = operands[0];
9872       if (GET_MODE (operands[0]) == DImode)
9873         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9874                              : gen_reg_rtx (SImode);
9875       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9876       if (sh_compare_op1 != const0_rtx)
9877         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9878                                     ? GET_MODE (sh_compare_op0)
9879                                     : GET_MODE (sh_compare_op1),
9880                                     sh_compare_op1);
9881
9882       emit_insn (gen_cmpgtudi_media (reg,
9883                                      sh_compare_op1, sh_compare_op0));
9884       if (GET_MODE (operands[0]) == DImode)
9885         emit_insn (gen_extendsidi2 (operands[0], reg));
9886
9887       DONE;
9888     }
9889   if (! currently_expanding_to_rtl)
9890     FAIL;
9891   operands[1] = prepare_scc_operands (LTU);
9892 }")
9893
9894 (define_expand "sleu"
9895   [(set (match_operand:SI 0 "arith_reg_operand" "")
9896         (match_dup 1))]
9897   ""
9898   "
9899 {
9900   if (TARGET_SHMEDIA)
9901     {
9902       rtx tmp, reg;
9903
9904       reg = operands[0];
9905       if (GET_MODE (operands[0]) != SImode)
9906         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9907                              : gen_reg_rtx (SImode);
9908       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9909       if (sh_compare_op1 != const0_rtx)
9910         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9911                                     ? GET_MODE (sh_compare_op0)
9912                                     : GET_MODE (sh_compare_op1),
9913                                     sh_compare_op1);
9914
9915       tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
9916
9917       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
9918       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9919       if (GET_MODE (operands[0]) == DImode)
9920         emit_insn (gen_extendsidi2 (operands[0], reg));
9921
9922       DONE;
9923     }
9924   if (! currently_expanding_to_rtl)
9925     FAIL;
9926   operands[1] = prepare_scc_operands (LEU);
9927 }")
9928
9929 (define_expand "sgeu"
9930   [(set (match_operand:SI 0 "arith_reg_operand" "")
9931         (match_dup 1))]
9932   ""
9933   "
9934 {
9935   if (TARGET_SHMEDIA)
9936     {
9937       rtx tmp, reg;
9938
9939       reg = operands[0];
9940       if (GET_MODE (operands[0]) != SImode)
9941         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9942                              : gen_reg_rtx (SImode);
9943       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9944       if (sh_compare_op1 != const0_rtx)
9945         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9946                                     ? GET_MODE (sh_compare_op0)
9947                                     : GET_MODE (sh_compare_op1),
9948                                     sh_compare_op1);
9949
9950       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
9951
9952       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
9953       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
9954       if (GET_MODE (operands[0]) == DImode)
9955         emit_insn (gen_extendsidi2 (operands[0], reg));
9956
9957       DONE;
9958     }
9959
9960   if (! currently_expanding_to_rtl)
9961     FAIL;
9962   operands[1] = prepare_scc_operands (GEU);
9963 }")
9964
9965 ;; sne moves the complement of the T reg to DEST like this:
9966 ;;      cmp/eq ...
9967 ;;      mov    #-1,temp
9968 ;;      negc   temp,dest
9969 ;;   This is better than xoring compare result with 1 because it does
9970 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
9971 ;;   loop.
9972
9973 (define_expand "sne"
9974   [(set (match_dup 2) (const_int -1))
9975    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
9976                    (neg:SI (plus:SI (match_dup 1)
9977                                     (match_dup 2))))
9978               (set (reg:SI T_REG)
9979                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
9980                           (const_int 0)))])]
9981   ""
9982   "
9983 {
9984   if (TARGET_SHMEDIA)
9985     {
9986       rtx tmp, reg;
9987
9988       reg = operands[0];
9989       if (GET_MODE (operands[0]) != SImode)
9990         reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
9991                              : gen_reg_rtx (SImode);
9992       if (! TARGET_SHMEDIA_FPU
9993           && GET_MODE (sh_compare_op0) != DImode
9994           && GET_MODE (sh_compare_op0) != SImode)
9995         FAIL;
9996
9997       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9998       if (sh_compare_op1 != const0_rtx)
9999         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
10000                                     ? GET_MODE (sh_compare_op0)
10001                                     : GET_MODE (sh_compare_op1),
10002                                     sh_compare_op1);
10003
10004       tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
10005
10006       emit_insn (gen_seq (tmp));
10007       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
10008       if (GET_MODE (operands[0]) == DImode)
10009         emit_insn (gen_extendsidi2 (operands[0], reg));
10010
10011       DONE;
10012     }
10013
10014   if (sh_expand_t_scc (NE, operands[0]))
10015     DONE;
10016   if (! currently_expanding_to_rtl)
10017     FAIL;
10018   operands[1] = prepare_scc_operands (EQ);
10019   operands[2] = gen_reg_rtx (SImode);
10020 }")
10021
10022 (define_expand "sunordered"
10023   [(set (match_operand:SI 0 "arith_reg_operand" "")
10024         (unordered:SI (match_dup 1) (match_dup 2)))]
10025   "TARGET_SHMEDIA_FPU"
10026   "
10027 {
10028   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
10029   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
10030 }")
10031
10032 ;; Use the same trick for FP sle / sge
10033
10034 ;; Apart from the constant use and the T setting, this is like movt,
10035 ;; except that it uses the logically negated value of T, i.e.
10036 ;; operand[0] := T ? 0 : 1.
10037 (define_expand "movnegt"
10038   [(set (match_dup 2) (const_int -1))
10039    (parallel [(set (match_operand 0 "" "")
10040                    (neg:SI (plus:SI (match_dup 1)
10041                                     (match_dup 2))))
10042               (set (reg:SI T_REG)
10043                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
10044                           (const_int 0)))])]
10045   "TARGET_SH1"
10046   "operands[2] = gen_reg_rtx (SImode);")
10047
10048 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
10049 ;; This prevents a regression that occurred when we switched from xor to
10050 ;; mov/neg for sne.
10051
10052 (define_split
10053   [(set (match_operand:SI 0 "arith_reg_dest" "")
10054         (plus:SI (reg:SI T_REG)
10055                  (const_int -1)))]
10056   "TARGET_SH1"
10057   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
10058    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
10059   "")
10060
10061 ;; -------------------------------------------------------------------------
10062 ;; Instructions to cope with inline literal tables
10063 ;; -------------------------------------------------------------------------
10064
10065 ; 2 byte integer in line
10066
10067 (define_insn "consttable_2"
10068  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
10069                     (match_operand 1 "" "")]
10070                    UNSPECV_CONST2)]
10071  ""
10072  "*
10073 {
10074   if (operands[1] != const0_rtx)
10075     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
10076   return \"\";
10077 }"
10078  [(set_attr "length" "2")
10079  (set_attr "in_delay_slot" "no")])
10080
10081 ; 4 byte integer in line
10082
10083 (define_insn "consttable_4"
10084  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
10085                     (match_operand 1 "" "")]
10086                    UNSPECV_CONST4)]
10087  ""
10088  "*
10089 {
10090   if (operands[1] != const0_rtx)
10091     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
10092   return \"\";
10093 }"
10094  [(set_attr "length" "4")
10095   (set_attr "in_delay_slot" "no")])
10096
10097 ; 8 byte integer in line
10098
10099 (define_insn "consttable_8"
10100  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
10101                     (match_operand 1 "" "")]
10102                    UNSPECV_CONST8)]
10103  ""
10104  "*
10105 {
10106   if (operands[1] != const0_rtx)
10107     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
10108   return \"\";
10109 }"
10110  [(set_attr "length" "8")
10111   (set_attr "in_delay_slot" "no")])
10112
10113 ; 4 byte floating point
10114
10115 (define_insn "consttable_sf"
10116  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
10117                     (match_operand 1 "" "")]
10118                    UNSPECV_CONST4)]
10119  ""
10120  "*
10121 {
10122   if (operands[1] != const0_rtx)
10123     {
10124       REAL_VALUE_TYPE d;
10125       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
10126       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
10127     }
10128   return \"\";
10129 }"
10130  [(set_attr "length" "4")
10131   (set_attr "in_delay_slot" "no")])
10132
10133 ; 8 byte floating point
10134
10135 (define_insn "consttable_df"
10136  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
10137                     (match_operand 1 "" "")]
10138                    UNSPECV_CONST8)]
10139  ""
10140  "*
10141 {
10142   if (operands[1] != const0_rtx)
10143     {
10144       REAL_VALUE_TYPE d;
10145       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
10146       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
10147     }
10148   return \"\";
10149 }"
10150  [(set_attr "length" "8")
10151   (set_attr "in_delay_slot" "no")])
10152
10153 ;; Alignment is needed for some constant tables; it may also be added for
10154 ;; Instructions at the start of loops, or after unconditional branches.
10155 ;; ??? We would get more accurate lengths if we did instruction
10156 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
10157 ;; here is too conservative.
10158
10159 ; align to a two byte boundary
10160
10161 (define_expand "align_2"
10162  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
10163  ""
10164  "")
10165
10166 ; align to a four byte boundary
10167 ;; align_4 and align_log are instructions for the starts of loops, or
10168 ;; after unconditional branches, which may take up extra room.
10169
10170 (define_expand "align_4"
10171  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
10172  ""
10173  "")
10174
10175 ; align to a cache line boundary
10176
10177 (define_insn "align_log"
10178  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
10179  ""
10180  ""
10181  [(set_attr "length" "0")
10182   (set_attr "in_delay_slot" "no")])
10183
10184 ; emitted at the end of the literal table, used to emit the
10185 ; 32bit branch labels if needed.
10186
10187 (define_insn "consttable_end"
10188   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
10189   ""
10190   "* return output_jump_label_table ();"
10191   [(set_attr "in_delay_slot" "no")])
10192
10193 ; emitted at the end of the window in the literal table.
10194
10195 (define_insn "consttable_window_end"
10196   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
10197   ""
10198   ""
10199   [(set_attr "length" "0")
10200    (set_attr "in_delay_slot" "no")])
10201
10202 ;; -------------------------------------------------------------------------
10203 ;; Misc
10204 ;; -------------------------------------------------------------------------
10205
10206 ;; String/block move insn.
10207
10208 (define_expand "movmemsi"
10209   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
10210                    (mem:BLK (match_operand:BLK 1 "" "")))
10211               (use (match_operand:SI 2 "nonmemory_operand" ""))
10212               (use (match_operand:SI 3 "immediate_operand" ""))
10213               (clobber (reg:SI PR_REG))
10214               (clobber (reg:SI R4_REG))
10215               (clobber (reg:SI R5_REG))
10216               (clobber (reg:SI R0_REG))])]
10217   "TARGET_SH1 && ! TARGET_SH5"
10218   "
10219 {
10220   if(expand_block_move (operands))
10221      DONE;
10222   else FAIL;
10223 }")
10224
10225 (define_insn "block_move_real"
10226   [(parallel [(set (mem:BLK (reg:SI R4_REG))
10227                    (mem:BLK (reg:SI R5_REG)))
10228               (use (match_operand:SI 0 "arith_reg_operand" "r"))
10229               (clobber (reg:SI PR_REG))
10230               (clobber (reg:SI R0_REG))])]
10231   "TARGET_SH1 && ! TARGET_HARD_SH4"
10232   "jsr  @%0%#"
10233   [(set_attr "type" "sfunc")
10234    (set_attr "needs_delay_slot" "yes")])
10235
10236 (define_insn "block_lump_real"
10237   [(parallel [(set (mem:BLK (reg:SI R4_REG))
10238                    (mem:BLK (reg:SI R5_REG)))
10239               (use (match_operand:SI 0 "arith_reg_operand" "r"))
10240               (use (reg:SI R6_REG))
10241               (clobber (reg:SI PR_REG))
10242               (clobber (reg:SI T_REG))
10243               (clobber (reg:SI R4_REG))
10244               (clobber (reg:SI R5_REG))
10245               (clobber (reg:SI R6_REG))
10246               (clobber (reg:SI R0_REG))])]
10247   "TARGET_SH1 && ! TARGET_HARD_SH4"
10248   "jsr  @%0%#"
10249   [(set_attr "type" "sfunc")
10250    (set_attr "needs_delay_slot" "yes")])
10251
10252 (define_insn "block_move_real_i4"
10253   [(parallel [(set (mem:BLK (reg:SI R4_REG))
10254                    (mem:BLK (reg:SI R5_REG)))
10255               (use (match_operand:SI 0 "arith_reg_operand" "r"))
10256               (clobber (reg:SI PR_REG))
10257               (clobber (reg:SI R0_REG))
10258               (clobber (reg:SI R1_REG))
10259               (clobber (reg:SI R2_REG))])]
10260   "TARGET_HARD_SH4"
10261   "jsr  @%0%#"
10262   [(set_attr "type" "sfunc")
10263    (set_attr "needs_delay_slot" "yes")])
10264
10265 (define_insn "block_lump_real_i4"
10266   [(parallel [(set (mem:BLK (reg:SI R4_REG))
10267                    (mem:BLK (reg:SI R5_REG)))
10268               (use (match_operand:SI 0 "arith_reg_operand" "r"))
10269               (use (reg:SI R6_REG))
10270               (clobber (reg:SI PR_REG))
10271               (clobber (reg:SI T_REG))
10272               (clobber (reg:SI R4_REG))
10273               (clobber (reg:SI R5_REG))
10274               (clobber (reg:SI R6_REG))
10275               (clobber (reg:SI R0_REG))
10276               (clobber (reg:SI R1_REG))
10277               (clobber (reg:SI R2_REG))
10278               (clobber (reg:SI R3_REG))])]
10279   "TARGET_HARD_SH4"
10280   "jsr  @%0%#"
10281   [(set_attr "type" "sfunc")
10282    (set_attr "needs_delay_slot" "yes")])
10283 \f
10284 ;; -------------------------------------------------------------------------
10285 ;; Floating point instructions.
10286 ;; -------------------------------------------------------------------------
10287
10288 ;; ??? All patterns should have a type attribute.
10289
10290 (define_expand "movpsi"
10291   [(set (match_operand:PSI 0 "register_operand" "")
10292         (match_operand:PSI 1 "general_movsrc_operand" ""))]
10293   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10294   "")
10295
10296 ;; The c / m alternative is a fake to guide reload to load directly into
10297 ;; fpscr, since reload doesn't know how to use post-increment.
10298 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
10299 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
10300 ;; predicate after reload.
10301 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
10302 ;; like a mac -> gpr move.
10303 (define_insn "fpu_switch"
10304   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
10305         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
10306   "TARGET_SH2E
10307    && (! reload_completed
10308        || true_regnum (operands[0]) != FPSCR_REG
10309        || GET_CODE (operands[1]) != MEM
10310        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
10311   "@
10312         ! precision stays the same
10313         lds.l   %1,fpscr
10314         mov.l   %1,%0
10315         #
10316         lds     %1,fpscr
10317         mov     %1,%0
10318         mov.l   %1,%0
10319         sts     fpscr,%0
10320         sts.l   fpscr,%0"
10321   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
10322    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
10323
10324 (define_peephole2
10325   [(set (reg:PSI FPSCR_REG)
10326         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10327   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
10328   [(const_int 0)]
10329 {
10330   rtx fpscr, mem, new_insn;
10331
10332   fpscr = SET_DEST (PATTERN (curr_insn));
10333   mem = SET_SRC (PATTERN (curr_insn));
10334   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10335
10336   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10337   REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
10338   DONE;
10339 })
10340
10341 (define_split
10342   [(set (reg:PSI FPSCR_REG)
10343         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
10344   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
10345    && (flag_peephole2 ? epilogue_completed : reload_completed)"
10346   [(const_int 0)]
10347 {
10348   rtx fpscr, mem, new_insn;
10349
10350   fpscr = SET_DEST (PATTERN (curr_insn));
10351   mem = SET_SRC (PATTERN (curr_insn));
10352   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
10353
10354   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
10355   REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
10356
10357   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
10358     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
10359   DONE;
10360 })
10361
10362 ;; ??? This uses the fp unit, but has no type indicating that.
10363 ;; If we did that, this would either give a bogus latency or introduce
10364 ;; a bogus FIFO constraint.
10365 ;; Since this insn is currently only used for prologues/epilogues,
10366 ;; it is probably best to claim no function unit, which matches the
10367 ;; current setting.
10368 (define_insn "toggle_sz"
10369   [(set (reg:PSI FPSCR_REG)
10370         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
10371   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10372   "fschg"
10373   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
10374
10375 ;; There's no way we can use it today, since optimize mode switching
10376 ;; doesn't enable us to know from which mode we're switching to the
10377 ;; mode it requests, to tell whether we can use a relative mode switch
10378 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
10379 ;; memory).
10380 (define_insn "toggle_pr"
10381   [(set (reg:PSI FPSCR_REG)
10382         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
10383   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
10384   "fpchg"
10385   [(set_attr "type" "fpscr_toggle")])
10386
10387 (define_expand "addsf3"
10388   [(set (match_operand:SF 0 "arith_reg_operand" "")
10389         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
10390                  (match_operand:SF 2 "arith_reg_operand" "")))]
10391   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10392   "
10393 {
10394   if (TARGET_SH2E)
10395     {
10396       expand_sf_binop (&gen_addsf3_i, operands);
10397       DONE;
10398     }
10399 }")
10400
10401 (define_insn "*addsf3_media"
10402   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10403         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10404                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10405   "TARGET_SHMEDIA_FPU"
10406   "fadd.s       %1, %2, %0"
10407   [(set_attr "type" "fparith_media")])
10408
10409 (define_insn_and_split "unary_sf_op"
10410   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10411         (vec_select:V2SF
10412          (vec_concat:V2SF
10413           (vec_select:SF
10414            (match_dup 0)
10415            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
10416           (match_operator:SF 2 "unary_float_operator"
10417             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10418                             (parallel [(match_operand 4
10419                                         "const_int_operand" "n")]))]))
10420          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
10421   "TARGET_SHMEDIA_FPU"
10422   "#"
10423   "TARGET_SHMEDIA_FPU && reload_completed"
10424   [(set (match_dup 5) (match_dup 6))]
10425   "
10426 {
10427   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10428   rtx op1 = gen_rtx_REG (SFmode,
10429                          (true_regnum (operands[1])
10430                           + (INTVAL (operands[4]) ^ endian)));
10431
10432   operands[7] = gen_rtx_REG (SFmode,
10433                              (true_regnum (operands[0])
10434                               + (INTVAL (operands[3]) ^ endian)));
10435   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10436 }"
10437   [(set_attr "type" "fparith_media")])
10438
10439 (define_insn_and_split "binary_sf_op"
10440   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10441         (vec_select:V2SF
10442          (vec_concat:V2SF
10443           (vec_select:SF
10444            (match_dup 0)
10445            (parallel [(match_operand 7 "const_int_operand" "n")]))
10446           (match_operator:SF 3 "binary_float_operator"
10447             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10448                             (parallel [(match_operand 5
10449                                         "const_int_operand" "n")]))
10450              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10451                             (parallel [(match_operand 6
10452                                         "const_int_operand" "n")]))]))
10453          (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
10454   "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
10455   "#"
10456   "&& reload_completed"
10457   [(set (match_dup 8) (match_dup 9))]
10458   "
10459 {
10460   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10461   rtx op1 = gen_rtx_REG (SFmode,
10462                          (true_regnum (operands[1])
10463                           + (INTVAL (operands[5]) ^ endian)));
10464   rtx op2 = gen_rtx_REG (SFmode,
10465                          (true_regnum (operands[2])
10466                           + (INTVAL (operands[6]) ^ endian)));
10467
10468   operands[8] = gen_rtx_REG (SFmode,
10469                              (true_regnum (operands[0])
10470                               + (INTVAL (operands[4]) ^ endian)));
10471   operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10472 }"
10473   [(set_attr "type" "fparith_media")])
10474
10475 (define_insn "addsf3_i"
10476   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10477         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10478                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10479    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10480   "TARGET_SH2E"
10481   "fadd %2,%0"
10482   [(set_attr "type" "fp")
10483    (set_attr "fp_mode" "single")])
10484
10485 (define_expand "subsf3"
10486   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10487         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10488                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10489   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10490   "
10491 {
10492   if (TARGET_SH2E)
10493     {
10494       expand_sf_binop (&gen_subsf3_i, operands);
10495       DONE;
10496     }
10497 }")
10498
10499 (define_insn "*subsf3_media"
10500   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10501         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10502                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10503   "TARGET_SHMEDIA_FPU"
10504   "fsub.s       %1, %2, %0"
10505   [(set_attr "type" "fparith_media")])
10506
10507 (define_insn "subsf3_i"
10508   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10509         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10510                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10511    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10512   "TARGET_SH2E"
10513   "fsub %2,%0"
10514   [(set_attr "type" "fp")
10515    (set_attr "fp_mode" "single")])
10516
10517 (define_expand "mulsf3"
10518   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10519         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10520                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10521   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10522   "")
10523
10524 (define_insn "*mulsf3_media"
10525   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10526         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10527                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10528   "TARGET_SHMEDIA_FPU"
10529   "fmul.s       %1, %2, %0"
10530   [(set_attr "type" "fparith_media")])
10531
10532 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10533 ;; register in feeding fp instructions.  Thus, in order to generate fmac,
10534 ;; we start out with a mulsf pattern that does not depend on fpscr.
10535 ;; This is split after combine to introduce the dependency, in order to
10536 ;; get mode switching and scheduling right.
10537 (define_insn_and_split "mulsf3_ie"
10538   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10539         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10540                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10541   "TARGET_SH2E"
10542   "fmul %2,%0"
10543   "TARGET_SH4 || TARGET_SH2A_SINGLE"
10544   [(const_int 0)]
10545   "
10546 {
10547   emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
10548              get_fpscr_rtx ()));
10549   DONE;
10550 }"
10551   [(set_attr "type" "fp")])
10552
10553 (define_insn "mulsf3_i4"
10554   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10555         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10556                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10557    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10558   "TARGET_SH2E"
10559   "fmul %2,%0"
10560   [(set_attr "type" "fp")
10561    (set_attr "fp_mode" "single")])
10562
10563 (define_insn "mac_media"
10564   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10565         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10566                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10567                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10568   "TARGET_SHMEDIA_FPU && TARGET_FMAC"
10569   "fmac.s %1, %2, %0"
10570   [(set_attr "type" "fparith_media")])
10571
10572 (define_insn "*macsf3"
10573   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10574         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10575                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10576                  (match_operand:SF 3 "arith_reg_operand" "0")))
10577    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10578   "TARGET_SH2E && TARGET_FMAC"
10579   "fmac fr0,%2,%0"
10580   [(set_attr "type" "fp")
10581    (set_attr "fp_mode" "single")])
10582
10583 (define_expand "divsf3"
10584   [(set (match_operand:SF 0 "arith_reg_operand" "")
10585         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10586                 (match_operand:SF 2 "arith_reg_operand" "")))]
10587   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10588   "
10589 {
10590   if (TARGET_SH2E)
10591     {
10592       expand_sf_binop (&gen_divsf3_i, operands);
10593       DONE;
10594     }
10595 }")
10596
10597 (define_insn "*divsf3_media"
10598   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10599         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10600                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10601   "TARGET_SHMEDIA_FPU"
10602   "fdiv.s       %1, %2, %0"
10603   [(set_attr "type" "fdiv_media")])
10604
10605 (define_insn "divsf3_i"
10606   [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10607         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10608                  (match_operand:SF 2 "arith_reg_operand" "f")))
10609    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10610   "TARGET_SH2E"
10611   "fdiv %2,%0"
10612   [(set_attr "type" "fdiv")
10613    (set_attr "fp_mode" "single")])
10614
10615 (define_insn "floatdisf2"
10616   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10617         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10618   "TARGET_SHMEDIA_FPU"
10619   "float.qs %1, %0"
10620   [(set_attr "type" "fpconv_media")])
10621
10622 (define_expand "floatsisf2"
10623   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10624         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10625   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10626   "
10627 {
10628   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10629     {
10630       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10631       DONE;
10632     }
10633 }")
10634
10635 (define_insn "*floatsisf2_media"
10636   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10637         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10638   "TARGET_SHMEDIA_FPU"
10639   "float.ls     %1, %0"
10640   [(set_attr "type" "fpconv_media")])
10641
10642 (define_insn "floatsisf2_i4"
10643   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10644         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10645    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10646   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10647   "float        %1,%0"
10648   [(set_attr "type" "fp")
10649    (set_attr "fp_mode" "single")])
10650
10651 (define_insn "*floatsisf2_ie"
10652   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10653         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10654   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10655   "float        %1,%0"
10656   [(set_attr "type" "fp")])
10657
10658 (define_insn "fix_truncsfdi2"
10659   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10660         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10661   "TARGET_SHMEDIA_FPU"
10662   "ftrc.sq %1, %0"
10663   [(set_attr "type" "fpconv_media")])
10664
10665 (define_expand "fix_truncsfsi2"
10666   [(set (match_operand:SI 0 "fpul_operand" "=y")
10667         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10668   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10669   "
10670 {
10671   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10672     {
10673       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10674       DONE;
10675     }
10676 }")
10677
10678 (define_insn "*fix_truncsfsi2_media"
10679   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10680         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10681   "TARGET_SHMEDIA_FPU"
10682   "ftrc.sl      %1, %0"
10683   [(set_attr "type" "fpconv_media")])
10684
10685 (define_insn "fix_truncsfsi2_i4"
10686   [(set (match_operand:SI 0 "fpul_operand" "=y")
10687         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10688    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10689   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10690   "ftrc %1,%0"
10691   [(set_attr "type" "ftrc_s")
10692    (set_attr "fp_mode" "single")])
10693
10694 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
10695 ;; fix_truncsfsi2_i4.
10696 ;; (define_insn "fix_truncsfsi2_i4_2"
10697 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10698 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10699 ;;   (use (reg:PSI FPSCR_REG))
10700 ;;   (clobber (reg:SI FPUL_REG))]
10701 ;;  "TARGET_SH4"
10702 ;;  "#"
10703 ;;  [(set_attr "length" "4")
10704 ;;   (set_attr "fp_mode" "single")])
10705
10706 ;;(define_split
10707 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10708 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10709 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
10710 ;;   (clobber (reg:SI FPUL_REG))]
10711 ;;  "TARGET_SH4"
10712 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10713 ;;            (use (match_dup 2))])
10714 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
10715
10716 (define_insn "*fixsfsi"
10717   [(set (match_operand:SI 0 "fpul_operand" "=y")
10718         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10719   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10720   "ftrc %1,%0"
10721   [(set_attr "type" "fp")])
10722
10723 (define_insn "cmpgtsf_t"
10724   [(set (reg:SI T_REG)
10725         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10726                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10727   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10728   "fcmp/gt      %1,%0"
10729   [(set_attr "type" "fp_cmp")
10730    (set_attr "fp_mode" "single")])
10731
10732 (define_insn "cmpeqsf_t"
10733   [(set (reg:SI T_REG)
10734         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10735                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10736   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10737   "fcmp/eq      %1,%0"
10738   [(set_attr "type" "fp_cmp")
10739    (set_attr "fp_mode" "single")])
10740
10741 (define_insn "ieee_ccmpeqsf_t"
10742   [(set (reg:SI T_REG)
10743         (ior:SI (reg:SI T_REG)
10744                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10745                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10746   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10747   "* return output_ieee_ccmpeq (insn, operands);"
10748   [(set_attr "length" "4")])
10749
10750
10751 (define_insn "cmpgtsf_t_i4"
10752   [(set (reg:SI T_REG)
10753         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10754                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10755    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10756   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10757   "fcmp/gt      %1,%0"
10758   [(set_attr "type" "fp_cmp")
10759    (set_attr "fp_mode" "single")])
10760
10761 (define_insn "cmpeqsf_t_i4"
10762   [(set (reg:SI T_REG)
10763         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10764                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10765    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10766   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10767   "fcmp/eq      %1,%0"
10768   [(set_attr "type" "fp_cmp")
10769    (set_attr "fp_mode" "single")])
10770
10771 (define_insn "*ieee_ccmpeqsf_t_4"
10772   [(set (reg:SI T_REG)
10773         (ior:SI (reg:SI T_REG)
10774                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10775                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10776    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10777   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10778   "* return output_ieee_ccmpeq (insn, operands);"
10779   [(set_attr "length" "4")
10780    (set_attr "fp_mode" "single")])
10781
10782 (define_insn "cmpeqsf_media"
10783   [(set (match_operand:SI 0 "register_operand" "=r")
10784         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10785                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10786   "TARGET_SHMEDIA_FPU"
10787   "fcmpeq.s     %1, %2, %0"
10788   [(set_attr "type" "fcmp_media")])
10789
10790 (define_insn "cmpgtsf_media"
10791   [(set (match_operand:SI 0 "register_operand" "=r")
10792         (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10793                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10794   "TARGET_SHMEDIA_FPU"
10795   "fcmpgt.s     %1, %2, %0"
10796   [(set_attr "type" "fcmp_media")])
10797
10798 (define_insn "cmpgesf_media"
10799   [(set (match_operand:SI 0 "register_operand" "=r")
10800         (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10801                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10802   "TARGET_SHMEDIA_FPU"
10803   "fcmpge.s     %1, %2, %0"
10804   [(set_attr "type" "fcmp_media")])
10805
10806 (define_insn "cmpunsf_media"
10807   [(set (match_operand:SI 0 "register_operand" "=r")
10808         (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10809                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10810   "TARGET_SHMEDIA_FPU"
10811   "fcmpun.s     %1, %2, %0"
10812   [(set_attr "type" "fcmp_media")])
10813
10814 (define_expand "cmpsf"
10815   [(set (reg:SI T_REG)
10816         (compare (match_operand:SF 0 "arith_operand" "")
10817                  (match_operand:SF 1 "arith_operand" "")))]
10818   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10819   "
10820 {
10821   sh_compare_op0 = operands[0];
10822   sh_compare_op1 = operands[1];
10823   DONE;
10824 }")
10825
10826 (define_expand "negsf2"
10827   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10828         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10829   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10830   "
10831 {
10832   if (TARGET_SH2E)
10833     {
10834       expand_sf_unop (&gen_negsf2_i, operands);
10835       DONE;
10836     }
10837 }")
10838
10839 (define_insn "*negsf2_media"
10840   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10841         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10842   "TARGET_SHMEDIA_FPU"
10843   "fneg.s       %1, %0"
10844   [(set_attr "type" "fmove_media")])
10845
10846 (define_insn "negsf2_i"
10847   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10848         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10849    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10850   "TARGET_SH2E"
10851   "fneg %0"
10852   [(set_attr "type" "fmove")
10853    (set_attr "fp_mode" "single")])
10854
10855 (define_expand "sqrtsf2"
10856   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10857         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10858   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10859   "
10860 {
10861   if (TARGET_SH3E)
10862     {
10863       expand_sf_unop (&gen_sqrtsf2_i, operands);
10864       DONE;
10865     }
10866 }")
10867
10868 (define_insn "*sqrtsf2_media"
10869   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10870         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10871   "TARGET_SHMEDIA_FPU"
10872   "fsqrt.s      %1, %0"
10873   [(set_attr "type" "fdiv_media")])
10874
10875 (define_insn "sqrtsf2_i"
10876   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10877         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10878    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10879   "TARGET_SH3E"
10880   "fsqrt        %0"
10881   [(set_attr "type" "fdiv")
10882    (set_attr "fp_mode" "single")])
10883
10884 (define_insn "rsqrtsf2"
10885   [(set (match_operand:SF 0 "register_operand" "=f")
10886         (div:SF (match_operand:SF 1 "immediate_operand" "i")
10887                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10888    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10889   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10890    && operands[1] == CONST1_RTX (SFmode)"
10891   "fsrra        %0"
10892   [(set_attr "type" "fsrra")
10893    (set_attr "fp_mode" "single")])
10894
10895 (define_insn "fsca"
10896   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10897         (vec_concat:V2SF
10898          (unspec:SF [(mult:SF
10899                       (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10900                       (match_operand:SF 2 "immediate_operand" "i"))
10901                     ] UNSPEC_FSINA)
10902          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10903                     ] UNSPEC_FCOSA)))
10904    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10905   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10906    && operands[2] == sh_fsca_int2sf ()"
10907   "fsca fpul,%d0"
10908   [(set_attr "type" "fsca")
10909    (set_attr "fp_mode" "single")])
10910
10911 (define_expand "sinsf2"
10912   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10913         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10914                    UNSPEC_FSINA))]
10915   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10916   "
10917 {
10918   rtx scaled = gen_reg_rtx (SFmode);
10919   rtx truncated = gen_reg_rtx (SImode);
10920   rtx fsca = gen_reg_rtx (V2SFmode);
10921   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10922
10923   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10924   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10925   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10926                           get_fpscr_rtx ()));
10927   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10928   DONE;
10929 }")
10930
10931 (define_expand "cossf2"
10932   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10933         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10934                    UNSPEC_FCOSA))]
10935   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10936   "
10937 {
10938   rtx scaled = gen_reg_rtx (SFmode);
10939   rtx truncated = gen_reg_rtx (SImode);
10940   rtx fsca = gen_reg_rtx (V2SFmode);
10941   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10942
10943   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10944   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10945   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10946                           get_fpscr_rtx ()));
10947   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10948   DONE;
10949 }")
10950
10951 (define_expand "sindf2"
10952   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10953         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10954                    UNSPEC_FSINA))]
10955   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10956   "
10957 {
10958   rtx scaled = gen_reg_rtx (DFmode);
10959   rtx truncated = gen_reg_rtx (SImode);
10960   rtx fsca = gen_reg_rtx (V2SFmode);
10961   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10962   rtx sfresult = gen_reg_rtx (SFmode);
10963
10964   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10965   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10966   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10967                           get_fpscr_rtx ()));
10968   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10969   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10970   DONE;
10971 }")
10972
10973 (define_expand "cosdf2"
10974   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10975         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10976                    UNSPEC_FCOSA))]
10977   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10978   "
10979 {
10980   rtx scaled = gen_reg_rtx (DFmode);
10981   rtx truncated = gen_reg_rtx (SImode);
10982   rtx fsca = gen_reg_rtx (V2SFmode);
10983   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10984   rtx sfresult = gen_reg_rtx (SFmode);
10985
10986   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10987   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10988   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10989                           get_fpscr_rtx ()));
10990   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10991   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10992   DONE;
10993 }")
10994
10995 (define_expand "abssf2"
10996   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10997         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10998   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10999   "
11000 {
11001   if (TARGET_SH2E)
11002     {
11003       expand_sf_unop (&gen_abssf2_i, operands);
11004       DONE;
11005     }
11006 }")
11007
11008 (define_insn "*abssf2_media"
11009   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11010         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11011   "TARGET_SHMEDIA_FPU"
11012   "fabs.s       %1, %0"
11013   [(set_attr "type" "fmove_media")])
11014
11015 (define_insn "abssf2_i"
11016   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11017         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
11018    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11019   "TARGET_SH2E"
11020   "fabs %0"
11021   [(set_attr "type" "fmove")
11022    (set_attr "fp_mode" "single")])
11023
11024 (define_expand "adddf3"
11025   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11026         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
11027                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
11028   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11029   "
11030 {
11031   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11032     {
11033       expand_df_binop (&gen_adddf3_i, operands);
11034       DONE;
11035     }
11036 }")
11037
11038 (define_insn "*adddf3_media"
11039   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11040         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
11041                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11042   "TARGET_SHMEDIA_FPU"
11043   "fadd.d       %1, %2, %0"
11044   [(set_attr "type" "dfparith_media")])
11045
11046 (define_insn "adddf3_i"
11047   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11048         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
11049                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
11050    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11051   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11052   "fadd %2,%0"
11053   [(set_attr "type" "dfp_arith")
11054    (set_attr "fp_mode" "double")])
11055
11056 (define_expand "subdf3"
11057   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11058         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
11059                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
11060   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11061   "
11062 {
11063   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11064     {
11065       expand_df_binop (&gen_subdf3_i, operands);
11066       DONE;
11067     }
11068 }")
11069
11070 (define_insn "*subdf3_media"
11071   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11072         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
11073                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11074   "TARGET_SHMEDIA_FPU"
11075   "fsub.d       %1, %2, %0"
11076   [(set_attr "type" "dfparith_media")])
11077
11078 (define_insn "subdf3_i"
11079   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11080         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
11081                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
11082    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11083   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11084   "fsub %2,%0"
11085   [(set_attr "type" "dfp_arith")
11086    (set_attr "fp_mode" "double")])
11087
11088 (define_expand "muldf3"
11089   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11090         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
11091                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
11092   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11093   "
11094 {
11095   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11096     {
11097       expand_df_binop (&gen_muldf3_i, operands);
11098       DONE;
11099     }
11100 }")
11101
11102 (define_insn "*muldf3_media"
11103   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11104         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
11105                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11106   "TARGET_SHMEDIA_FPU"
11107   "fmul.d       %1, %2, %0"
11108   [(set_attr "type" "dfmul_media")])
11109
11110 (define_insn "muldf3_i"
11111   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11112         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
11113                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
11114    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11115   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11116   "fmul %2,%0"
11117   [(set_attr "type" "dfp_mul")
11118    (set_attr "fp_mode" "double")])
11119
11120 (define_expand "divdf3"
11121   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11122         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
11123                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
11124   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11125   "
11126 {
11127   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11128     {
11129       expand_df_binop (&gen_divdf3_i, operands);
11130       DONE;
11131     }
11132 }")
11133
11134 (define_insn "*divdf3_media"
11135   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11136         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
11137                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11138   "TARGET_SHMEDIA_FPU"
11139   "fdiv.d       %1, %2, %0"
11140   [(set_attr "type" "dfdiv_media")])
11141
11142 (define_insn "divdf3_i"
11143   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11144         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
11145                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
11146    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11147   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11148   "fdiv %2,%0"
11149   [(set_attr "type" "dfdiv")
11150    (set_attr "fp_mode" "double")])
11151
11152 (define_insn "floatdidf2"
11153   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11154         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
11155   "TARGET_SHMEDIA_FPU"
11156   "float.qd     %1, %0"
11157   [(set_attr "type" "dfpconv_media")])
11158
11159 (define_expand "floatsidf2"
11160   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11161         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
11162   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11163   "
11164 {
11165   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11166     {
11167       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
11168                                       get_fpscr_rtx ()));
11169       DONE;
11170     }
11171 }")
11172
11173 (define_insn "*floatsidf2_media"
11174   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11175         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
11176   "TARGET_SHMEDIA_FPU"
11177   "float.ld     %1, %0"
11178   [(set_attr "type" "dfpconv_media")])
11179
11180 (define_insn "floatsidf2_i"
11181   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11182         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
11183    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11184   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11185   "float        %1,%0"
11186   [(set_attr "type" "dfp_conv")
11187    (set_attr "fp_mode" "double")])
11188
11189 (define_insn "fix_truncdfdi2"
11190   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
11191         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11192   "TARGET_SHMEDIA_FPU"
11193   "ftrc.dq      %1, %0"
11194   [(set_attr "type" "dfpconv_media")])
11195
11196 (define_expand "fix_truncdfsi2"
11197   [(set (match_operand:SI 0 "fpul_operand" "")
11198         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11199   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11200   "
11201 {
11202   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11203     {
11204       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
11205                                           get_fpscr_rtx ()));
11206       DONE;
11207     }
11208 }")
11209
11210 (define_insn "*fix_truncdfsi2_media"
11211   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
11212         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11213   "TARGET_SHMEDIA_FPU"
11214   "ftrc.dl      %1, %0"
11215   [(set_attr "type" "dfpconv_media")])
11216
11217 (define_insn "fix_truncdfsi2_i"
11218   [(set (match_operand:SI 0 "fpul_operand" "=y")
11219         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11220    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11221   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11222   "ftrc %1,%0"
11223   [(set_attr "type" "dfp_conv")
11224    (set_attr "dfp_comp" "no")
11225    (set_attr "fp_mode" "double")])
11226
11227 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
11228 ;; fix_truncdfsi2_i.
11229 ;; (define_insn "fix_truncdfsi2_i4"
11230 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11231 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
11232 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
11233 ;;    (clobber (reg:SI FPUL_REG))]
11234 ;;   "TARGET_SH4"
11235 ;;   "#"
11236 ;;   [(set_attr "length" "4")
11237 ;;    (set_attr "fp_mode" "double")])
11238 ;;
11239 ;; (define_split
11240 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11241 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
11242 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
11243 ;;    (clobber (reg:SI FPUL_REG))]
11244 ;;   "TARGET_SH4"
11245 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
11246 ;;            (use (match_dup 2))])
11247 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
11248
11249 (define_insn "cmpgtdf_t"
11250   [(set (reg:SI T_REG)
11251         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
11252                (match_operand:DF 1 "arith_reg_operand" "f")))
11253    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11254   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11255   "fcmp/gt      %1,%0"
11256   [(set_attr "type" "dfp_cmp")
11257    (set_attr "fp_mode" "double")])
11258
11259 (define_insn "cmpeqdf_t"
11260   [(set (reg:SI T_REG)
11261         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
11262                (match_operand:DF 1 "arith_reg_operand" "f")))
11263    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11264   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11265   "fcmp/eq      %1,%0"
11266   [(set_attr "type" "dfp_cmp")
11267    (set_attr "fp_mode" "double")])
11268
11269 (define_insn "*ieee_ccmpeqdf_t"
11270   [(set (reg:SI T_REG)
11271         (ior:SI (reg:SI T_REG)
11272                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
11273                        (match_operand:DF 1 "arith_reg_operand" "f"))))
11274    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11275   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11276   "* return output_ieee_ccmpeq (insn, operands);"
11277   [(set_attr "length" "4")
11278    (set_attr "fp_mode" "double")])
11279
11280 (define_insn "cmpeqdf_media"
11281   [(set (match_operand:SI 0 "register_operand" "=r")
11282         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11283                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11284   "TARGET_SHMEDIA_FPU"
11285   "fcmpeq.d     %1,%2,%0"
11286   [(set_attr "type" "fcmp_media")])
11287
11288 (define_insn "cmpgtdf_media"
11289   [(set (match_operand:SI 0 "register_operand" "=r")
11290         (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11291                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11292   "TARGET_SHMEDIA_FPU"
11293   "fcmpgt.d     %1,%2,%0"
11294   [(set_attr "type" "fcmp_media")])
11295
11296 (define_insn "cmpgedf_media"
11297   [(set (match_operand:SI 0 "register_operand" "=r")
11298         (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11299                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11300   "TARGET_SHMEDIA_FPU"
11301   "fcmpge.d     %1,%2,%0"
11302   [(set_attr "type" "fcmp_media")])
11303
11304 (define_insn "cmpundf_media"
11305   [(set (match_operand:SI 0 "register_operand" "=r")
11306         (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
11307                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
11308   "TARGET_SHMEDIA_FPU"
11309   "fcmpun.d     %1,%2,%0"
11310   [(set_attr "type" "fcmp_media")])
11311
11312 (define_expand "cmpdf"
11313   [(set (reg:SI T_REG)
11314         (compare (match_operand:DF 0 "arith_operand" "")
11315                  (match_operand:DF 1 "arith_operand" "")))]
11316   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11317   "
11318 {
11319   sh_compare_op0 = operands[0];
11320   sh_compare_op1 = operands[1];
11321   DONE;
11322 }")
11323
11324 (define_expand "negdf2"
11325   [(set (match_operand:DF 0 "arith_reg_operand" "")
11326         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11327   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11328   "
11329 {
11330   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11331     {
11332       expand_df_unop (&gen_negdf2_i, operands);
11333       DONE;
11334     }
11335 }")
11336
11337 (define_insn "*negdf2_media"
11338   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11339         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11340   "TARGET_SHMEDIA_FPU"
11341   "fneg.d       %1, %0"
11342   [(set_attr "type" "fmove_media")])
11343
11344 (define_insn "negdf2_i"
11345   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11346         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11347    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11348   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11349   "fneg %0"
11350   [(set_attr "type" "fmove")
11351    (set_attr "fp_mode" "double")])
11352
11353 (define_expand "sqrtdf2"
11354   [(set (match_operand:DF 0 "arith_reg_operand" "")
11355         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11356   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11357   "
11358 {
11359   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11360     {
11361       expand_df_unop (&gen_sqrtdf2_i, operands);
11362       DONE;
11363     }
11364 }")
11365
11366 (define_insn "*sqrtdf2_media"
11367   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11368         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11369   "TARGET_SHMEDIA_FPU"
11370   "fsqrt.d      %1, %0"
11371   [(set_attr "type" "dfdiv_media")])
11372
11373 (define_insn "sqrtdf2_i"
11374   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11375         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11376    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11377   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11378   "fsqrt        %0"
11379   [(set_attr "type" "dfdiv")
11380    (set_attr "fp_mode" "double")])
11381
11382 (define_expand "absdf2"
11383   [(set (match_operand:DF 0 "arith_reg_operand" "")
11384         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
11385   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11386   "
11387 {
11388   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11389     {
11390       expand_df_unop (&gen_absdf2_i, operands);
11391       DONE;
11392     }
11393 }")
11394
11395 (define_insn "*absdf2_media"
11396   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11397         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11398   "TARGET_SHMEDIA_FPU"
11399   "fabs.d       %1, %0"
11400   [(set_attr "type" "fmove_media")])
11401
11402 (define_insn "absdf2_i"
11403   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11404         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
11405    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11406   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11407   "fabs %0"
11408   [(set_attr "type" "fmove")
11409    (set_attr "fp_mode" "double")])
11410
11411 (define_expand "extendsfdf2"
11412   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11413         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11414   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11415   "
11416 {
11417   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11418     {
11419       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11420                                         get_fpscr_rtx ()));
11421       DONE;
11422     }
11423 }")
11424
11425 (define_insn "*extendsfdf2_media"
11426   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11427         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11428   "TARGET_SHMEDIA_FPU"
11429   "fcnv.sd      %1, %0"
11430   [(set_attr "type" "dfpconv_media")])
11431
11432 (define_insn "extendsfdf2_i4"
11433   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11434         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11435    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11436   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11437   "fcnvsd  %1,%0"
11438   [(set_attr "type" "fp")
11439    (set_attr "fp_mode" "double")])
11440
11441 (define_expand "truncdfsf2"
11442   [(set (match_operand:SF 0 "fpul_operand" "")
11443         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11444   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11445   "
11446 {
11447   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11448     {
11449       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11450                                        get_fpscr_rtx ()));
11451       DONE;
11452     }
11453 }")
11454
11455 (define_insn "*truncdfsf2_media"
11456   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11457         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11458   "TARGET_SHMEDIA_FPU"
11459   "fcnv.ds      %1, %0"
11460   [(set_attr "type" "dfpconv_media")])
11461
11462 (define_insn "truncdfsf2_i4"
11463   [(set (match_operand:SF 0 "fpul_operand" "=y")
11464         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11465    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11466   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11467   "fcnvds  %1,%0"
11468   [(set_attr "type" "fp")
11469    (set_attr "fp_mode" "double")])
11470 \f
11471 ;; Bit field extract patterns.  These give better code for packed bitfields,
11472 ;; because they allow auto-increment addresses to be generated.
11473
11474 (define_expand "insv"
11475   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11476                          (match_operand:SI 1 "immediate_operand" "")
11477                          (match_operand:SI 2 "immediate_operand" ""))
11478         (match_operand:SI 3 "general_operand" ""))]
11479   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11480   "
11481 {
11482   rtx addr_target, orig_address, shift_reg, qi_val;
11483   HOST_WIDE_INT bitsize, size, v = 0;
11484   rtx x = operands[3];
11485
11486   /* ??? expmed doesn't care for non-register predicates.  */
11487   if (! memory_operand (operands[0], VOIDmode)
11488       || ! immediate_operand (operands[1], VOIDmode)
11489       || ! immediate_operand (operands[2], VOIDmode)
11490       || ! general_operand (x, VOIDmode))
11491     FAIL;
11492   /* If this isn't a 16 / 24 / 32 bit field, or if
11493      it doesn't start on a byte boundary, then fail.  */
11494   bitsize = INTVAL (operands[1]);
11495   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11496       || (INTVAL (operands[2]) % 8) != 0)
11497     FAIL;
11498
11499   size = bitsize / 8;
11500   orig_address = XEXP (operands[0], 0);
11501   shift_reg = gen_reg_rtx (SImode);
11502   if (GET_CODE (x) == CONST_INT)
11503     {
11504       v = INTVAL (x);
11505       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11506     }
11507   else
11508     {
11509       emit_insn (gen_movsi (shift_reg, operands[3]));
11510       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11511     }
11512   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11513
11514   operands[0] = replace_equiv_address (operands[0], addr_target);
11515   emit_insn (gen_movqi (operands[0], qi_val));
11516
11517   while (size -= 1)
11518     {
11519       if (GET_CODE (x) == CONST_INT)
11520         qi_val
11521           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11522       else
11523         {
11524           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11525           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11526         }
11527       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11528       emit_insn (gen_movqi (operands[0], qi_val));
11529     }
11530
11531   DONE;
11532 }")
11533
11534 (define_insn "movua"
11535   [(set (match_operand:SI 0 "register_operand" "=z")
11536         (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
11537                    UNSPEC_MOVUA))]
11538   "TARGET_SH4A_ARCH"
11539   "movua.l      %1,%0"
11540   [(set_attr "type" "movua")])
11541
11542 ;; We shouldn't need this, but cse replaces increments with references
11543 ;; to other regs before flow has a chance to create post_inc
11544 ;; addressing modes, and only postreload's cse_move2add brings the
11545 ;; increments back to a usable form.
11546 (define_peephole2
11547   [(set (match_operand:SI 0 "register_operand" "")
11548         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11549                          (const_int 32) (const_int 0)))
11550    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11551   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11552   [(set (match_operand:SI 0 "register_operand" "")
11553         (sign_extract:SI (mem:SI (post_inc:SI
11554                                   (match_operand:SI 1 "register_operand" "")))
11555                          (const_int 32) (const_int 0)))]
11556   "")
11557
11558 (define_expand "extv"
11559   [(set (match_operand:SI 0 "register_operand" "")
11560         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11561                          (match_operand 2 "const_int_operand" "")
11562                          (match_operand 3 "const_int_operand" "")))]
11563   "TARGET_SH4A_ARCH"
11564 {
11565   if (TARGET_SH4A_ARCH
11566       && INTVAL (operands[2]) == 32
11567       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11568       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11569     {
11570       rtx src = adjust_address (operands[1], BLKmode, 0);
11571       set_mem_size (src, GEN_INT (4));
11572       emit_insn (gen_movua (operands[0], src));
11573       DONE;
11574     }
11575
11576   FAIL;
11577 })
11578
11579 (define_expand "extzv"
11580   [(set (match_operand:SI 0 "register_operand" "")
11581         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11582                          (match_operand 2 "const_int_operand" "")
11583                          (match_operand 3 "const_int_operand" "")))]
11584   "TARGET_SH4A_ARCH"
11585 {
11586   if (TARGET_SH4A_ARCH
11587       && INTVAL (operands[2]) == 32
11588       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11589       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11590     {
11591       rtx src = adjust_address (operands[1], BLKmode, 0);
11592       set_mem_size (src, GEN_INT (4));
11593       emit_insn (gen_movua (operands[0], src));
11594       DONE;
11595     }
11596
11597   FAIL;
11598 })
11599
11600 \f
11601 ;; -------------------------------------------------------------------------
11602 ;; Peepholes
11603 ;; -------------------------------------------------------------------------
11604
11605 ;; This matches cases where a stack pointer increment at the start of the
11606 ;; epilogue combines with a stack slot read loading the return value.
11607
11608 (define_peephole
11609   [(set (match_operand:SI 0 "arith_reg_operand" "")
11610         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11611    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11612   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11613   "mov.l        @%1+,%0")
11614
11615 ;; See the comment on the dt combiner pattern above.
11616
11617 (define_peephole
11618   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11619         (plus:SI (match_dup 0)
11620                  (const_int -1)))
11621    (set (reg:SI T_REG)
11622         (eq:SI (match_dup 0)
11623                (const_int 0)))]
11624   "TARGET_SH2"
11625   "dt   %0")
11626
11627 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11628 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
11629 ;; reload when the constant is too large for a reg+offset address.
11630
11631 ;; ??? We would get much better code if this was done in reload.  This would
11632 ;; require modifying find_reloads_address to recognize that if the constant
11633 ;; is out-of-range for an immediate add, then we get better code by reloading
11634 ;; the constant into a register than by reloading the sum into a register,
11635 ;; since the former is one instruction shorter if the address does not need
11636 ;; to be offsettable.  Unfortunately this does not work, because there is
11637 ;; only one register, r0, that can be used as an index register.  This register
11638 ;; is also the function return value register.  So, if we try to force reload
11639 ;; to use double-reg addresses, then we end up with some instructions that
11640 ;; need to use r0 twice.  The only way to fix this is to change the calling
11641 ;; convention so that r0 is not used to return values.
11642
11643 (define_peephole
11644   [(set (match_operand:SI 0 "register_operand" "=r")
11645         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11646    (set (mem:SI (match_dup 0))
11647         (match_operand:SI 2 "general_movsrc_operand" ""))]
11648   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11649   "mov.l        %2,@(%0,%1)")
11650
11651 (define_peephole
11652   [(set (match_operand:SI 0 "register_operand" "=r")
11653         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11654    (set (match_operand:SI 2 "general_movdst_operand" "")
11655         (mem:SI (match_dup 0)))]
11656   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11657   "mov.l        @(%0,%1),%2")
11658
11659 (define_peephole
11660   [(set (match_operand:SI 0 "register_operand" "=r")
11661         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11662    (set (mem:HI (match_dup 0))
11663         (match_operand:HI 2 "general_movsrc_operand" ""))]
11664   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11665   "mov.w        %2,@(%0,%1)")
11666
11667 (define_peephole
11668   [(set (match_operand:SI 0 "register_operand" "=r")
11669         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11670    (set (match_operand:HI 2 "general_movdst_operand" "")
11671         (mem:HI (match_dup 0)))]
11672   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11673   "mov.w        @(%0,%1),%2")
11674
11675 (define_peephole
11676   [(set (match_operand:SI 0 "register_operand" "=r")
11677         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11678    (set (mem:QI (match_dup 0))
11679         (match_operand:QI 2 "general_movsrc_operand" ""))]
11680   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11681   "mov.b        %2,@(%0,%1)")
11682
11683 (define_peephole
11684   [(set (match_operand:SI 0 "register_operand" "=r")
11685         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11686    (set (match_operand:QI 2 "general_movdst_operand" "")
11687         (mem:QI (match_dup 0)))]
11688   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11689   "mov.b        @(%0,%1),%2")
11690
11691 (define_peephole
11692   [(set (match_operand:SI 0 "register_operand" "=r")
11693         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11694    (set (mem:SF (match_dup 0))
11695         (match_operand:SF 2 "general_movsrc_operand" ""))]
11696   "TARGET_SH1 && REGNO (operands[0]) == 0
11697    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11698        || (GET_CODE (operands[2]) == SUBREG
11699            && REGNO (SUBREG_REG (operands[2])) < 16))
11700    && reg_unused_after (operands[0], insn)"
11701   "mov.l        %2,@(%0,%1)")
11702
11703 (define_peephole
11704   [(set (match_operand:SI 0 "register_operand" "=r")
11705         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11706    (set (match_operand:SF 2 "general_movdst_operand" "")
11707
11708         (mem:SF (match_dup 0)))]
11709   "TARGET_SH1 && REGNO (operands[0]) == 0
11710    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11711        || (GET_CODE (operands[2]) == SUBREG
11712            && REGNO (SUBREG_REG (operands[2])) < 16))
11713    && reg_unused_after (operands[0], insn)"
11714   "mov.l        @(%0,%1),%2")
11715
11716 (define_peephole
11717   [(set (match_operand:SI 0 "register_operand" "=r")
11718         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11719    (set (mem:SF (match_dup 0))
11720         (match_operand:SF 2 "general_movsrc_operand" ""))]
11721   "TARGET_SH2E && REGNO (operands[0]) == 0
11722    && ((GET_CODE (operands[2]) == REG
11723         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11724        || (GET_CODE (operands[2]) == SUBREG
11725            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11726    && reg_unused_after (operands[0], insn)"
11727   "fmov{.s|}    %2,@(%0,%1)")
11728
11729 (define_peephole
11730   [(set (match_operand:SI 0 "register_operand" "=r")
11731         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11732    (set (match_operand:SF 2 "general_movdst_operand" "")
11733
11734         (mem:SF (match_dup 0)))]
11735   "TARGET_SH2E && REGNO (operands[0]) == 0
11736    && ((GET_CODE (operands[2]) == REG
11737         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11738        || (GET_CODE (operands[2]) == SUBREG
11739            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11740    && reg_unused_after (operands[0], insn)"
11741   "fmov{.s|}    @(%0,%1),%2")
11742
11743 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
11744 (define_insn "sp_switch_1"
11745   [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11746   "TARGET_SH1"
11747   "*
11748 {
11749   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11750   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11751   return \"mov r0,r15\";
11752 }"
11753   [(set_attr "length" "10")])
11754
11755 ;; Switch back to the original stack for interrupt functions with the
11756 ;; sp_switch attribute.  */
11757 (define_insn "sp_switch_2"
11758   [(const_int 2)]
11759   "TARGET_SH1"
11760   "mov.l @r15+,r15\;mov.l @r15+,r0"
11761   [(set_attr "length" "4")])
11762
11763 ;; Integer vector moves
11764
11765 (define_expand "movv8qi"
11766   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11767         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11768   "TARGET_SHMEDIA"
11769   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11770
11771 (define_insn "movv8qi_i"
11772   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11773         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11774   "TARGET_SHMEDIA
11775    && (register_operand (operands[0], V8QImode)
11776        || sh_register_operand (operands[1], V8QImode))"
11777   "@
11778         add     %1, r63, %0
11779         movi    %1, %0
11780         #
11781         ld%M1.q %m1, %0
11782         st%M0.q %m0, %N1"
11783   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11784    (set_attr "length" "4,4,16,4,4")])
11785
11786 (define_split
11787   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11788         (subreg:V8QI (const_int 0) 0))]
11789   "TARGET_SHMEDIA"
11790   [(set (match_dup 0)
11791         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11792                             (const_int 0) (const_int 0) (const_int 0)
11793                             (const_int 0) (const_int 0)]))])
11794
11795 (define_split
11796   [(set (match_operand 0 "arith_reg_dest" "")
11797         (match_operand 1 "sh_rep_vec" ""))]
11798   "TARGET_SHMEDIA && reload_completed
11799    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11800    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11801    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11802    && (XVECEXP (operands[1], 0, 0) != const0_rtx
11803        || XVECEXP (operands[1], 0, 1) != const0_rtx)
11804    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11805        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11806   [(set (match_dup 0) (match_dup 1))
11807    (match_dup 2)]
11808   "
11809 {
11810   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11811   rtx elt1 = XVECEXP (operands[1], 0, 1);
11812
11813   if (unit_size > 2)
11814     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11815   else
11816     {
11817       if (unit_size < 2)
11818         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11819       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11820     }
11821   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11822   operands[1] = XVECEXP (operands[1], 0, 0);
11823   if (unit_size < 2)
11824     {
11825       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
11826         operands[1]
11827           = GEN_INT (TARGET_LITTLE_ENDIAN
11828                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11829                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11830       else
11831         {
11832           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11833           operands[1]
11834             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11835         }
11836     }
11837 }")
11838
11839 (define_split
11840   [(set (match_operand 0 "arith_reg_dest" "")
11841         (match_operand 1 "sh_const_vec" ""))]
11842   "TARGET_SHMEDIA && reload_completed
11843    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11844    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11845   [(set (match_dup 0) (match_dup 1))]
11846   "
11847 {
11848   rtx v = operands[1];
11849   enum machine_mode new_mode
11850     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11851
11852   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11853   operands[1]
11854     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11855 }")
11856
11857 (define_expand "movv2hi"
11858   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11859         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
11860   "TARGET_SHMEDIA"
11861   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11862
11863 (define_insn "movv2hi_i"
11864   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11865         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11866   "TARGET_SHMEDIA
11867    && (register_operand (operands[0], V2HImode)
11868        || sh_register_operand (operands[1], V2HImode))"
11869   "@
11870         add.l   %1, r63, %0
11871         movi    %1, %0
11872         #
11873         ld%M1.l %m1, %0
11874         st%M0.l %m0, %N1"
11875   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11876    (set_attr "length" "4,4,16,4,4")
11877    (set (attr "highpart")
11878         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
11879                (const_string "user")]
11880               (const_string "ignore")))])
11881
11882 (define_expand "movv4hi"
11883   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11884         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
11885   "TARGET_SHMEDIA"
11886   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11887
11888 (define_insn "movv4hi_i"
11889   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11890         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11891   "TARGET_SHMEDIA
11892    && (register_operand (operands[0], V4HImode)
11893        || sh_register_operand (operands[1], V4HImode))"
11894   "@
11895         add     %1, r63, %0
11896         movi    %1, %0
11897         #
11898         ld%M1.q %m1, %0
11899         st%M0.q %m0, %N1"
11900   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11901    (set_attr "length" "4,4,16,4,4")
11902    (set_attr "highpart" "depend")])
11903
11904 (define_expand "movv2si"
11905   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11906         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
11907   "TARGET_SHMEDIA"
11908   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11909
11910 (define_insn "movv2si_i"
11911   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11912         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11913   "TARGET_SHMEDIA
11914    && (register_operand (operands[0], V2SImode)
11915        || sh_register_operand (operands[1], V2SImode))"
11916   "@
11917         add     %1, r63, %0
11918         #
11919         #
11920         ld%M1.q %m1, %0
11921         st%M0.q %m0, %N1"
11922   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11923    (set_attr "length" "4,4,16,4,4")
11924    (set_attr "highpart" "depend")])
11925
11926 ;; Multimedia Intrinsics
11927
11928 (define_insn "absv2si2"
11929   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11930         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11931   "TARGET_SHMEDIA"
11932   "mabs.l       %1, %0"
11933   [(set_attr "type" "mcmp_media")
11934    (set_attr "highpart" "depend")])
11935
11936 (define_insn "absv4hi2"
11937   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11938         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11939   "TARGET_SHMEDIA"
11940   "mabs.w       %1, %0"
11941   [(set_attr "type" "mcmp_media")
11942    (set_attr "highpart" "depend")])
11943
11944 (define_insn "addv2si3"
11945   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11946         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11947                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11948   "TARGET_SHMEDIA"
11949   "madd.l       %1, %2, %0"
11950   [(set_attr "type" "arith_media")
11951    (set_attr "highpart" "depend")])
11952
11953 (define_insn "addv4hi3"
11954   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11955         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11956                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11957   "TARGET_SHMEDIA"
11958   "madd.w       %1, %2, %0"
11959   [(set_attr "type" "arith_media")
11960    (set_attr "highpart" "depend")])
11961
11962 (define_insn_and_split "addv2hi3"
11963   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11964         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11965                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11966   "TARGET_SHMEDIA"
11967   "#"
11968   "TARGET_SHMEDIA"
11969   [(const_int 0)]
11970   "
11971 {
11972   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11973   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11974   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11975   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11976   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11977
11978   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11979   emit_insn (gen_truncdisi2 (si_dst, di_dst));
11980   DONE;
11981 }"
11982   [(set_attr "highpart" "must_split")])
11983
11984 (define_insn "ssaddv2si3"
11985   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11986         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11987                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11988   "TARGET_SHMEDIA"
11989   "madds.l      %1, %2, %0"
11990   [(set_attr "type" "mcmp_media")
11991    (set_attr "highpart" "depend")])
11992
11993 (define_insn "usaddv8qi3"
11994   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11995         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11996                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11997   "TARGET_SHMEDIA"
11998   "madds.ub     %1, %2, %0"
11999   [(set_attr "type" "mcmp_media")
12000    (set_attr "highpart" "depend")])
12001
12002 (define_insn "ssaddv4hi3"
12003   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12004         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
12005                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12006   "TARGET_SHMEDIA"
12007   "madds.w      %1, %2, %0"
12008   [(set_attr "type" "mcmp_media")
12009    (set_attr "highpart" "depend")])
12010
12011 (define_insn "negcmpeqv8qi"
12012   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12013         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
12014                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
12015   "TARGET_SHMEDIA"
12016   "mcmpeq.b     %N1, %N2, %0"
12017   [(set_attr "type" "mcmp_media")
12018    (set_attr "highpart" "depend")])
12019
12020 (define_insn "negcmpeqv2si"
12021   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12022         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
12023                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12024   "TARGET_SHMEDIA"
12025   "mcmpeq.l     %N1, %N2, %0"
12026   [(set_attr "type" "mcmp_media")
12027    (set_attr "highpart" "depend")])
12028
12029 (define_insn "negcmpeqv4hi"
12030   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12031         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
12032                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12033   "TARGET_SHMEDIA"
12034   "mcmpeq.w     %N1, %N2, %0"
12035   [(set_attr "type" "mcmp_media")
12036    (set_attr "highpart" "depend")])
12037
12038 (define_insn "negcmpgtuv8qi"
12039   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12040         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
12041                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
12042   "TARGET_SHMEDIA"
12043   "mcmpgt.ub    %N1, %N2, %0"
12044   [(set_attr "type" "mcmp_media")
12045    (set_attr "highpart" "depend")])
12046
12047 (define_insn "negcmpgtv2si"
12048   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12049         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
12050                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12051   "TARGET_SHMEDIA"
12052   "mcmpgt.l     %N1, %N2, %0"
12053   [(set_attr "type" "mcmp_media")
12054    (set_attr "highpart" "depend")])
12055
12056 (define_insn "negcmpgtv4hi"
12057   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12058         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
12059                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12060   "TARGET_SHMEDIA"
12061   "mcmpgt.w     %N1, %N2, %0"
12062   [(set_attr "type" "mcmp_media")
12063    (set_attr "highpart" "depend")])
12064
12065 (define_insn "mcmv"
12066   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12067         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12068                         (match_operand:DI 2 "arith_reg_operand" "r"))
12069                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
12070                         (not:DI (match_dup 2)))))]
12071   "TARGET_SHMEDIA"
12072   "mcmv %N1, %2, %0"
12073   [(set_attr "type" "arith_media")
12074    (set_attr "highpart" "depend")])
12075
12076 (define_insn "mcnvs_lw"
12077   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12078         (vec_concat:V4HI
12079          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
12080          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
12081   "TARGET_SHMEDIA"
12082   "mcnvs.lw     %N1, %N2, %0"
12083   [(set_attr "type" "mcmp_media")])
12084
12085 (define_insn "mcnvs_wb"
12086   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12087         (vec_concat:V8QI
12088          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12089          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12090   "TARGET_SHMEDIA"
12091   "mcnvs.wb     %N1, %N2, %0"
12092   [(set_attr "type" "mcmp_media")])
12093
12094 (define_insn "mcnvs_wub"
12095   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12096         (vec_concat:V8QI
12097          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
12098          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
12099   "TARGET_SHMEDIA"
12100   "mcnvs.wub    %N1, %N2, %0"
12101   [(set_attr "type" "mcmp_media")])
12102
12103 (define_insn "mextr_rl"
12104   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12105         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12106                              (match_operand:HI 3 "mextr_bit_offset" "i"))
12107                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12108                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12109   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12110   "*
12111 {
12112   static char templ[21];
12113
12114   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
12115            (int) INTVAL (operands[3]) >> 3);
12116   return templ;
12117 }"
12118   [(set_attr "type" "arith_media")])
12119
12120 (define_insn "*mextr_lr"
12121   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12122         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12123                            (match_operand:HI 3 "mextr_bit_offset" "i"))
12124                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12125                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
12126   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
12127   "*
12128 {
12129   static char templ[21];
12130
12131   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
12132            (int) INTVAL (operands[4]) >> 3);
12133   return templ;
12134 }"
12135   [(set_attr "type" "arith_media")])
12136
12137 ; mextrN can be modelled with vec_select / vec_concat, but the selection
12138 ; vector then varies depending on endianness.
12139 (define_expand "mextr1"
12140   [(match_operand:DI 0 "arith_reg_dest" "")
12141    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12142    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12143   "TARGET_SHMEDIA"
12144   "
12145 {
12146   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12147                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
12148   DONE;
12149 }")
12150
12151 (define_expand "mextr2"
12152   [(match_operand:DI 0 "arith_reg_dest" "")
12153    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12154    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12155   "TARGET_SHMEDIA"
12156   "
12157 {
12158   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12159                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
12160   DONE;
12161 }")
12162
12163 (define_expand "mextr3"
12164   [(match_operand:DI 0 "arith_reg_dest" "")
12165    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12166    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12167   "TARGET_SHMEDIA"
12168   "
12169 {
12170   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12171                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
12172   DONE;
12173 }")
12174
12175 (define_expand "mextr4"
12176   [(match_operand:DI 0 "arith_reg_dest" "")
12177    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12178    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12179   "TARGET_SHMEDIA"
12180   "
12181 {
12182   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12183                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
12184   DONE;
12185 }")
12186
12187 (define_expand "mextr5"
12188   [(match_operand:DI 0 "arith_reg_dest" "")
12189    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12190    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12191   "TARGET_SHMEDIA"
12192   "
12193 {
12194   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12195                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
12196   DONE;
12197 }")
12198
12199 (define_expand "mextr6"
12200   [(match_operand:DI 0 "arith_reg_dest" "")
12201    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12202    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12203   "TARGET_SHMEDIA"
12204   "
12205 {
12206   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12207                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
12208   DONE;
12209 }")
12210
12211 (define_expand "mextr7"
12212   [(match_operand:DI 0 "arith_reg_dest" "")
12213    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12214    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
12215   "TARGET_SHMEDIA"
12216   "
12217 {
12218   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
12219                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
12220   DONE;
12221 }")
12222
12223 (define_expand "mmacfx_wl"
12224   [(match_operand:V2SI 0 "arith_reg_dest" "")
12225    (match_operand:V2HI 1 "extend_reg_operand" "")
12226    (match_operand:V2HI 2 "extend_reg_operand" "")
12227    (match_operand:V2SI 3 "arith_reg_operand" "")]
12228   "TARGET_SHMEDIA"
12229   "
12230 {
12231   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
12232                               operands[1], operands[2]));
12233   DONE;
12234 }")
12235
12236 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
12237 ;; is depend
12238 (define_insn "mmacfx_wl_i"
12239   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12240         (ss_plus:V2SI
12241          (match_operand:V2SI 1 "arith_reg_operand" "0")
12242          (ss_truncate:V2SI
12243           (ashift:V2DI
12244            (sign_extend:V2DI
12245             (mult:V2SI
12246              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12247              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12248            (const_int 1)))))]
12249   "TARGET_SHMEDIA"
12250   "mmacfx.wl    %2, %3, %0"
12251   [(set_attr "type" "mac_media")
12252    (set_attr "highpart" "depend")])
12253
12254 (define_expand "mmacnfx_wl"
12255   [(match_operand:V2SI 0 "arith_reg_dest" "")
12256    (match_operand:V2HI 1 "extend_reg_operand" "")
12257    (match_operand:V2HI 2 "extend_reg_operand" "")
12258    (match_operand:V2SI 3 "arith_reg_operand" "")]
12259   "TARGET_SHMEDIA"
12260   "
12261 {
12262   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
12263                                operands[1], operands[2]));
12264   DONE;
12265 }")
12266
12267 (define_insn "mmacnfx_wl_i"
12268   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12269         (ss_minus:V2SI
12270          (match_operand:V2SI 1 "arith_reg_operand" "0")
12271          (ss_truncate:V2SI
12272           (ashift:V2DI
12273            (sign_extend:V2DI
12274             (mult:V2SI
12275              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
12276              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
12277            (const_int 1)))))]
12278   "TARGET_SHMEDIA"
12279   "mmacnfx.wl   %2, %3, %0"
12280   [(set_attr "type" "mac_media")
12281    (set_attr "highpart" "depend")])
12282
12283 (define_insn "mulv2si3"
12284   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12285         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12286                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12287   "TARGET_SHMEDIA"
12288   "mmul.l       %1, %2, %0"
12289   [(set_attr "type" "d2mpy_media")
12290    (set_attr "highpart" "depend")])
12291
12292 (define_insn "mulv4hi3"
12293   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12294         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12295                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12296   "TARGET_SHMEDIA"
12297   "mmul.w       %1, %2, %0"
12298   [(set_attr "type" "dmpy_media")
12299    (set_attr "highpart" "depend")])
12300
12301 (define_insn "mmulfx_l"
12302   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12303         (ss_truncate:V2SI
12304          (ashiftrt:V2DI
12305           (mult:V2DI
12306            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12307            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
12308           (const_int 31))))]
12309   "TARGET_SHMEDIA"
12310   "mmulfx.l     %1, %2, %0"
12311   [(set_attr "type" "d2mpy_media")
12312    (set_attr "highpart" "depend")])
12313
12314 (define_insn "mmulfx_w"
12315   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12316         (ss_truncate:V4HI
12317          (ashiftrt:V4SI
12318           (mult:V4SI
12319            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12320            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12321           (const_int 15))))]
12322   "TARGET_SHMEDIA"
12323   "mmulfx.w     %1, %2, %0"
12324   [(set_attr "type" "dmpy_media")
12325    (set_attr "highpart" "depend")])
12326
12327 (define_insn "mmulfxrp_w"
12328   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12329         (ss_truncate:V4HI
12330          (ashiftrt:V4SI
12331           (plus:V4SI
12332            (mult:V4SI
12333             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12334             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12335            (const_int 16384))
12336           (const_int 15))))]
12337   "TARGET_SHMEDIA"
12338   "mmulfxrp.w   %1, %2, %0"
12339   [(set_attr "type" "dmpy_media")
12340    (set_attr "highpart" "depend")])
12341
12342
12343 (define_expand "mmulhi_wl"
12344   [(match_operand:V2SI 0 "arith_reg_dest" "")
12345    (match_operand:V4HI 1 "arith_reg_operand" "")
12346    (match_operand:V4HI 2 "arith_reg_operand" "")]
12347   "TARGET_SHMEDIA"
12348   "
12349 {
12350   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12351              (operands[0], operands[1], operands[2]));
12352   DONE;
12353 }")
12354
12355 (define_expand "mmullo_wl"
12356   [(match_operand:V2SI 0 "arith_reg_dest" "")
12357    (match_operand:V4HI 1 "arith_reg_operand" "")
12358    (match_operand:V4HI 2 "arith_reg_operand" "")]
12359   "TARGET_SHMEDIA"
12360   "
12361 {
12362   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12363              (operands[0], operands[1], operands[2]));
12364   DONE;
12365 }")
12366
12367 (define_insn "mmul23_wl"
12368   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12369         (vec_select:V2SI
12370          (mult:V4SI
12371           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12372           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12373          (parallel [(const_int 2) (const_int 3)])))]
12374   "TARGET_SHMEDIA"
12375   "* return (TARGET_LITTLE_ENDIAN
12376              ? \"mmulhi.wl      %1, %2, %0\"
12377              : \"mmullo.wl      %1, %2, %0\");"
12378   [(set_attr "type" "dmpy_media")
12379    (set (attr "highpart")
12380         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12381          (const_string "user")))])
12382
12383 (define_insn "mmul01_wl"
12384   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12385         (vec_select:V2SI
12386          (mult:V4SI
12387           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12388           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12389          (parallel [(const_int 0) (const_int 1)])))]
12390   "TARGET_SHMEDIA"
12391   "* return (TARGET_LITTLE_ENDIAN
12392              ? \"mmullo.wl      %1, %2, %0\"
12393              : \"mmulhi.wl      %1, %2, %0\");"
12394   [(set_attr "type" "dmpy_media")
12395    (set (attr "highpart")
12396         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12397          (const_string "user")))])
12398
12399
12400 (define_expand "mmulsum_wq"
12401   [(match_operand:DI 0 "arith_reg_dest" "")
12402    (match_operand:V4HI 1 "arith_reg_operand" "")
12403    (match_operand:V4HI 2 "arith_reg_operand" "")
12404    (match_operand:DI 3 "arith_reg_operand" "")]
12405   "TARGET_SHMEDIA"
12406   "
12407 {
12408   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12409                                operands[1], operands[2]));
12410   DONE;
12411 }")
12412
12413 (define_insn "mmulsum_wq_i"
12414   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12415         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12416          (plus:DI
12417           (plus:DI
12418            (vec_select:DI
12419             (mult:V4DI
12420              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12421              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12422             (parallel [(const_int 0)]))
12423            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12424                                      (sign_extend:V4DI (match_dup 3)))
12425                           (parallel [(const_int 1)])))
12426           (plus:DI
12427            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12428                                      (sign_extend:V4DI (match_dup 3)))
12429                           (parallel [(const_int 2)]))
12430            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12431                                      (sign_extend:V4DI (match_dup 3)))
12432                           (parallel [(const_int 3)]))))))]
12433   "TARGET_SHMEDIA"
12434   "mmulsum.wq   %2, %3, %0"
12435   [(set_attr "type" "mac_media")])
12436
12437 (define_expand "mperm_w"
12438   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12439    (match_operand:V4HI 1 "arith_reg_operand" "r")
12440    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12441   "TARGET_SHMEDIA"
12442   "
12443 {
12444   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12445              (operands[0], operands[1], operands[2]));
12446   DONE;
12447 }")
12448
12449 ; This use of vec_select isn't exactly correct according to rtl.texi
12450 ; (because not constant), but it seems a straightforward extension.
12451 (define_insn "mperm_w_little"
12452   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12453         (vec_select:V4HI
12454          (match_operand:V4HI 1 "arith_reg_operand" "r")
12455          (parallel
12456           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12457                             (const_int 2) (const_int 0))
12458            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12459            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12460            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12461   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12462   "mperm.w      %1, %N2, %0"
12463   [(set_attr "type" "arith_media")])
12464
12465 (define_insn "mperm_w_big"
12466   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12467         (vec_select:V4HI
12468          (match_operand:V4HI 1 "arith_reg_operand" "r")
12469          (parallel
12470           [(zero_extract:QI (not:QI (match_operand:QI 2
12471                                      "extend_reg_or_0_operand" "rZ"))
12472                             (const_int 2) (const_int 0))
12473            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12474            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12475            (zero_extract:QI (not:QI (match_dup 2))
12476                             (const_int 2) (const_int 6))])))]
12477   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12478   "mperm.w      %1, %N2, %0"
12479   [(set_attr "type" "arith_media")])
12480
12481 (define_insn "mperm_w0"
12482   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12483         (vec_duplicate:V4HI (truncate:HI (match_operand 1
12484                                           "trunc_hi_operand" "r"))))]
12485   "TARGET_SHMEDIA"
12486   "mperm.w      %1, r63, %0"
12487   [(set_attr "type" "arith_media")
12488    (set_attr "highpart" "ignore")])
12489
12490 (define_expand "msad_ubq"
12491   [(match_operand:DI 0 "arith_reg_dest" "")
12492    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12493    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12494    (match_operand:DI 3 "arith_reg_operand" "")]
12495   "TARGET_SHMEDIA"
12496   "
12497 {
12498   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12499                              operands[1], operands[2]));
12500   DONE;
12501 }")
12502
12503 (define_insn "msad_ubq_i"
12504   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12505         (plus:DI
12506          (plus:DI
12507           (plus:DI
12508            (plus:DI
12509             (match_operand:DI 1 "arith_reg_operand" "0")
12510             (abs:DI (vec_select:DI
12511                      (minus:V8DI
12512                       (zero_extend:V8DI
12513                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12514                       (zero_extend:V8DI
12515                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12516                      (parallel [(const_int 0)]))))
12517            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12518                                               (zero_extend:V8DI (match_dup 3)))
12519                                   (parallel [(const_int 1)]))))
12520           (plus:DI
12521            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12522                                               (zero_extend:V8DI (match_dup 3)))
12523                                   (parallel [(const_int 2)])))
12524            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12525                                               (zero_extend:V8DI (match_dup 3)))
12526                                   (parallel [(const_int 3)])))))
12527          (plus:DI
12528           (plus:DI
12529            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12530                                               (zero_extend:V8DI (match_dup 3)))
12531                                   (parallel [(const_int 4)])))
12532            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12533                                               (zero_extend:V8DI (match_dup 3)))
12534                                   (parallel [(const_int 5)]))))
12535           (plus:DI
12536            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12537                                               (zero_extend:V8DI (match_dup 3)))
12538                                   (parallel [(const_int 6)])))
12539            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12540                                               (zero_extend:V8DI (match_dup 3)))
12541                                   (parallel [(const_int 7)])))))))]
12542   "TARGET_SHMEDIA"
12543   "msad.ubq     %N2, %N3, %0"
12544   [(set_attr "type" "mac_media")])
12545
12546 (define_insn "mshalds_l"
12547   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12548         (ss_truncate:V2SI
12549          (ashift:V2DI
12550           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12551           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12552                   (const_int 31)))))]
12553   "TARGET_SHMEDIA"
12554   "mshalds.l    %1, %2, %0"
12555   [(set_attr "type" "mcmp_media")
12556    (set_attr "highpart" "depend")])
12557
12558 (define_insn "mshalds_w"
12559   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12560         (ss_truncate:V4HI
12561          (ashift:V4SI
12562           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12563           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12564                   (const_int 15)))))]
12565   "TARGET_SHMEDIA"
12566   "mshalds.w    %1, %2, %0"
12567   [(set_attr "type" "mcmp_media")
12568    (set_attr "highpart" "depend")])
12569
12570 (define_insn "ashrv2si3"
12571   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12572         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12573                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12574   "TARGET_SHMEDIA"
12575   "mshard.l     %1, %2, %0"
12576   [(set_attr "type" "arith_media")
12577    (set_attr "highpart" "depend")])
12578
12579 (define_insn "ashrv4hi3"
12580   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12581         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12582                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12583   "TARGET_SHMEDIA"
12584   "mshard.w     %1, %2, %0"
12585   [(set_attr "type" "arith_media")
12586    (set_attr "highpart" "depend")])
12587
12588 (define_insn "mshards_q"
12589   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12590         (ss_truncate:HI
12591          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12592                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12593   "TARGET_SHMEDIA"
12594   "mshards.q    %1, %N2, %0"
12595   [(set_attr "type" "mcmp_media")])
12596
12597 (define_expand "mshfhi_b"
12598   [(match_operand:V8QI 0 "arith_reg_dest" "")
12599    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12600    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12601   "TARGET_SHMEDIA"
12602   "
12603 {
12604   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12605              (operands[0], operands[1], operands[2]));
12606   DONE;
12607 }")
12608
12609 (define_expand "mshflo_b"
12610   [(match_operand:V8QI 0 "arith_reg_dest" "")
12611    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12612    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12613   "TARGET_SHMEDIA"
12614   "
12615 {
12616   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12617              (operands[0], operands[1], operands[2]));
12618   DONE;
12619 }")
12620
12621 (define_insn "mshf4_b"
12622   [(set
12623     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12624     (vec_select:V8QI
12625      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12626                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12627      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12628                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12629   "TARGET_SHMEDIA"
12630   "* return (TARGET_LITTLE_ENDIAN
12631              ? \"mshfhi.b       %N1, %N2, %0\"
12632              : \"mshflo.b       %N1, %N2, %0\");"
12633   [(set_attr "type" "arith_media")
12634    (set (attr "highpart")
12635         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12636          (const_string "user")))])
12637
12638 (define_insn "mshf0_b"
12639   [(set
12640     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12641     (vec_select:V8QI
12642      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12643                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12644      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12645                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12646   "TARGET_SHMEDIA"
12647   "* return (TARGET_LITTLE_ENDIAN
12648              ? \"mshflo.b       %N1, %N2, %0\"
12649              : \"mshfhi.b       %N1, %N2, %0\");"
12650   [(set_attr "type" "arith_media")
12651    (set (attr "highpart")
12652         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12653          (const_string "user")))])
12654
12655 (define_expand "mshfhi_l"
12656   [(match_operand:V2SI 0 "arith_reg_dest" "")
12657    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12658    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12659   "TARGET_SHMEDIA"
12660   "
12661 {
12662   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12663              (operands[0], operands[1], operands[2]));
12664   DONE;
12665 }")
12666
12667 (define_expand "mshflo_l"
12668   [(match_operand:V2SI 0 "arith_reg_dest" "")
12669    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12670    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12671   "TARGET_SHMEDIA"
12672   "
12673 {
12674   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12675              (operands[0], operands[1], operands[2]));
12676   DONE;
12677 }")
12678
12679 (define_insn "mshf4_l"
12680   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12681         (vec_select:V2SI
12682          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12683                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12684          (parallel [(const_int 1) (const_int 3)])))]
12685   "TARGET_SHMEDIA"
12686   "* return (TARGET_LITTLE_ENDIAN
12687              ? \"mshfhi.l       %N1, %N2, %0\"
12688              : \"mshflo.l       %N1, %N2, %0\");"
12689   [(set_attr "type" "arith_media")
12690    (set (attr "highpart")
12691         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12692          (const_string "user")))])
12693
12694 (define_insn "mshf0_l"
12695   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12696         (vec_select:V2SI
12697          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12698                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12699          (parallel [(const_int 0) (const_int 2)])))]
12700   "TARGET_SHMEDIA"
12701   "* return (TARGET_LITTLE_ENDIAN
12702              ? \"mshflo.l       %N1, %N2, %0\"
12703              : \"mshfhi.l       %N1, %N2, %0\");"
12704   [(set_attr "type" "arith_media")
12705    (set (attr "highpart")
12706         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12707          (const_string "user")))])
12708
12709 (define_expand "mshfhi_w"
12710   [(match_operand:V4HI 0 "arith_reg_dest" "")
12711    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12712    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12713   "TARGET_SHMEDIA"
12714   "
12715 {
12716   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12717              (operands[0], operands[1], operands[2]));
12718   DONE;
12719 }")
12720
12721 (define_expand "mshflo_w"
12722   [(match_operand:V4HI 0 "arith_reg_dest" "")
12723    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12724    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12725   "TARGET_SHMEDIA"
12726   "
12727 {
12728   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12729              (operands[0], operands[1], operands[2]));
12730   DONE;
12731 }")
12732
12733 (define_insn "mshf4_w"
12734   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12735         (vec_select:V4HI
12736          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12737                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12738          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12739   "TARGET_SHMEDIA"
12740   "* return (TARGET_LITTLE_ENDIAN
12741              ? \"mshfhi.w       %N1, %N2, %0\"
12742              : \"mshflo.w       %N1, %N2, %0\");"
12743   [(set_attr "type" "arith_media")
12744    (set (attr "highpart")
12745         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12746          (const_string "user")))])
12747
12748 (define_insn "mshf0_w"
12749   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12750         (vec_select:V4HI
12751          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12752                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12753          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12754   "TARGET_SHMEDIA"
12755   "* return (TARGET_LITTLE_ENDIAN
12756              ? \"mshflo.w       %N1, %N2, %0\"
12757              : \"mshfhi.w       %N1, %N2, %0\");"
12758   [(set_attr "type" "arith_media")
12759    (set (attr "highpart")
12760         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12761          (const_string "user")))])
12762
12763 (define_insn "mshflo_w_x"
12764   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12765         (vec_select:V4HI
12766          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12767                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12768          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12769   "TARGET_SHMEDIA"
12770   "mshflo.w     %N1, %N2, %0"
12771   [(set_attr "type" "arith_media")
12772    (set_attr "highpart" "ignore")])
12773
12774 /* These are useful to expand ANDs and as combiner patterns.  */
12775 (define_insn_and_split "mshfhi_l_di"
12776   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12777         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12778                              (const_int 32))
12779                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12780                         (const_int -4294967296))))]
12781   "TARGET_SHMEDIA"
12782   "@
12783         mshfhi.l        %N1, %N2, %0
12784         #"
12785   "TARGET_SHMEDIA && reload_completed
12786    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12787   [(set (match_dup 3) (match_dup 4))
12788    (set (match_dup 5) (match_dup 6))]
12789   "
12790 {
12791   operands[3] = gen_lowpart (SImode, operands[0]);
12792   operands[4] = gen_highpart (SImode, operands[1]);
12793   operands[5] = gen_highpart (SImode, operands[0]);
12794   operands[6] = gen_highpart (SImode, operands[2]);
12795 }"
12796   [(set_attr "type" "arith_media")])
12797
12798 (define_insn "*mshfhi_l_di_rev"
12799   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12800         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12801                         (const_int -4294967296))
12802                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12803                              (const_int 32))))]
12804   "TARGET_SHMEDIA"
12805   "mshfhi.l     %N2, %N1, %0"
12806   [(set_attr "type" "arith_media")])
12807
12808 (define_split
12809   [(set (match_operand:DI 0 "arith_reg_dest" "")
12810         (ior:DI (zero_extend:DI (match_operand:SI 1
12811                                               "extend_reg_or_0_operand" ""))
12812                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12813                         (const_int -4294967296))))
12814    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12815   "TARGET_SHMEDIA"
12816   [(const_int 0)]
12817   "
12818 {
12819   emit_insn (gen_ashldi3_media (operands[3],
12820                                 simplify_gen_subreg (DImode, operands[1],
12821                                                      SImode, 0),
12822                                 GEN_INT (32)));
12823   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12824   DONE;
12825 }")
12826
12827 (define_insn "mshflo_l_di"
12828   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12829         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12830                         (const_int 4294967295))
12831                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12832                            (const_int 32))))]
12833
12834   "TARGET_SHMEDIA"
12835   "mshflo.l     %N1, %N2, %0"
12836   [(set_attr "type" "arith_media")
12837    (set_attr "highpart" "ignore")])
12838
12839 (define_insn "*mshflo_l_di_rev"
12840   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12841         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12842                            (const_int 32))
12843                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12844                         (const_int 4294967295))))]
12845
12846   "TARGET_SHMEDIA"
12847   "mshflo.l     %N2, %N1, %0"
12848   [(set_attr "type" "arith_media")
12849    (set_attr "highpart" "ignore")])
12850
12851 ;; Combiner pattern for trampoline initialization.
12852 (define_insn_and_split "*double_shori"
12853   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12854         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12855                            (const_int 32))
12856                 (match_operand:DI 2 "const_int_operand" "n")))]
12857   "TARGET_SHMEDIA
12858    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12859   "#"
12860   "rtx_equal_p (operands[0], operands[1])"
12861   [(const_int 0)]
12862   "
12863 {
12864   HOST_WIDE_INT v = INTVAL (operands[2]);
12865
12866   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12867   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12868   DONE;
12869 }"
12870   [(set_attr "highpart" "ignore")])
12871
12872
12873 (define_insn "*mshflo_l_di_x"
12874   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12875         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12876                                  "rZ"))
12877                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12878                            (const_int 32))))]
12879
12880   "TARGET_SHMEDIA"
12881   "mshflo.l     %N1, %N2, %0"
12882   [(set_attr "type" "arith_media")
12883    (set_attr "highpart" "ignore")])
12884
12885 (define_insn_and_split "concat_v2sf"
12886   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12887 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12888         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12889                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12890
12891   "TARGET_SHMEDIA"
12892   "@
12893         mshflo.l        %N1, %N2, %0
12894         #
12895         #"
12896   "TARGET_SHMEDIA && reload_completed
12897    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12898   [(set (match_dup 3) (match_dup 1))
12899    (set (match_dup 4) (match_dup 2))]
12900   "
12901 {
12902   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12903   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12904 }"
12905   [(set_attr "type" "arith_media")
12906    (set_attr "highpart" "ignore")])
12907
12908 (define_insn "*mshflo_l_di_x_rev"
12909   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12910         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12911                            (const_int 32))
12912                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12913
12914   "TARGET_SHMEDIA"
12915   "mshflo.l     %N2, %N1, %0"
12916   [(set_attr "type" "arith_media")
12917    (set_attr "highpart" "ignore")])
12918
12919 (define_insn "ashlv2si3"
12920   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12921         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12922                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12923   "TARGET_SHMEDIA"
12924   "mshlld.l     %1, %2, %0"
12925   [(set_attr "type" "arith_media")
12926    (set_attr "highpart" "depend")])
12927
12928 (define_split
12929   [(set (match_operand 0 "any_register_operand" "")
12930         (match_operator 3 "shift_operator"
12931           [(match_operand 1 "any_register_operand" "")
12932            (match_operand 2 "shift_count_reg_operand" "")]))]
12933   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12934   [(set (match_dup 0) (match_dup 3))]
12935   "
12936 {
12937   rtx count = operands[2];
12938   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12939
12940   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12941          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12942          || GET_CODE (count) == TRUNCATE)
12943     count = XEXP (count, 0);
12944   inner_mode = GET_MODE (count);
12945   count = simplify_gen_subreg (outer_mode, count, inner_mode,
12946                                subreg_lowpart_offset (outer_mode, inner_mode));
12947   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12948                                 operands[1], count);
12949 }")
12950
12951 (define_insn "ashlv4hi3"
12952   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12953         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12954                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12955   "TARGET_SHMEDIA"
12956   "mshlld.w     %1, %2, %0"
12957   [(set_attr "type" "arith_media")
12958    (set_attr "highpart" "depend")])
12959
12960 (define_insn "lshrv2si3"
12961   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12962         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12963                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12964   "TARGET_SHMEDIA"
12965   "mshlrd.l     %1, %2, %0"
12966   [(set_attr "type" "arith_media")
12967    (set_attr "highpart" "depend")])
12968
12969 (define_insn "lshrv4hi3"
12970   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12971         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12972                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12973   "TARGET_SHMEDIA"
12974   "mshlrd.w     %1, %2, %0"
12975   [(set_attr "type" "arith_media")
12976    (set_attr "highpart" "depend")])
12977
12978 (define_insn "subv2si3"
12979   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12980         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12981                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12982   "TARGET_SHMEDIA"
12983   "msub.l       %N1, %2, %0"
12984   [(set_attr "type" "arith_media")
12985    (set_attr "highpart" "depend")])
12986
12987 (define_insn "subv4hi3"
12988   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12989         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12990                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12991   "TARGET_SHMEDIA"
12992   "msub.w       %N1, %2, %0"
12993   [(set_attr "type" "arith_media")
12994    (set_attr "highpart" "depend")])
12995
12996 (define_insn_and_split "subv2hi3"
12997   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12998         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12999                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
13000   "TARGET_SHMEDIA"
13001   "#"
13002   "TARGET_SHMEDIA"
13003   [(const_int 0)]
13004   "
13005 {
13006   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13007   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13008   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13009   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13010   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13011
13012   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
13013   emit_insn (gen_truncdisi2 (si_dst, di_dst));
13014   DONE;
13015 }"
13016   [(set_attr "highpart" "must_split")])
13017
13018 (define_insn "sssubv2si3"
13019   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13020         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
13021                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13022   "TARGET_SHMEDIA"
13023   "msubs.l      %N1, %2, %0"
13024   [(set_attr "type" "mcmp_media")
13025    (set_attr "highpart" "depend")])
13026
13027 (define_insn "ussubv8qi3"
13028   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13029         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
13030                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13031   "TARGET_SHMEDIA"
13032   "msubs.ub     %N1, %2, %0"
13033   [(set_attr "type" "mcmp_media")
13034    (set_attr "highpart" "depend")])
13035
13036 (define_insn "sssubv4hi3"
13037   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13038         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
13039                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13040   "TARGET_SHMEDIA"
13041   "msubs.w      %N1, %2, %0"
13042   [(set_attr "type" "mcmp_media")
13043    (set_attr "highpart" "depend")])
13044
13045 ;; Floating Point Intrinsics
13046
13047 (define_insn "fcosa_s"
13048   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13049         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
13050                    UNSPEC_FCOSA))]
13051   "TARGET_SHMEDIA"
13052   "fcosa.s      %1, %0"
13053   [(set_attr "type" "atrans_media")])
13054
13055 (define_insn "fsina_s"
13056   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13057         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
13058                    UNSPEC_FSINA))]
13059   "TARGET_SHMEDIA"
13060   "fsina.s      %1, %0"
13061   [(set_attr "type" "atrans_media")])
13062
13063 (define_insn "fipr"
13064   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13065         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
13066                                                     "fp_arith_reg_operand" "f")
13067                                                    (match_operand:V4SF 2
13068                                                     "fp_arith_reg_operand" "f"))
13069                                          (parallel [(const_int 0)]))
13070                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13071                                          (parallel [(const_int 1)])))
13072                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13073                                          (parallel [(const_int 2)]))
13074                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
13075                                          (parallel [(const_int 3)])))))]
13076   "TARGET_SHMEDIA"
13077   "fipr.s       %1, %2, %0"
13078   [(set_attr "type" "fparith_media")])
13079
13080 (define_insn "fsrra_s"
13081   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13082         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
13083                    UNSPEC_FSRRA))]
13084   "TARGET_SHMEDIA"
13085   "fsrra.s      %1, %0"
13086   [(set_attr "type" "atrans_media")])
13087
13088 (define_insn "ftrv"
13089   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
13090         (plus:V4SF
13091          (plus:V4SF
13092           (mult:V4SF
13093            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
13094                             (parallel [(const_int 0) (const_int 5)
13095                                        (const_int 10) (const_int 15)]))
13096            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
13097           (mult:V4SF
13098            (vec_select:V4SF (match_dup 1)
13099                             (parallel [(const_int 4) (const_int 9)
13100                                        (const_int 14) (const_int 3)]))
13101            (vec_select:V4SF (match_dup 2)
13102                             (parallel [(const_int 1) (const_int 2)
13103                                        (const_int 3) (const_int 0)]))))
13104          (plus:V4SF
13105           (mult:V4SF
13106            (vec_select:V4SF (match_dup 1)
13107                             (parallel [(const_int 8) (const_int 13)
13108                                        (const_int 2) (const_int 7)]))
13109            (vec_select:V4SF (match_dup 2)
13110                             (parallel [(const_int 2) (const_int 3)
13111                                        (const_int 0) (const_int 1)])))
13112           (mult:V4SF
13113            (vec_select:V4SF (match_dup 1)
13114                             (parallel [(const_int 12) (const_int 1)
13115                                        (const_int 6) (const_int 11)]))
13116            (vec_select:V4SF (match_dup 2)
13117                             (parallel [(const_int 3) (const_int 0)
13118                                        (const_int 1) (const_int 2)]))))))]
13119   "TARGET_SHMEDIA"
13120   "ftrv.s %1, %2, %0"
13121   [(set_attr "type" "fparith_media")])
13122
13123 (define_insn "ldhi_l"
13124   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13125         (zero_extract:SI
13126          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13127                                   (const_int 3))
13128                           (const_int -3)))
13129          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
13130          (const_int 0)))]
13131   "TARGET_SHMEDIA32"
13132   "ldhi.l       %U1, %0"
13133   [(set_attr "type" "load_media")])
13134
13135 (define_insn "ldhi_q"
13136   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13137         (zero_extract:DI
13138          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
13139                                   (const_int 7))
13140                           (const_int -7)))
13141          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
13142          (const_int 0)))]
13143   "TARGET_SHMEDIA32"
13144   "ldhi.q       %U1, %0"
13145   [(set_attr "type" "load_media")])
13146
13147 (define_insn_and_split "*ldhi_q_comb0"
13148   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13149         (zero_extract:DI
13150          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13151                                             "register_operand" "r")
13152                                            (match_operand:SI 2
13153                                             "ua_offset" "I06"))
13154                                   (const_int 7))
13155                           (const_int -7)))
13156          (plus:SI (and:SI (match_dup 1) (const_int 7))
13157                   (const_int 1))
13158          (const_int 0)))]
13159   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13160   "#"
13161   ""
13162   [(pc)]
13163   "emit_insn (gen_ldhi_q (operands[0],
13164                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13165    DONE;")
13166
13167
13168 (define_insn_and_split "*ldhi_q_comb1"
13169   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13170         (zero_extract:DI
13171          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
13172                                             "register_operand" "r")
13173                                            (match_operand:SI 2
13174                                             "ua_offset" "I06"))
13175                                   (const_int 7))
13176                           (const_int -7)))
13177          (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
13178                                                    "ua_offset" "I06"))
13179                           (const_int 7))
13180                   (const_int 1))
13181          (const_int 0)))]
13182   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13183    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13184   "#"
13185   ""
13186   [(pc)]
13187   "emit_insn (gen_ldhi_q (operands[0],
13188                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13189    DONE;")
13190
13191
13192 (define_insn "ldlo_l"
13193   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13194         (zero_extract:SI
13195          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13196                          (const_int -4)))
13197          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
13198          (and:SI (match_dup 1) (const_int 3))))]
13199   "TARGET_SHMEDIA32"
13200   "ldlo.l       %U1, %0"
13201   [(set_attr "type" "load_media")])
13202
13203 (define_insn "ldlo_q"
13204   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13205         (zero_extract:DI
13206          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
13207                          (const_int -8)))
13208          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13209          (and:SI (match_dup 1) (const_int 7))))]
13210   "TARGET_SHMEDIA32"
13211   "ldlo.q       %U1, %0"
13212   [(set_attr "type" "load_media")])
13213
13214 (define_insn_and_split "*ldlo_q_comb0"
13215   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13216         (zero_extract:DI
13217          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13218                                   (match_operand:SI 2 "ua_offset" "I06"))
13219                          (const_int -8)))
13220          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
13221          (and:SI (match_dup 1) (const_int 7))))]
13222   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
13223   "#"
13224   ""
13225   [(pc)]
13226   "emit_insn (gen_ldlo_q (operands[0],
13227                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13228    DONE;")
13229
13230 (define_insn_and_split "*ldlo_q_comb1"
13231   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13232         (zero_extract:DI
13233          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
13234                                   (match_operand:SI 2 "ua_offset" "I06"))
13235                          (const_int -8)))
13236          (minus:SI (const_int 8)
13237                    (and:SI (plus:SI (match_dup 1)
13238                                     (match_operand:SI 3 "ua_offset" "I06"))
13239                            (const_int 7)))
13240          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
13241   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
13242    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
13243   "#"
13244   ""
13245   [(pc)]
13246   "emit_insn (gen_ldlo_q (operands[0],
13247                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
13248    DONE;")
13249
13250 (define_insn "sthi_l"
13251   [(set (zero_extract:SI
13252          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13253                                   (const_int 3))
13254                           (const_int -3)))
13255          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
13256          (const_int 0))
13257         (match_operand:SI 1 "arith_reg_operand" "r"))]
13258   "TARGET_SHMEDIA32"
13259   "sthi.l       %U0, %1"
13260   [(set_attr "type" "ustore_media")])
13261
13262 ;; All unaligned stores are considered to be 'narrow' because they typically
13263 ;; operate on less that a quadword, and when they operate on a full quadword,
13264 ;; the vanilla store high / store low sequence will cause a stall if not
13265 ;; scheduled apart.
13266 (define_insn "sthi_q"
13267   [(set (zero_extract:DI
13268          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
13269                                   (const_int 7))
13270                           (const_int -7)))
13271          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13272          (const_int 0))
13273         (match_operand:DI 1 "arith_reg_operand" "r"))]
13274   "TARGET_SHMEDIA32"
13275   "sthi.q       %U0, %1"
13276   [(set_attr "type" "ustore_media")])
13277
13278 (define_insn_and_split "*sthi_q_comb0"
13279   [(set (zero_extract:DI
13280          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13281                                             "register_operand" "r")
13282                                            (match_operand:SI 1 "ua_offset"
13283                                             "I06"))
13284                                   (const_int 7))
13285                           (const_int -7)))
13286          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
13287          (const_int 0))
13288         (match_operand:DI 2 "arith_reg_operand" "r"))]
13289   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13290   "#"
13291   ""
13292   [(pc)]
13293   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13294                           operands[2]));
13295    DONE;")
13296
13297 (define_insn_and_split "*sthi_q_comb1"
13298   [(set (zero_extract:DI
13299          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
13300                                             "register_operand" "r")
13301                                            (match_operand:SI 1 "ua_offset"
13302                                             "I06"))
13303                                   (const_int 7))
13304                           (const_int -7)))
13305          (plus:SI (and:SI (plus:SI (match_dup 0)
13306                                    (match_operand:SI 2 "ua_offset" "I06"))
13307                           (const_int 7))
13308                   (const_int 1))
13309          (const_int 0))
13310         (match_operand:DI 3 "arith_reg_operand" "r"))]
13311   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13312    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13313   "#"
13314   ""
13315   [(pc)]
13316   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13317                           operands[3]));
13318    DONE;")
13319
13320 ;; This is highpart user because the address is used as full 64 bit.
13321 (define_insn "stlo_l"
13322   [(set (zero_extract:SI
13323          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13324                          (const_int -4)))
13325          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13326          (and:SI (match_dup 0) (const_int 3)))
13327         (match_operand:SI 1 "arith_reg_operand" "r"))]
13328   "TARGET_SHMEDIA32"
13329   "stlo.l       %U0, %1"
13330   [(set_attr "type" "ustore_media")])
13331
13332 (define_insn "stlo_q"
13333   [(set (zero_extract:DI
13334          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13335                          (const_int -8)))
13336          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13337          (and:SI (match_dup 0) (const_int 7)))
13338         (match_operand:DI 1 "arith_reg_operand" "r"))]
13339   "TARGET_SHMEDIA32"
13340   "stlo.q       %U0, %1"
13341   [(set_attr "type" "ustore_media")])
13342
13343 (define_insn_and_split "*stlo_q_comb0"
13344   [(set (zero_extract:DI
13345          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13346                                   (match_operand:SI 1 "ua_offset" "I06"))
13347                          (const_int -8)))
13348          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13349          (and:SI (match_dup 0) (const_int 7)))
13350         (match_operand:DI 2 "arith_reg_operand" "r"))]
13351   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13352   "#"
13353   ""
13354   [(pc)]
13355   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13356                           operands[2]));
13357    DONE;")
13358
13359 (define_insn_and_split "*stlo_q_comb1"
13360   [(set (zero_extract:DI
13361          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13362                                   (match_operand:SI 1 "ua_offset" "I06"))
13363                          (const_int -8)))
13364          (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13365                                                   (match_operand:SI 2
13366                                                    "ua_offset" "I06"))
13367                                          (const_int 7)))
13368          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13369         (match_operand:DI 3 "arith_reg_operand" "r"))]
13370   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13371   "#"
13372   ""
13373   [(pc)]
13374   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13375                           operands[3]));
13376    DONE;")
13377
13378 (define_insn "ldhi_l64"
13379   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13380         (zero_extract:SI
13381          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13382                                   (const_int 3))
13383                           (const_int -3)))
13384          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13385          (const_int 0)))]
13386   "TARGET_SHMEDIA64"
13387   "ldhi.l       %U1, %0"
13388   [(set_attr "type" "load_media")])
13389
13390 (define_insn "ldhi_q64"
13391   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13392         (zero_extract:DI
13393          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13394                                   (const_int 7))
13395                           (const_int -7)))
13396          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13397          (const_int 0)))]
13398   "TARGET_SHMEDIA64"
13399   "ldhi.q       %U1, %0"
13400   [(set_attr "type" "load_media")])
13401
13402 (define_insn "ldlo_l64"
13403   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13404         (zero_extract:SI
13405          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13406                          (const_int -4)))
13407          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13408          (and:DI (match_dup 1) (const_int 3))))]
13409   "TARGET_SHMEDIA64"
13410   "ldlo.l       %U1, %0"
13411   [(set_attr "type" "load_media")])
13412
13413 (define_insn "ldlo_q64"
13414   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13415         (zero_extract:DI
13416          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13417                          (const_int -8)))
13418          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13419          (and:DI (match_dup 1) (const_int 7))))]
13420   "TARGET_SHMEDIA64"
13421   "ldlo.q       %U1, %0"
13422   [(set_attr "type" "load_media")])
13423
13424 (define_insn "sthi_l64"
13425   [(set (zero_extract:SI
13426          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13427                                   (const_int 3))
13428                           (const_int -3)))
13429          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13430          (const_int 0))
13431         (match_operand:SI 1 "arith_reg_operand" "r"))]
13432   "TARGET_SHMEDIA64"
13433   "sthi.l       %U0, %1"
13434   [(set_attr "type" "ustore_media")])
13435
13436 (define_insn "sthi_q64"
13437   [(set (zero_extract:DI
13438          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13439                                   (const_int 7))
13440                           (const_int -7)))
13441          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13442          (const_int 0))
13443         (match_operand:DI 1 "arith_reg_operand" "r"))]
13444   "TARGET_SHMEDIA64"
13445   "sthi.q       %U0, %1"
13446   [(set_attr "type" "ustore_media")])
13447
13448 (define_insn "stlo_l64"
13449   [(set (zero_extract:SI
13450          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13451                          (const_int -4)))
13452          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13453          (and:DI (match_dup 0) (const_int 3)))
13454         (match_operand:SI 1 "arith_reg_operand" "r"))]
13455   "TARGET_SHMEDIA64"
13456   "stlo.l       %U0, %1"
13457   [(set_attr "type" "ustore_media")])
13458
13459 (define_insn "stlo_q64"
13460   [(set (zero_extract:DI
13461          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13462                          (const_int -8)))
13463          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13464          (and:DI (match_dup 0) (const_int 7)))
13465         (match_operand:DI 1 "arith_reg_operand" "r"))]
13466   "TARGET_SHMEDIA64"
13467   "stlo.q       %U0, %1"
13468   [(set_attr "type" "ustore_media")])
13469
13470 (define_insn "nsb"
13471   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13472         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13473                    UNSPEC_NSB))]
13474   "TARGET_SHMEDIA"
13475   "nsb  %1, %0"
13476   [(set_attr "type" "arith_media")])
13477
13478 (define_insn "nsbsi"
13479   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13480         (zero_extend:SI
13481          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13482                     UNSPEC_NSB)))]
13483   "TARGET_SHMEDIA"
13484   "nsb  %1, %0"
13485   [(set_attr "type" "arith_media")])
13486
13487 (define_insn "nsbdi"
13488   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13489         (zero_extend:DI
13490          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13491                     UNSPEC_NSB)))]
13492   "TARGET_SHMEDIA"
13493   "nsb  %1, %0"
13494   [(set_attr "type" "arith_media")])
13495
13496 (define_expand "ffsdi2"
13497   [(set (match_operand:DI 0 "arith_reg_dest" "")
13498         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13499   "TARGET_SHMEDIA"
13500   "
13501 {
13502   rtx scratch = gen_reg_rtx (DImode);
13503   rtx last;
13504
13505   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13506   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13507   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13508   emit_insn (gen_nsbdi (scratch, scratch));
13509   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13510   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13511   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13512   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
13513
13514   DONE;
13515 }")
13516
13517 (define_expand "ffssi2"
13518   [(set (match_operand:SI 0 "arith_reg_dest" "")
13519         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13520   "TARGET_SHMEDIA"
13521   "
13522 {
13523   rtx scratch = gen_reg_rtx (SImode);
13524   rtx discratch = gen_reg_rtx (DImode);
13525   rtx last;
13526
13527   emit_insn (gen_adddi3 (discratch,
13528                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
13529                          constm1_rtx));
13530   emit_insn (gen_andcdi3 (discratch,
13531                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
13532                           discratch));
13533   emit_insn (gen_nsbsi (scratch, discratch));
13534   last = emit_insn (gen_subsi3 (operands[0],
13535                                 force_reg (SImode, GEN_INT (63)), scratch));
13536   set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
13537
13538   DONE;
13539 }")
13540
13541 (define_insn "byterev"
13542   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13543         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13544                          (parallel [(const_int 7) (const_int 6) (const_int 5)
13545                                     (const_int 4) (const_int 3) (const_int 2)
13546                                     (const_int 1) (const_int 0)])))]
13547   "TARGET_SHMEDIA"
13548   "byterev      %1, %0"
13549   [(set_attr "type" "arith_media")])
13550
13551 (define_insn "*prefetch_media"
13552   [(prefetch (match_operand:QI 0 "address_operand" "p")
13553              (match_operand:SI 1 "const_int_operand" "n")
13554              (match_operand:SI 2 "const_int_operand" "n"))]
13555   "TARGET_SHMEDIA"
13556   "*
13557 {
13558   operands[0] = gen_rtx_MEM (QImode, operands[0]);
13559   output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
13560   return \"\";
13561 }"
13562   [(set_attr "type" "other")])
13563
13564 (define_insn "*prefetch_i4"
13565   [(prefetch (match_operand:SI 0 "register_operand" "r")
13566              (match_operand:SI 1 "const_int_operand" "n")
13567              (match_operand:SI 2 "const_int_operand" "n"))]
13568   "TARGET_HARD_SH4 || TARGET_SHCOMPACT"
13569   "*
13570 {
13571   return \"pref @%0\";
13572 }"
13573   [(set_attr "type" "other")])
13574
13575 (define_expand "prefetch"
13576   [(prefetch (match_operand 0 "address_operand" "p")
13577              (match_operand:SI 1 "const_int_operand" "n")
13578              (match_operand:SI 2 "const_int_operand" "n"))]
13579   "TARGET_HARD_SH4 || TARGET_SH5"
13580   "
13581 {
13582   if (GET_MODE (operands[0]) != Pmode
13583       || GET_CODE (operands[1]) != CONST_INT
13584       || GET_CODE (operands[2]) != CONST_INT)
13585     FAIL;
13586   if (! TARGET_SHMEDIA)
13587     operands[0] = force_reg (Pmode, operands[0]);
13588 }")
13589
13590 (define_insn "alloco_i"
13591   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13592         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13593   "TARGET_SHMEDIA32"
13594   "*
13595 {
13596   rtx xops[2];
13597
13598   if (GET_CODE (operands[0]) == PLUS)
13599     {
13600       xops[0] = XEXP (operands[0], 0);
13601       xops[1] = XEXP (operands[0], 1);
13602     }
13603   else
13604     {
13605       xops[0] = operands[0];
13606       xops[1] = const0_rtx;
13607     }
13608   output_asm_insn (\"alloco   %0, %1\", xops);
13609   return \"\";
13610 }"
13611   [(set_attr "type" "other")])
13612
13613 (define_split
13614   [(set (match_operand 0 "any_register_operand" "")
13615         (match_operand 1 "" ""))]
13616   "TARGET_SHMEDIA && reload_completed"
13617   [(set (match_dup 0) (match_dup 1))]
13618   "
13619 {
13620   int n_changes = 0;
13621
13622   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13623   if (!n_changes)
13624     FAIL;
13625 }")
13626
13627 ; Stack Protector Patterns
13628
13629 (define_expand "stack_protect_set"
13630   [(set (match_operand 0 "memory_operand" "")
13631         (match_operand 1 "memory_operand" ""))]
13632   ""
13633 {
13634   if (TARGET_SHMEDIA)
13635     {
13636       if (TARGET_SHMEDIA64)
13637         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13638       else
13639         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13640     }
13641   else
13642     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13643
13644   DONE;
13645 })
13646
13647 (define_insn "stack_protect_set_si"
13648   [(set (match_operand:SI 0 "memory_operand" "=m")
13649         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13650    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13651   "!TARGET_SHMEDIA"
13652   "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13653   [(set_attr "type" "other")
13654    (set_attr "length" "6")])
13655
13656 (define_insn "stack_protect_set_si_media"
13657   [(set (match_operand:SI 0 "memory_operand" "=m")
13658         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13659    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13660   "TARGET_SHMEDIA"
13661   "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13662   [(set_attr "type" "other")
13663    (set_attr "length" "12")])
13664
13665 (define_insn "stack_protect_set_di_media"
13666   [(set (match_operand:DI 0 "memory_operand" "=m")
13667         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13668    (set (match_scratch:DI 2 "=&r") (const_int 0))]
13669   "TARGET_SHMEDIA64"
13670   "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13671   [(set_attr "type" "other")
13672    (set_attr "length" "12")])
13673
13674 (define_expand "stack_protect_test"
13675   [(match_operand 0 "memory_operand" "")
13676    (match_operand 1 "memory_operand" "")
13677    (match_operand 2 "" "")]
13678   ""
13679 {
13680   if (TARGET_SHMEDIA)
13681     {
13682       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13683
13684       if (TARGET_SHMEDIA64)
13685         emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13686                                                     operands[1]));
13687       else
13688         emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13689                                                     operands[1]));
13690
13691       emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx));
13692     }
13693   else
13694     {
13695       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13696       emit_jump_insn (gen_branch_true (operands[2]));
13697     }
13698
13699   DONE;
13700 })
13701
13702 (define_insn "stack_protect_test_si"
13703   [(set (reg:SI T_REG)
13704         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13705                     (match_operand:SI 1 "memory_operand" "m")]
13706                    UNSPEC_SP_TEST))
13707   (set (match_scratch:SI 2 "=&r") (const_int 0))
13708   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13709   "!TARGET_SHMEDIA"
13710   "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13711   [(set_attr "type" "other")
13712    (set_attr "length" "10")])
13713
13714 (define_insn "stack_protect_test_si_media"
13715   [(set (match_operand:SI 0 "register_operand" "=&r")
13716         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13717                     (match_operand:SI 2 "memory_operand" "m")]
13718                    UNSPEC_SP_TEST))
13719   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13720   "TARGET_SHMEDIA"
13721   "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13722   [(set_attr "type" "other")
13723    (set_attr "length" "16")])
13724
13725 (define_insn "stack_protect_test_di_media"
13726   [(set (match_operand:DI 0 "register_operand" "=&r")
13727         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13728                     (match_operand:DI 2 "memory_operand" "m")]
13729                    UNSPEC_SP_TEST))
13730   (set (match_scratch:DI 3 "=&r") (const_int 0))]
13731   "TARGET_SHMEDIA64"
13732   "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13733   [(set_attr "type" "other")
13734    (set_attr "length" "16")])